2011-03-04 40 views
9

據我所知,build方法可用於在保存之前建立關聯記錄的集合。然後,在撥打save時,所有的子記錄都將被驗證並保存,如果存在驗證錯誤,則父記錄會有一個反映此錯誤的錯誤。第一個問題是,這是正確的嗎?Rails:一次保存更新記錄的集合

但我的主要問題是,假設上述是有效的,是否有可能對更新做同樣的事情,而不是創建?換句話說,是否有辦法更新與父記錄相關聯的集合中的多個記錄,然後保存父記錄並一次發生所有更新(如果在子級中存在驗證錯誤,則在父級中出現錯誤)?所以總而言之,我想知道正確的方法來處理一個父記錄和幾個關聯的子記錄需要一次更新和保存的情況,任何錯誤都會中止整個保存過程。

+7

只有一個建議。你也可以將你的代碼包裝在ActiveRecord :: Transaction 中,並使用.save!而不是保存。 如果處理異常,Activerecord將回滾任何更改。 http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html – andrea 2011-03-08 11:45:25

+0

@andrea這是一個非常有趣的方法。可能對許多事情有用。 – bowsersenior 2011-03-08 18:09:34

回答

6

首先+1到@andrea爲Transactions - 很酷的東西,我不知道

但最簡單的華麗在這裏,要去使用accepts_nested_attributes_formethod爲模型。

讓我們舉個例子。我們有兩種型號: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 

太棒了!一切正常。

現在讓我們用更新做同樣的事情:

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_fortag爲關聯的看法。此外,您可以使用非常深的嵌套與您的驗證聯繫在一起,它將起到完美的作用。