我有一个模型需要不同的验证器,具体取决于它的当前状态。我应该如何为每个实例调用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基于类的更合理,但我不是在这里判断。我想回到解决更有趣的问题。我只是希望其他人能够遇到这个并且能指出一些有趣的要点或宝石。
答案 0 :(得分:4)
我很确定所有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
- 但这不会让我感到惊讶。
答案 1 :(得分:0)
有什么理由说这不合适吗?它似乎可能有用,但也许元编程会扭曲我的大脑......
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%肯定这个单例修改不会影响其他订单。
叹息需要一些睡眠。