如果一条记录无效,Rails accepts_nested_attributes_for 将不保存嵌套记录 [英] Rails accepts_nested_attributes_for saves no nested records if one record is invalid

查看:47
本文介绍了如果一条记录无效,Rails accepts_nested_attributes_for 将不保存嵌套记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果其中一条记录未通过验证,则创建具有嵌套关联的记录将无法保存任何关联记录.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆