验证与模型的错误消息相关联

Gau*_*hah 26 validation ruby-on-rails

我有两个模型如下

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
Run Code Online (Sandbox Code Playgroud)

现在,当我将帐户与用户关联时,它说

"帐户无效"

相反,我想直接从该模型获取错误消息.所以它应该说

"Should be atleast 3 characters long!""Already Taken"" Cannot contain special charaters"

有没有办法做到这一点 ?

我不想给出如下通用消息:

validates_associated :account , :message=>"one of the three validations failed"
Run Code Online (Sandbox Code Playgroud)

Ben*_*Lee 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
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用此示例来创建一个自定义验证程序,它会冒出错误消息,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

您可以将此代码放在初始化程序中,例如/initializers/associated_bubbling_validator.rb.

最后,你会这样验证:

class User < ActiveRecord::Base
 validates_associated_bubbling :account
end
Run Code Online (Sandbox Code Playgroud)

注意:上面的代码是完全未经测试的,但是如果它不能完全正常工作,那么希望能让你走上正确的轨道

  • 老实说,我认为这实际上是最优雅和最红润的方式.不知道你在寻找什么"香草" - 没有一个完全直接解决这个问题的方法. (5认同)

Pau*_*esC 11

也许你可以尝试下面给出的东西

validates_associated :account , :message=> lambda{|class_obj, obj| obj[:value].errors.full_messages.join(",") }
Run Code Online (Sandbox Code Playgroud)

通过 obj[:value] 您访问经过验证的Account对象.所以obj [:value] .errors会给你错误.