【问题标题】:How would I save multiple records at once in Rails?如何在 Rails 中一次保存多条记录?
【发布时间】:2013-10-05 13:02:46
【问题描述】:

如何使用 Rails 在一次调用中保存这个数组?

tax_rates = [{
  :income_from => 0
  :income_to  => 18200
  :start => "01-07-2013"
  :finish => "30-06-2014"
  :rate => nil
  :premium => nil
  },{
  :income_from => 18201
  :income_to  => 37000
  :start => "01-07-2013"
  :finish => "30-06-2014"
  :rate => 0.19
  :premium => nil
  },{
    :income_from => 18201
    :income_to  => 37000
    :start => "01-07-2013"
    :finish => "30-06-2014"
    :rate => 0.19
    :premium => nil
    }]

我可以打电话给Rails.create(tax_rates)吗?

另外,有没有办法去除重复的符号,让它们看起来更整洁?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    你的例子几乎是正确的。

    使用ActiveRecord::Persistence#create,它可以接受一个哈希数组作为参数。

    tax_rates = [
      {
        income_from: 0,
        income_to: 18200,
        start: "01-07-2013",
        finish: "30-06-2014",
        rate: nil,
        premium: nil,
      },
      {
        income_from: 18201,
        income_to: 37000,
        start: "01-07-2013",
        finish: "30-06-2014",
        rate: 0.19,
        premium: nil,
      },
      # ...
    ]
    
    TaxRate.create(tax_rates)  # Or `create!` to raise if validations fail
    

    【讨论】:

    • 这对我不起作用。我可以保存哈希,但使用“!”忽略验证或没有。你是怎么做到的?
    【解决方案2】:

    一个不错的解决方案是使用active record import gem。我现在推荐它而不是内置的 Rails 批量插入,因为在违反约束的情况下,它的选项更加灵活。

    TaxRate.import(
      [:income_from, :income_to, :start, :finish, :rate, :premium],
      tax_rates
    )
    

    它绝对比我的旧答案更好,它会触发数组中每个条目的数据库提交:)


    旧答案:

    tax_rates.map {|tax_rate| TaxRate.new(tax_rate).save } 
    

    这样您将检索一个带有truefalse 的数组,以了解哪个成功,哪个没有成功。

    【讨论】:

    • 这很有帮助,但是如果我也有索引怎么办 比如:{"0":{ :income_from => 0.....},"1":{ :income_from => 18201.. .},"2":{}...}
    • 我得到了解决方案,只需使用 'index' --> |index, tax_rate|。
    • 只有我需要在最后删除 .save ,因为它以某种方式在表中保存了双精度值。
    • 太糟糕了。这将为每个插入生成一个新查询。
    • @DamienRoche 感谢您的跟进。我们正在评估 Active Record 导入 gem 的使用,因此需要知道它是否是单个 INSERT。我们今天早上开始使用它,事实上,它确实使用了一个 INSERT。再次感谢。
    【解决方案3】:

    如果您希望所有这些都被保存。或者即使一个失败也不保存它们,您可以使用 'ActiveRecord::Base.transaction'

    例如

    ActiveRecord::Base.transaction do  
       tax_rate.each do |tax_rt|  
           TaxRate.new(tax_rt).save  
        end
     end
    

    【讨论】:

      【解决方案4】:

      我不确定rails

      TaxRate.create(tax_rt)
      

      【讨论】:

        【解决方案5】:

        这是一个像你这样的例子:

        a = []
        
        a << B.new(:name => "c")
        a << B.new(:name => "s")
        a << B.new(:name => "e")
        a << B.new(:name => "t")
        

        数组一次性保存:

        a.each(&:save)
        

        这将对数组中的每个项目调用B#save

        【讨论】:

        • 此解决方案生成多个INSERT 调用。这不是 OP 要求的
        【解决方案6】:

        使用 gem 'fast_inserter':https://github.com/joinhandshake/fast_inserter

        它生成一个包含数千条记录的 sql 查询。

        movie_data = [1, 'Climates (Iklimler)', 'Clay Pauwel', 'Drama'],
                  [2, 'Tinpis Run', 'Andros Glazer', 'Comedy'],
                  [3, 'Naked City, The', 'Bethena Chatband', 'Mystery'],
                  [4, 'Small Time Crooks', 'Naomi Plom', 'Crime'],
                  [5, 'Shadowboxer', 'Georgeanne Widdicombe', 'Thriller']
        
            params = {
              table: 'movies',
                static_columns: {
                  created_at: '0000-00-00 00:00:00',
                  updated_at: '0000-00-00 00:00:00',
                },
              options: {
                timestamps: false,
                unique: true,
                check_for_existing: true
              },
                group_size: 100,
                variable_columns: %w(id title director description),
                values: movie_data
            }
            inserter = FastInserter::Base.new(params)
            inserter.fast_insert
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-10
          相关资源
          最近更新 更多