据我了解,可以在保存之前使用build
方法建立关联记录的集合。然后,在调用save
时,将验证并保存所有子记录,并且如果存在验证错误,则父记录将具有反射(reflect)此情况的错误。第一个问题是,这是正确的吗?
但是我的主要问题是,假设以上内容是有效的,是否可以通过更新而不是创建相同的操作?换句话说,有没有一种方法可以更新与父记录相关联的集合中的几条记录,然后保存父记录并使所有更新一次发生(如果子代中存在验证错误,则父代中会出现错误) )?
编辑:因此,总而言之,我想知道一种正确的方法来处理一个父记录和几个关联的子记录需要立即更新并保存的情况,而任何错误都会中止整个保存过程。
最佳答案
首先向@andrea +1以获得Transactions
-我不知道的好东西
但是,最简单的方法是将accepts_nested_attributes_for
method用于模型。
让我们举个例子。我们有两种模型:Post title:string
和Comment 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"]}>
这行得通!
因此,您将如何使用它。在您的模型中,使用相同的方式,在 View 中,例如常见的表单,但使用
fields_for
tag进行关联。您也可以对验证与关联使用非常深层的嵌套,它可以完美地发挥作用。
关于ruby-on-rails - 一次保存所有更新记录的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5200235/