Topic: DRYing up AR Validations that are based on a condition

I have the following validations in an 'Order' model:

  validates_length_of :ship_to_first_name, :in => 2..255 
  validates_length_of :ship_to_last_name, :in => 2..255
  validates_length_of :ship_to_address, :in => 2..255
  validates_length_of :ship_to_city, :in => 2..255
  validates_length_of :ship_to_postal_code, :in => 2..255
  validates_length_of :ship_to_country, :in => 2..255
  validates_length_of :ship_to_phone_number, :in => 7..20

However, I only want these validations to run if @order.use_different_shipping_address? Is there a DRYer way to make these validation hinge on that condition than adding an :if option to each validation?

I thought about how mothers feed their babies with tiny little spoons and forks, so I wondered what do Chinese mothers use. Toothpicks?

Re: DRYing up AR Validations that are based on a condition

Put the attributes in an array and loop through them to set the validation. Like this:

%w[first_name last_name address city postal_code country phone_number].each do |a|
  validates_length_of "ship_to_#{a}".to_sym, :in => 2..255
end
validates_length_of :ship_to_phone_number, :in => 7..20

Then you can append more conditions without too much duplication.

Last edited by ryanb (2006-11-30 13:31:05)

Railscasts - Free Ruby on Rails Screencasts

Re: DRYing up AR Validations that are based on a condition

ryanb wrote:

Put the attributes in an array and loop through them to set the validation. Like this:

%w[first_name last_name address city postal_code country phone_number].each do |a|
  validates_length_of "ship_to_#{a}".to_sym, :in => 2..255
end
validates_length_of :ship_to_phone_number, :in => 7..20

Then you can append more conditions without too much duplication.

That worked very well. My final validations ended up looking like this:

  %w(first_name last_name address city postal_code country).each do |field|
    validates_length_of "bill_to_#{field}".to_sym, :in => 2..255
    validates_length_of "ship_to_#{field}".to_sym, :in => 2..255, :if => Proc.new { |order| order.use_different_shipping_address? }
  end
  validates_length_of :bill_to_phone_number, :in => 7..20
  validates_length_of :ship_to_phone_number, :in => 7..20, :if => Proc.new { |order| order.use_different_shipping_address? }

I thought about how mothers feed their babies with tiny little spoons and forks, so I wondered what do Chinese mothers use. Toothpicks?

Re: DRYing up AR Validations that are based on a condition

I think you can just do this:

:if => :use_different_shipping_address?

Not need to set up a Proc.

Railscasts - Free Ruby on Rails Screencasts

Re: DRYing up AR Validations that are based on a condition

ryanb wrote:

I think you can just do this:

:if => :use_different_shipping_address?

Not need to set up a Proc.

yep. thanks big_smile

I thought about how mothers feed their babies with tiny little spoons and forks, so I wondered what do Chinese mothers use. Toothpicks?