父节点无法保存

时间:2018-01-04 16:49:54

标签: ruby-on-rails ruby-on-rails-5

在尝试同时创建父母和孩子时,我遇到了困难。 我认为当关联的父级无法保存时,应该引发异常,但它没有。

class Child < ApplicationRecord
  belongs_to :parent
  validates_presence_of :parent, :name
end

class Parent < ApplicationRecord
  has_one :child
  validates_presence_of :name
end

请注意,子项已保存,并且他们无法查看父项的保存问题:

parent = Parent.new
parent.valid?                         # => false
child = Child.create!(name: 'something', parent: parent) # => true
child.parent_id                       # => nil
child.reload.valid?                   # => false

已创建无效的子项。为什么create!方法也没有在父级上调用create!,因此会引发异常?

值得注意的是,当遵循相同的过程,但我们从父母开始,我们得到了我期望的行为:

child = child.new
child.valid?                         # => false
parent = Parent.create!(name: 'something', child: child) # => ActiveRecord::Exception
parent.valid?                         # => false

我知道一些工作(例如孩子的validates_associated :parent),但我试图理解为什么Rails的行为方式。

3 个答案:

答案 0 :(得分:1)

Rails不知道你是在尝试同时保存它们。如果您想同时保存它们,请尝试nested attributes

我希望这可以做你想做的事:

class Child < ApplicationRecord
  belongs_to :parent
  validates_presence_of :parent
end

class Parent < ApplicationRecord
  has_many :children
  validates_presence_of :name

  accepts_nested_attributes_for :children, allow_destroy: true
end

parent = Parent.new children: [child]
parent.save!

答案 1 :(得分:1)

为什么会引发异常?您正在设置parent,就child而言,parent存在(通过验证)并且它不会调用父级和IMO上的create!也不应该。

您的解决方法是在parent_id而不是parent上进行验证,或通过parent.children.create!创建子项。如果父级未持久化,后者将引发ActiveRecord::RecordNotSaved: You cannot call create unless the parent is saved

答案 2 :(得分:0)

将孩子改为

class Child < ApplicationRecord
  belongs_to :parent
  validates_presence_of :parent, :id
end

正如@AbM所说,你应该把约束放在某些字段上,这会给你ActiveRecord::RecordInvalid: Validation failed: Id can't be blank例外。