如何将ActiveRecordvalidation器作为实例方法调用(ala Sequel)?

我有一个模型需要不同的validation器,具体取决于它的当前状态。 我应该如何为每个实例调用ActiveRecordvalidation器? 我想重用尽可能多的管道,但我不知道如何继续。

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 

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

有没有一种巧妙的方法来调用Railsvalidation器作为实例方法? 我认为Sequel基于实例的validation器的方法比ActiveRecord基于类的更合理,但我不是来判断。 我想回到解决更有趣的问题。 我只是希望其他人遇到过这个并且能指出一些有趣的要点或gem。

我非常确定所有validate_*方法都可以采用:if选项 – 它可以指向另一种方法(并且可能也接受Proc),因此您可以将您的validation分解为:

 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 – 但它不会让我感到惊讶。

这有什么不合适的原因吗? 它似乎可能有效,但也许元编程扭曲了我的大脑……

 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%肯定这个单例修改不会影响其他订单。

感叹需要一些睡眠。