简体   繁体   中英

How can I combine multiple Rails validations for the same :if condition?

I have a model with many validations that can be grouped based on various conditions. The brute force way to handle it would be:

validates_presence_of :attr1, :if => :condition1
validates_something :attr2, :if => :condition1
validates_something_else :attr3, :if => :condition1
...

validates_presence_of :attr4, :if => :condition2
validates_something :attr5, :if => :condition2
validates_presence_of :attr6, :if => :condition2
...

But that doesn't seem very DRY. Is there a good way to group the validations based on the conditions? The approach I came up with is:

class Condition1Validator < ActiveModel::Validator
  def validate(record)
    record.instance_eval do
      validates_presence_of :attr1
      validates_something, :attr2
      validates_something_else :attr3
    end
  end
end
validates_with Condition1Validator, :if => :condition1

class Condition2Validator < ActiveModel::Validator
...
end
validates_with Condition2Validator, :if => :condition2

Can anyone think of a better way?

Update: the way I posted above is flawed in that you cannot have if, unless, etc on the nested validators. Jesse's solution is much better.

This approach is from the multi-step wizard, where you only want to validate if you are on that wizard step. Should work for you as well

class YourModel 

  with_options :if => lambda { |o| o.whatever == "whatever" } do |on_condition|
    on_condition.validates_presence_of :address
    on_condition.validates_presence_of :city
  end

  with_options :if => lambda { |o| o.condition_the_second == "whatever" } do |on_condition|
    on_condition.validates_presence_of :foo
    on_condition.validates_presence_of :bar
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM