5

这是我的问题的后续行动: 在 ActiveModel 中更新子关联

我正在寻找标准/正确的方法来更新与父母相关的许多子记录。

假设我有一个父级(使用 has_many 连接到一个子表,并且:autosave=>true)。

obj = Parent.first

现在我迭代它的孩子,并更新它们。

obj.each.do |child|
    child.remark = "something"
end

我希望在调用 obj.save 时将孩子与父母一起保存,但正如在上一个问题中向我解释的那样,唯一的方法是直接更新它,如下所示:

obj.children.first.remark = "something"

(或保存每个孩子,但这需要一个明确的交易,我认为不应该在这里使用)。

实现这一点的正确方法是什么?

谢谢!

*编辑:按照此处给出的建议,我已将其添加到模型中:

class Parent < ActiveRecord::Base

     has_many :children, :inverse_of => :parent,:autosave=>true

     accepts_nested_attributes_for :children

但还是,

x = Parent.first
c = x.children.first
c.remark = "something"
x.save    # => doesn't update c
4

2 回答 2

3

你想要 ActiveRecord nested_attributes

class Parent
  include ActiveModel::Model

  accepts_nested_attributes_for :children
end

更新你的孩子并保存父母,你应该完成

编辑:你必须先打电话parent.children

irb(main):001:0> x = Parent.first
  Parent Load (0.3ms)  SELECT "parents".* FROM "parents" ORDER BY "parents"."id" ASC LIMIT 1
=> #<Parent id: 1, created_at: "2013-08-07 21:21:10", updated_at: "2013-08-07 21:21:10">
irb(main):002:0> x.children
  Child Load (3.0ms)  SELECT "children".* FROM "children" WHERE "children"."parent_id" = ?  [["parent_id", 1]]
=> #<ActiveRecord::Associations::CollectionProxy [ ]>
irb(main):003:0> x.children.first.remark = "foo"
=> "foo"
irb(main):004:0> x.save
   (0.3ms)  begin transaction
  SQL (2.3ms)  UPDATE "children" SET "remark" = ?, "updated_at" = ? WHERE "children"."id" = 1  [["remark", "foo"], ["updated_at", Wed, 07 Aug 2013 21:33:04 UTC +00:00]]
   (0.3ms)  commit transaction
=> true
于 2013-08-07T20:35:13.300 回答
1

您可以覆盖保存方法,但我不会这样做。为什么不做这样的事情?

def save_with_children
  Child.transaction do
    children.each do |child|
      if child.changed?
        child.save
      end
    end
  end
  save
end

这应该运行 1 个查询。如果你有 10'000'000 条记录,但你没有提到这一点,可能不会工作。

于 2013-08-07T21:13:34.217 回答