从数组哈希中在ruby中创建多个记录

时间:2018-08-27 02:41:26

标签: ruby-on-rails ruby rails-activerecord

我有一个响应,其中包含哈希中的数组哈希。我需要在ruby / rails中创建三个记录(见下文)。

density

我在理解如何解决这个问题上遇到困难。任何帮助将不胜感激。

到目前为止,我有:

{
    "first_name" => [John, Tom, Michael],
    "last_name" => [Smith, Watts, Pit],
    "email" => [John.smith@gmail.com, tom.watts@gmail.com,  mike.pit@gmail.com]
}

id  || first_name   || last_name  || email
----------------------------------------------
1   || John         ||  Smith     || john.smith@gmail.com
2   || Tom          ||  Watts     || tom.watts@gmail.com
3   || Michael      ||  Pit       || mike.pit@gmail.com

3 个答案:

答案 0 :(得分:0)

如何处理-

def create_records_from_responses!(responses)
  items = responses.values.first.length
  fields = responses.keys
  users = []

  # Don't process an empty set
  return if items.zero?

  # Wrap creation of User objects in a transaction
  # If one fails, it rolls back all created records
  # As per transaction documentation, you still have to manually
  # handle the propagated error
  # See: https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
  # In this case we named the method with a `!` to indicate that it might raise
  # an error. Whatever is calling this should rescue and handle the error

  ActiveRecord::Base.transaction do
    (0..items).each do |i|
      attributes = {}
      fields.each { |field| attributes[field] = responses[field][i] }

      users << User.create!(attributes)
    end
  end

  users

这有2个假设-

  1. 您的responses哈希格式正确。如果每个键都有不匹配的数组,则可能会出错。您应该事先验证其格式

  2. 您正在创建的用户数量并不多。如您所见,它在每个循环中重建attributes。如果记录是10到20条,这不是什么大问题,但是如果您要处理更多的记录,可以考虑对其进行优化。

答案 1 :(得分:0)

只要保证数组的长度相同,并且顺序不变,就可以执行以下操作:

data = {
  first_name: ["John", "Tom", "Michael"],
  last_name: ["Smith", "Watts","Pit"],
  email: ["John.smith@gmail.com", "tom.watts@gmail.com",  "mike.pit@gmail.com"]
}

0.upto(data[:first_name].length-1) do |i|
  record = {
    first_name: data[:first_name][i],
    last_name: data[:last_name][i],
    email: data[:email][i]
  }
  User.create!(record)
end

您也可以对.zip和.each_slice感到疯狂,尽管我认为以上内容更加简单明了。

maxlen = data[:first_name].length
first_name_fields = Array.new(maxlen, 'first_name')
last_name_fields = Array.new(maxlen, 'last_name')
email_fields = Array.new(maxlen, 'email')
records = first_name_fields.zip(data[:first_name], last_name_fields, data[:last_name], email_fields, data[:email])
records.map!{|x| x.each_slice(2).to_a.to_h}
records.each{|record| User.create!(record)}

答案 2 :(得分:0)

就这么简单:

response.values.transpose.each { |record|
  User.create!(data.keys.zip(record).to_h)
}

response.values将给我们一个数组数组(每个字段的字段值数组),而transpose将其翻转过来,以便我们有记录数组。然后,对于每条记录,只需添加字段名称,进行哈希化并传递到#create!