在创建父项之前验证子项
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
增加预期数量(在后一个示例中为零) .
只有当子模型符合某些验证(例如它们的属性之和等于来值等)时,我如何才能创建父模型?
我有一个父模型:
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
增加预期数量(在后一个示例中为零) .