在创建父项之前验证子项

Validate children before creating parent

只有当子模型符合某些验证(例如它们的属性之和等于来值等)时,我如何才能创建父模型?

我有一个父模型:

class Foo < ApplicationRecord

  has_many :bars, dependent: :destroy

  accepts_nested_attributes_for :bars, allow_destroy: true

end

子模型为:

class Bar < ApplicationRecord

  belongs_to :foo

end

有正确的做法吗?我应该在哪里验证子模型?另外我怎么能用rspec测试它?像这样?

before do
  @foo = create(:foo)
  @bar = create(:bar, value: 30, foo_id: @foo.id)
end

Rails 提供 validates_associated,这将确保关联的记录有效。如果关联记录无效,则不会保存父记录。

Foo中:

class Foo < ApplicationRecord
  has_many :bars, dependent: :destroy
  accepts_nested_attributes_for :bars, allow_destroy: true

  validates_associated :bars
end

Bar中:

class Bar < ApplicationRecord
  belongs_to :foo

  include ActiveModel::Validations
  validates_with BarValidator
end

BarValidator中,即a custom validator:

class BarValidator < ActiveModel::Validator
  def validate(record)
    record.errors.add :some_error, 'Some message' unless condition_met?
  end
end

您已声明:

only if its children models fit some validations alltogether like the sum of their attributes equal come value, etc?

这有点模棱两可。如果您确实 do 需要计算子项的总和,那么您可以向父项添加一个验证器,该验证器映射到子项并在未能满足条件时附加错误:

Foo中,(或者最好是验证器):

validate :children_condition

def children_condition
  errors[:base] << "Some message" if bars.map(&:attribute).sum != expected_minimum_value
end

validates_associated 文档中的重要说明:

WARNING: This validation must not be used on both ends of an association. Doing so will lead to a circular dependency and cause infinite recursion.

NOTE: This validation will not fail if the association hasn't been assigned. If you want to ensure that the association is both present and guaranteed to be valid, you also need to use validates_presence_of.

至于:

Also how could I test it with rspec?

我会创建一个包含有效父项、有效子项 && 有效父项、无效子项等的测试套件,并期望 Model.count 增加预期数量(在后一个示例中为零) .