简体   繁体   English

如何对已经具有多个验证的ActiveModel属性进行条件验证?

[英]How can I put a conditional validation on an ActiveModel attribute that has several validations already?

I'm using Authlogic which by default puts a few validations(length, uniqueness, format, etc) on fields like login, email, and password. 我使用的是Authlogic,默认情况下会对登录名,电子邮件和密码等字段进行一些验证(长度,唯一性,格式等)。

I'd like to be able to skip all validations attached to one of the attributes if, say, another attribute is present. 如果存在另一个属性,我希望能够跳过附加到其中一个属性的所有验证。

Is this possible? 这可能吗? Something like: 就像是:

validate :email, :unless => :has_openid?

which will then skip the format, length, and uniqueness validations just on the email attribute. 然后,仅在电子邮件属性上跳过格式,长度和唯一性验证。

I'm working with a Rails 3.1.x app and authlogic 3.1.0 我正在使用Rails 3.1.x应用程序和authlogic 3.1.0

Update: I was trying to follow this article, but I couldn't get it to work properly: http://erikonrails.snowedin.net/?p=242 更新:我正在尝试关注本文,但无法使其正常运行: http : //erikonrails.snowedin.net/?p=242

The way I've done this with authlogic is by passing a block to acts_as_authentic : 我使用authlogic完成此操作的方法是将一个块传递给acts_as_authentic

acts_as_authentic do |config|
  with_options :unless => :has_openid? do      
    config.merge_validates_format_of_email_field_options
    config.merge_validates_length_of_email_field_options
    config.merge_validates_uniqueness_of_email_field_options
  end
end

I've written a workaround and abstracted it out into a gem: https://github.com/synth/conditional_attribute_validator 我已经写了一个解决方法,并将其抽象为一个gem: https : //github.com/synth/conditional_attribute_validator

Gemfile: 宝石文件:

gem 'conditional_attribute_validator', :git => "git://github.com/synth/conditional_attribute_validator.git"

Example: 例:

class User
  include ConditionalAttributeValidator

  validate_attributes_with_condition :login, :password, :password_confirmation, :unless => :has_another_form_of_authentication?
end

Source: 资源:

def validate_attributes_with_condition(*args)
  opts = args.extract_options!
  raise "Must have an :if or :unless option" unless opts.has_key?(:if) or opts.has_key?(:unless)

  merge_methods = self.methods.grep(/merge_.*_options/)
  args.each do |field|
    merge_methods.grep(/#{Regexp.quote(field)}/).each do |m|
      self.send(m, opts)
    end
  end
end

Rails automagically creates the merge_ attr _options methods based upon whatever validations have been specified in order to merge options into an existing validation. Rails根据指定的验证内容自动创建merge_ attr _options方法,以便将选项合并到现有验证中。 So I lookup these methods and iterate over them and check if that method applies to a particular field. 因此,我查找了这些方法并对其进行迭代,然后检查该方法是否适用于特定字段。 If so, I call the merge_ attr _options method and pass in the options. 如果是这样,我调用merge_ attr _options方法并传递选项。

I'm not too concerned about performance since this is just performed on initialization. 我不太担心性能,因为它只是在初始化时执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM