activemodel - 保存父节点时更新对象的子节点

时间:2013-08-07 19:44:19

标签: ruby-on-rails activerecord

这是我的问题的后续跟进: Updating child association in 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

2 个答案:

答案 0 :(得分:2)

您想要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

答案 1 :(得分:0)

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

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个记录,但你没有提到它,可能不会起作用。