我有这个域名模型:
class Person < ActiveRecord::Base
composed_of :address,
mapping: [%w(address_street street), %w(address_city city), %w(address_zip_code zip_code), %w(address_country country)]
validates :name, presence: true, length: { maximum: 50 }
validates :surname, presence: true, length: { maximum: 50 }
validates_associated :address
end
class Address
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_reader :street, :city, :zip_code, :country
validates :street, presence: true
validates :city, presence: true
validates :zip_code, presence: true
validates :country, presence: true
def initialize(street, city, zip_code, country)
@street, @city, @zip_code, @country = street, city, zip_code, country
end
def ==(other_address)
street == other_address.street && city == other_address.city && zip_code == other_address.zip_code && country == other_address.country
end
def persisted?
false
end
end
当我尝试保存无效模型时:
> p = Person.new
=> #<Person id: nil, name: nil, surname: nil, address_street: nil, address_city: nil, address_zip_code: nil, address_country: nil
> p.valid?
=> false
> p.errors
=> {:name=>["can't be blank"], :surname=>["can't be blank"], :address=>["is invalid"]}
这没关系,但是我希望错误数组中填充了Address的错误消息,如下所示:
=> {:name=>["can't be blank"], :surname=>["can't be blank"], :address_street=>["can't be blank"], :address_city=>["can't be blank"], :address_zip_code=>["can't be blank"], :address_country=>["can't be blank"]}
问题是:有一个干净的Rails方法吗?或者只是我必须将验证代码从Address移动到Person(非常难看)?还有其他解决办法吗?
非常感谢。
答案 0 :(得分:2)
定义composed_of
属性时,它会成为自己的对象。我认为有两种方法可以满足您的需求。
1)在Address
班级
将您当前的验证替换为:
validates_each :street, :city, :zip_code, :country do |record, attr, value|
record.errors.add attr, 'should not be blank' if value.blank?
end
这样,您就可以访问以下错误消息:
p = Person.new
p.address.errors
2)仅自定义address
错误消息
validates_associated :address,
:message => lambda { |i18n_key, object| self.set_address_error_msg(object[:value]) }
def self.set_address_error_msg address
errors_array = Array.new
address.instance_variables.each do |var|
errors_array << "#{var[1..-1]} should not be blank" if address.send(var[1..-1]).blank?
end
errors_array.join(", ")
end
这将呈现如下内容:
=> #<OrderedHash {:address=>["country should not be blank, zip_code should not be blank, validation_context should not be blank, city should not be blank"]}>
最后,您可以在Profile
课程中重写验证器,但正如您所说,它真的很难看。