我有两个普通的Ruby类,Account和Contact。我使用Simple Form的simple_form_for和simple_fields_for来创建嵌套属性。我希望满足以下验证要求:
看起来ActiveModel不再包含validates_associated方法,因为使用该方法会导致未定义的方法错误。我考虑过要求ActiveRecord :: Validations,但这导致了一系列各种错误(例如,未定义的方法`marked_for_destruction?')
我还考虑过在Account类上定义验证并调用有效吗?在关联对象上,但只有在父对象上也存在错误时才阻止表单提交。
validate do |account|
account.contact.valid?
# required for form to fail
errors.add(:base, "some error")
end
有什么东西我不知道要解决这个问题吗?感谢。
答案 0 :(得分:1)
class Person
include Virtus
include ActiveModel::Model
attribute :address, Address, :default => Address.new
validate :address_valid
private
def address_valid
errors.add(:base, 'address is not valid') unless address.valid?
end
end
class Address
include Virtus::ValueObject
include ActiveModel::Validations
attribute :line_1, String
attribute :line_2, String
validates :line_1, :presence => true
validates :line_2, :presence => true
end
如果将对象传递给simple_fields_for
= form.simple_fields_for person.address do |af|
= af.input :line_1
另一个选项是覆盖valid?
:
def valid?
super & address.valid?
end
请注意其&
而非&&
,因此如果第一个返回false,条件不会被短路。
答案 1 :(得分:1)
最近(问了这个问题已有7年了!),我遇到了同样的问题,并通过基于ActiveRecord的AssociatedValidator
实现了解决。
我只是将其包含在config/initializers
文件夹中:
module ActiveModel
module Validations
class AssociatedValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
if Array(value).reject { |r| valid_object?(r) }.any?
record.errors.add(attribute, :invalid, **options.merge(value: value))
end
end
private
def valid_object?(record)
record.valid?
end
end
module ClassMethods
def validates_associated(*attr_names)
validates_with AssociatedValidator, _merge_attributes(attr_names)
end
end
end
end
现在您也可以在ActiveModel中使用validates_associated
。