我编写了一个解决方法并将其抽象为一个 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方法并传入选项。
我不太关心性能,因为这只是在初始化时执行的。