【问题标题】:How can I put a conditional validation on an ActiveModel attribute that has several validations already?如何对已经有多个验证的 ActiveModel 属性进行条件验证?
【发布时间】:2012-06-29 21:55:41
【问题描述】:

我使用的是 Authlogic,默认情况下会在登录、电子邮件和密码等字段上进行一些验证(长度、唯一性、格式等)。

如果存在另一个属性,我希望能够跳过附加到某个属性的所有验证。

这可能吗?类似的东西:

validate :email, :unless => :has_openid?

然后将跳过电子邮件属性上的格式、长度和唯一性验证。

我正在使用 Rails 3.1.x 应用程序和 authlogic 3.1.0

更新:我试图关注这篇文章,但我无法让它正常工作: http://erikonrails.snowedin.net/?p=242

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 validation authlogic


    【解决方案1】:

    我使用 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
    

    【讨论】:

    • 是的,我可以做到这一点,但它将它与该属性的特定验证集相结合。例如,如果我向电子邮件字段添加 gem 或添加任何其他验证...然后我需要记住更新此块...明白我的意思吗?
    • 这很公平。当你说它“不起作用”时,你看到了什么行为?它是否无论如何都在尝试验证该字段?
    • 当我关注这篇文章时,保存失败但没有错误消息,我发现这很奇怪......我没有深入研究它,我已经放弃了这种方法所以我不能告诉你到底发生了什么。我正在考虑编写自己的模块,该模块循环遍历所有 User.validators 并添加 if/unless 选项...但我发现 rails 源在初始化时冻结了选项哈希lib/active_model/validator.rb
    • 嗯,好的。如果你想修改它,你可以尝试duping 哈希。
    • 当然,ruby 的美妙之处在于你可以做任何你想做的事情,比如复制哈希然后做 instance_variable_set ......但是“应该”我这样做是个问题......我也可以修补 ActiveModel::Validator...我希望有更好的方法...
    【解决方案2】:

    我编写了一个解决方法并将其抽象为一个 gem: https://github.com/synth/conditional_attribute_validator

    宝石文件:

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

    例子:

    class User
      include ConditionalAttributeValidator
    
      validate_attributes_with_condition :login, :password, :password_confirmation, :unless => :has_another_form_of_authentication?
    end
    

    来源:

    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 会根据已指定的任何验证自动创建 merge_attr_options 方法,以便将选项合并到现有验证中。所以我查找这些方法并遍历它们并检查该方法是否适用于特定字段。如果是这样,我调用 merge_attr_options 方法并传入选项。

    我不太关心性能,因为这只是在初始化时执行。

    【讨论】:

      猜你喜欢
      • 2011-01-31
      • 2011-12-03
      • 2012-08-23
      • 2011-06-21
      • 2011-01-20
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2011-11-15
      相关资源
      最近更新 更多