【问题标题】:How to call ActiveRecord validators as instance methods (ala Sequel)?如何调用 ActiveRecord 验证器作为实例方法(ala Sequel)?
【发布时间】:2011-08-15 08:54:45
【问题描述】:

我的模型需要不同的验证器,具体取决于其当前状态。我应该如何为每个实例调用 ActiveRecord 验证器?我想尽可能多地重复使用管道,但我不确定如何继续。

class Order < ActiveRecord::Base
  attr_accessible :state

  validate :state_specific_validations

  def state_specific_validations
    if :paid == self.state
      # Warning: here be Unicorns...

      # Wishful thinking...
      validate_presence_of :paid_at
      validate_associated :purchaser

      # Hopeful. What are the validators called internally in Rails?
      errors << PresenceValidator.new(self, :paid_at).valid?
      errors << AssociationValidator.new(self, :paid_at).valid?

      # Plan B
      # ... Hoping for help from the audience ...

    else
      # Even more complicated validator logic, hoping for some DRY validators
    end
  end
end

我可以只使用自定义验证器,但为什么我需要复制所有内置验证器逻辑(i18n 错误消息等)?

有没有一种简洁的方式将 Rails 验证器调用为实例方法? 我认为 Sequel 的基于实例的验证器的方法比 ActiveRecord 的基于类的方法更合理,但我不在这里判断。我只是想回到解决更有趣的问题。我只是希望其他人也遇到过这个问题,并可以为我指出一些有趣的要点或宝石。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 activerecord sequel


    【解决方案1】:

    我很确定所有 validate_* 方法都可以采用 :if 选项 - 它可以指向另一种方法(并且可能也接受 Proc),因此您可以将验证分解为更多内容喜欢:

    validates_presence_of :paid_at, :if => :paid?
    validates_association :purchaser, :if => :paid?
    

    为了进一步清理,有 with_options 帮助器:

    with_options :if => :paid? do |v|
      v.validates_presence_of :paid_at
      v.validates_association :purchaser
    end
    

    虽然不确定是否可以与标准 validate :custom_validate_method 一起使用 - 但我不会感到惊讶。

    【讨论】:

    • 帕特,感谢您的意见。 with_options 是我将来肯定会使用更多的东西。看起来我可能正在使用您的解决方案,尽管您可以先看看我发布的答案吗?我不确定红宝石单身人士是否扭曲了我的大脑。 :)
    【解决方案2】:

    这有什么不合适的理由吗?看起来它可能会起作用,但也许元编程扭曲了我的大脑......

    class Order < ActiveRecord::Base
      attr_accessible :state
    
      validate :state_specific_validations
    
      def state_specific_validations
        if :paid == self.state
          class << self
            validate_presence_of :paid_at
            validate_associated :purchaser
          end
        end
      end
    end
    

    最糟糕的是测试通过了,所以我不确定我是否解决了它或者我需要更好的测试。例如,我不是 100% 肯定这个单例修改不会影响其他订单。

    叹息需要睡觉。

    【讨论】:

    • 这里的问题是您在验证过程中添加了类级别的内容(授予,而不是 Order,只是 eigenclass)。也许它有效,但感觉非常脆弱。我根本不会推荐这种方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多