Rails:一次保存更新记录的集合

时间:2011-03-04 23:04:14

标签: ruby-on-rails validation collections build associations

据我了解,build方法可用于在保存之前建立相关记录的集合。然后,当调用save时,将验证并保存所有子记录,如果存在验证错误,则父记录将出现反映此错误的错误。第一个问题是,这是正确的吗?

但我的主要问题是,假设上述内容有效,是否可以对更新执行相同的操作,而不是创建?换句话说,有没有办法更新与父记录关联的集合中的多个记录,然后保存父记录并立即进行所有更新(如果子项中存在验证错误,则在父项中出现错误) )?

编辑:总而言之,我想知道正确的方法来处理父记录和几个相关子记录需要一次更新和保存的情况,任何错误都会中止整个保存过程。

2 个答案:

答案 0 :(得分:7)

首先给Transactions的@andrea +1 - 我不知道的很酷的东西

但最简单的方法是使用accepts_nested_attributes_for method作为模型。

让我们举个例子。我们有两个模型:Post title:stringComment body:string post:references

让我们看看模型:

class Post < ActiveRecord::Base
  has_many :comments
  validates :title, :presence => true
  accepts_nested_attributes_for :comments # this is our hero
end

class Comment < ActiveRecord::Base
  belongs_to :post
  validates :body, :presence => true
end

你看:我们在这里得到了一些验证。所以我们去rails console做一些测试:

post = Post.new
post.save
#=> false
post.errors
#=> #<OrderedHash {:title=>["can't be blank"]}>
post.title = "My post title"
# now the interesting: adding association
# one comment is ok and second with __empty__ body
post.comments_attributes = [{:body => "My cooment"}, {:body => nil}]
post.save
#=> false
post.errors
#=> #<OrderedHash {:"comments.body"=>["can't be blank"]}>
# Cool! everything works fine
# let's now cleean our comments and add some new valid
post.comments.destroy_all
post.comments_attributes = [{:body => "first comment"}, {:body => "second comment"}]
post.save
#=> true

大!一切正常。

现在让我们使用 update 执行相同的操作:

post = Post.last
post.comments.count # We have got already two comments with ID:1 and ID:2
#=> 2
# Lets change first comment's body
post.comments_attributes = [{:id => 1, :body => "Changed body"}] # second comment isn't changed
post.save
#=> true
# Now let's check validation
post.comments_attributes => [{:id => 1, :body => nil}]
post.save
#=> false
post.errors
#=> #<OrderedHash {:"comments.body"=>["can't be blank"]}>

这有效!

那你怎么用呢。在您的模型中使用相同的方式,在视图中使用常见表单,但使用fields_for tag进行关联。此外,您可以使用非常深的嵌套来与验证相关联,并且它将完美运行。

答案 1 :(得分:1)

尝试在validates_associated :some_child_records课程中使用Patient

如果您只希望在更新时发生这种情况,请使用:onvalidates_associated :some_child_records, :on => :update选项

更多信息: