我有两个模型如下
class User < ActiveRecord::Base
validates_associated :account
end
class Account < ActiveRecord::Base
belongs_to :user
#----------------------------------Validations--Start-------------------------
validates_length_of :unique_url, :within => 2..30 ,:message => "Should be atleast 3 characters long!"
validates_uniqueness_of :unique_url ,:message => "Already Taken"
validates_format_of :unique_url,:with => /^([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])$/ , :message => " Cannot contain special charaters"
#----------------------------------Validations--End---------------------------
end
现在,当我将帐户与用户关联时,它会显示
“帐户无效”
相反,我希望直接从该模型获取错误消息。 所以应该说
"Should be atleast 3 characters long!"
或"Already Taken"
或" Cannot contain special charaters"
有办法做到这一点吗?
我不想给出像:
这样的通用消息validates_associated :account , :message=>"one of the three validations failed"
答案 0 :(得分:28)
您可以根据内置验证器的代码编写自己的自定义验证器。
查看validates_associated的源代码,我们看到它使用了“AssociatedValidator”。源代码是:
module ActiveRecord
module Validations
class AssociatedValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return if (value.is_a?(Array) ? value : [value]).collect{ |r| r.nil? || r.valid? }.all?
record.errors.add(attribute, :invalid, options.merge(:value => value))
end
end
module ClassMethods
def validates_associated(*attr_names)
validates_with AssociatedValidator, _merge_attributes(attr_names)
end
end
end
end
因此,您可以使用此示例来创建一个自定义验证程序,以此类似于此错误消息:
module ActiveRecord
module Validations
class AssociatedBubblingValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
(value.is_a?(Array) ? value : [value]).each do |v|
unless v.valid?
v.errors.full_messages.each do |msg|
record.errors.add(attribute, msg, options.merge(:value => value))
end
end
end
end
end
module ClassMethods
def validates_associated_bubbling(*attr_names)
validates_with AssociatedBubblingValidator, _merge_attributes(attr_names)
end
end
end
end
您可以将此代码放在初始值设定项中,例如/initializers/associated_bubbling_validator.rb
。
最后,你会这样验证:
class User < ActiveRecord::Base
validates_associated_bubbling :account
end
注意:上面的代码是完全未经测试的,但是如果它不能完全正常工作,那么希望能够让你走上正确的轨道
答案 1 :(得分:11)
可能你可以试试下面给出的东西
validates_associated :account , :message=> lambda{|class_obj, obj| obj[:value].errors.full_messages.join(",") }
通过 obj[:value]
您正在访问经过验证的帐户对象。所以obj [:value] .errors会给你错误。
答案 2 :(得分:4)
vanilla解决方案是对关联对象进行第二次错误渲染:
<%= render :partial => 'shared/errors', :locals => {:instance => @account.owner} %>
<%= render :partial => 'shared/errors', :locals => {:instance => @account} %>
答案 3 :(得分:1)
要获取帐户的错误消息,您必须在该实例上调用errors
方法:
@user.account.errors
或
@account = @user.build_account
@account.errors
或在视图中:
<%= error_messages_for :account %>
我假设它是一个has_one关系。
答案 4 :(得分:1)
我遇到了同样的问题...我想验证关联的对象,并让valid?
方法返回false,但不添加“多余的”消息,如“帐户无效”。我只希望帐户验证消息显示在帐户字段旁边。
我发现完成此任务的唯一方法是覆盖run_validations!
,如下所示。在此示例中,关联为has_many :contacts
:
def run_validations!
valid = super
contacts.each do |contact|
valid = false unless contact.valid?(validation_context)
end
valid
end
不要使用valid &&= contacts.all? ...
,因为如果基类已经无效,这将阻止对联系人进行验证,如果其中一个联系人验证失败,将停止迭代。
或许将其概括为一些关注模块,但我只需要一次。
答案 5 :(得分:1)
对于那些仍然在Rails 2上的人,你可以用以下代码覆盖validates_associated:
module ActiveRecord::Validations::ClassMethods
def validates_associated(association, options = {})
class_eval do
validates_each(association) do |record, associate_name, value|
associate = record.send(associate_name)
if associate && !associate.valid?
associate.errors.each do |key, value|
record.errors.add(key, value)
end
end
end
end
end
end
来源:http://pivotallabs.com/alias-method-chain-validates-associated-informative-error-message/
答案 6 :(得分:1)
如果仍然需要,则可以在Rails 5.2上进行以下操作
#app/validators/with_own_error_messages_validator.rb
class WithOwnErrorMessagesValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
Array(value).each do |v|
unless v.valid?
v.errors.full_messages.each do |msg|
record.errors.add(attribute, msg, options.merge(value: value))
end
end
end
end
end
#app/models/project.rb
class Project < ApplicationRecord
validates :attachments, with_own_error_messages: true
has_many :attachments, as: :attachable, validate: false
end
请注意validate: false
关联上的has_many
。这是必需的,因为Rails现在默认情况下会验证关联。没有它,您会收到Attachment
错误消息以及一般的Attachments is invalid
。
希望这会有所帮助。