【问题标题】:Rails/ActiveRecord: save changes to a model's associated collectionsRails/ActiveRecord:保存对模型关联集合的更改
【发布时间】:2009-05-15 17:15:25
【问题描述】:

我是否必须为模型保存对集合中单个项目的修改,或者在保存模型时我可以调用一种方法来保存它们。

#save 似乎没有这样做。例如:

irb> rental = #...
#=> #<Rental id: 18737, customer_id: 61, dvd_id: 3252, date_rented: "2008-12-16 05:00:00", date_shipped: "2008-12-16 05:00:00", date_returned: "2008-12-22 05:00:00">
irb> rental.dvd
#=> #<Dvd id: 3252, title: "The Women of Summer", year: 1986, copies: 20, is_new: false, is_discontinued: false, list_price: #<BigDecimal:1a48f0c,'0.1599E2',8(8)>, sale_price: #<BigDecimal:1a48ed0,'0.1599E2',8(8)>>
irb> rental.dvd.copies += 1
#=> 21
irb> rental.save
#=> true
irb> rental.dvd
#=> #<Dvd id: 3252, title: "The Women of Summer", year: 1986, copies: 21, is_new: false, is_discontinued: false, list_price: #<BigDecimal:1a2e9cc,'0.1599E2',8(8)>, sale_price: #<BigDecimal:1a2e97c,'0.1599E2',8(8)>>
irb> Dvd.find_by_title('The Women of Summer')
#=> #<Dvd id: 3252, title: "The Women of Summer", year: 1986, copies: 20, is_new: false, is_discontinued: false, list_price: #<BigDecimal:1a30164,'0.1599E2',8(8)>, sale_price: #<BigDecimal:1a30128,'0.1599E2',8(8)>>

在上面的示例中,租用的 DVD 副本似乎没有更新 DB 中的副本(请注意副本数量不同)。

【问题讨论】:

    标签: ruby-on-rails ruby activerecord


    【解决方案1】:

    您可以通过在声明关联时添加 :autosave =&gt; true 选项来配置 ActiveRecord 以级联保存对模型集合中项目的更改。 Read more.

    例子:

    class Payment < ActiveRecord::Base
        belongs_to :cash_order, :autosave => true
        ...
    end
    

    【讨论】:

      【解决方案2】:

      在你增加值后做一个rental.dvd.save,或者在上述情况下你可以使用

      rental.dvd.increment!(:copies)
      

      它也会自动保存,注意'!'递增!

      【讨论】:

        【解决方案3】:

        你必须自己做这个

        这并不完全正确。您可以使用强制保存的“构建”方法。举例来说,假设您有一个公司模型和员工(公司 has_many 员工)。你可以这样做:

        acme = Company.new({:name => "Acme, Inc"})
        acme.employees.build({:first_name => "John"})
        acme.employees.build({:first_name => "Mary"})
        acme.employees.build({:first_name => "Sue"})
        acme.save
        

        将创建所有 4 条记录,即 Company 记录和 3 条 Employee 记录,并且 company_id 将被适当地推送到 Employee 对象。

        【讨论】:

        • 您指的是创建新模型;您引用的问题和答案是指在现有模型上保存更改。
        • 需要注意的是,这只适用于新模型实例。
        【解决方案4】:

        你必须自己做。 Active Record does not cascade save operations in has_many relations after the initial save.

        您可以使用before_save 回调自动执行该过程。

        【讨论】:

        • 我喜欢 before_save 回调的想法,但我担心爆炸性递归 - 我这里的另一个场景是客户和 dvd 都有很多租借,所以我可以这样做,比如 customer.rentals。我担心 first.dvd.rentals.first.customer 和级联 before_saves 可能会有点失控。
        【解决方案5】:

        这篇文章很有用: http://erikonrails.snowedin.net/?p=267

        Erik 描述了如何在模型中使用“accepts_nested_attributes_for”并在视图中使用 来完成这项工作。

        其详细说明见: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-16
          • 1970-01-01
          • 2014-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多