rails find_or_initialize更新或创建大量记录

时间:2013-09-20 18:55:20

标签: performance postgresql activerecord ruby-on-rails-3.2 shopify

在我们的Rails 3.2.13应用程序中,我们需要查询具有许多关联对象的Order数据的API,然后将其存储在我们的数据库中。有些记录可能已经存在,所以如果它们存在,我们想要更新,如果是新的,那么我们想要创建。我们一次导入数千条记录。

我一直在调查activerecord-import gem,以帮助使用import方法对性能进行优化,并提出以下代码:

def add_details(order, tax_lines)
  tax_lines.each do |shopify_tax_line|
    taxlines_updated << Taxline.where(:order_id => order.id).first_or_initialize(
      :price => tax_line.price,
      :rate => tax_line.rate,
      :title => tax_line.title)
  end
  Taxline.import taxlines_updated, :validate => false
end

问题是,如果记录已经存在,那么它不会更新,它只会在记录是新的时更新属性。

我怎样才能让它像以下一样工作:“如果找到 - >更新属性”或“如果找不到 - >新”在每条记录上?

非常感谢!

3 个答案:

答案 0 :(得分:0)

雅。 first_or_initialize以这种方式工作。在first_or_initialize之后尝试update_attributes。

  

Taxline.where(:order_id =&gt;   order.id).first_or_initialize.update_attributes!(         :price =&gt; tax_line.price,:rate =&gt; tax_line.rate,:title =&gt; tax_line.title)

答案 1 :(得分:0)

:synchronize选项可能有效

 def add_details(order, tax_lines)
      taxlines_updated = []
      tax_lines.each do |shopify_tax_line|
        taxlines_updated << Taxline.where(:order_id => order.id).first_or_initialize(
               :price => tax_line.price,
               :rate => tax_line.rate,
                :title => tax_line.title)
      end
      Taxline.import taxlines_updated, :validate => false, :synchronize => taxlines_updated
  end

对于宝石docs

    # * +synchronize+ - an array of ActiveRecord instances for the model
    # that you are currently importing data into. This synchronizes
    # existing model instances in memory with updates from the import.

答案 2 :(得分:0)

这是我们最终使用的代码,可能不是最有效的代码,但它有效:

def add_details(shopify_orders)
    tax_lines = []
    shopify_orders.each do |shopify_order|
      shopify_order.tax_lines.each do |shopify_tax_line|
        tax_line = Taxline.where(:order_id => shopify_order.id).first_or_initialize
        tax_line.price = shopify_tax_line.price
        tax_line.rate = shopify_tax_line.rate
        tax_line.title = shopify_tax_line.title
        tax_lines << tax_line
      end
    end
    TaxLine.import tax_lines, :validate => false
end