如果一条记录无效,Rails accepts_nested_attributes_for 将不保存嵌套记录 [英] Rails accepts_nested_attributes_for saves no nested records if one record is invalid
问题描述
如果其中一条记录未通过验证,则创建具有嵌套关联的记录将无法保存任何关联记录.
Creating a record with nested associations fails to save any of the associated records if one of the records fails validations.
class Podcast < ActiveRecord::Base
has_many :episodes, inverse_of: :podcast
accepts_nested_attributes_for :episodes
end
class Episode < ActiveRecord::Base
belongs_to :podcast, inverse_of: :episodes
validates :podcast, :some_attr, presence: true
end
# Creates a podcast with one episode.
case_1 = Podcast.create {
title: 'title'
episode_attributes: [
{title: "ep1", some_attr: "some_attr"}, # <- Valid Episode
]
}
# Creates a podcast without any episodes.
case_2 = Podcast.create {
title: 'title'
episode_attributes: [
{title: "ep1", some_attr: "some_attr"}, # <- Valid Episode
{title: "ep2"} # <- Invalid Episode
]
}
我希望 case_1
能够成功保存一个创建的剧集.我希望 case_2
做两件事之一:
I'd expect case_1
to save successfully with one created episode.
I'd expect case_2
to do one of two things:
- 保存一集
- 由于验证错误而无法保存.
取而代之的是播客保存,但两集都没有保存.
Instead the podcast saves but neither episode does.
我希望播客与保存的任何有效剧集一起保存.
I'd like the podcast to save with any valid episode saved as well.
我想通过将接受嵌套属性行更改为
I thought to reject invalid episodes by changing the accepts nested attributes line to
accepts_nested_attributes_for :episodes, reject_if: proc { |attributes| !Episode.new(attributes).valid? }
但是每一集都是无效的,因为他们还没有podcast_id
,所以他们会失败validates:podcast,presence:true
but every episode would be invalid because they don't yet have podcast_id
's, so they would fail validates :podcast, presence: true
推荐答案
试试这个模式:在你的 accepts_nested_attributes_for 指令中使用 :reject_if 参数 (docs) 并传递一个方法来发现属性是否有效.这可以让您将验证卸载到 Episode 模型.
Try this pattern: Use the :reject_if param in your accepts_nested_attributes_for directive (docs) and pass a method to discover if the attributes are valid. This would let you offload the validation to the Episode model.
类似……
accepts_nested_attributes_for :episodes, :reject_if => :reject_episode_attributes?
def reject_episode_attributes?( attributes )
!Episode.attributes_are_valid?( attributes )
end
然后在Episode中,您可以创建一种方法来测试您喜欢的那些.您甚至可以创建新记录并使用现有验证.
Then in Episode you make a method that tests those however you like. You could even create a new record and use existing validations.
def self.attributes_are_valid?( attributes )
new_e = Episode.new( attributes )
new_e.valid?
end
这篇关于如果一条记录无效,Rails accepts_nested_attributes_for 将不保存嵌套记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!