簡體   English   中英

從數組哈希中在ruby中創建多個記錄

[英]Creating multiple records in ruby from a hash of arrays

我有一個由哈希內的數組哈希組成的響應。 我需要在ruby / rails中創建三個記錄(見下文)。

{
    "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

我在了解如何解決此問題時遇到困難。 任何幫助將不勝感激。

到目前為止,我有:

response.keys.each do |field_name|
  response[field_name].each do |value|
     puts "#{field_name} => #{value}"
     User.create!(
       first_name: value['first_name'],
       last_name: value['last_name'],
       email:  value['email']
     )
  end
end

像這樣的方法怎么樣?

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條記錄,這並不是什么大問題,但是如果您要處理更多的記錄,可以考慮對其進行優化。

只要保證數組的長度相同,並且順序不變,就可以執行以下操作:

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)}

就這么簡單:

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

response.values將給我們一個數組數組(每個字段的字段值數組),並且transpose將其翻轉,因此我們有了記錄數組。 然后,對於每條記錄,只需添加字段名稱,進行哈希化並傳遞給#create!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM