Forum: Ruby on Rails Cleaner way to build a "one or the other" validation?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Michael K. (Guest)
on 2008-10-22 09:22
(Received via mailing list)
I have an object called dealer.  Dealer has two fields dealer_number
and sub_dealer_number.  It must have 1 OR the other... but not both.
To validate this I have:

class Dealer < ActiveRecord::Base
  validate :dealer_id?

private
  def dealer_id?
    if number.blank? && sub_number.blank?
      errors.add_to_base("You must specify either a Dealer Number OR a
Sub Dealer Number.")
    elsif (number.length > 0) && (sub_number.length > 0)
        errors.add_to_base("You must specify either a Dealer Number OR
a Sub Dealer Number.")
    end
  end
end

This looks really messy to me.  Is there a better way?  Thank you for
your thoughts.
Frederick C. (Guest)
on 2008-10-22 09:49
(Received via mailing list)
On 21 Oct 2008, at 12:58, gnunix wrote:

>
> I have an object called dealer.  Dealer has two fields dealer_number
> and sub_dealer_number.  It must have 1 OR the other... but not both.
> To validate this I have:
>
Use the Xor operator ( ^ ) ?

Fred
Roy P. (Guest)
on 2008-10-22 19:15
(Received via mailing list)
How about:

def validate_dealer_id
  if number.blank? then
    errors.add_to_base("You must specify either a Dealer Number OR a Sub
Dealer Number.") if subnumber.blank?
  else
    erros.add_to_base("A dealer can't have both a dealer number AND a
sub dealer number") unless subnumber.blank?
  end
end

?

Extra bonus kibbitzing:
 - Would it make things any easier to store both those
   numbers in a single field, and keep track of whether
   a given dealer is a dealer or a sub in a separate 'dealer_type'
   field?
 - FWIW--the ruby convention is that methods whose names
   end in a ? return a boolean.

Cheers,

-Roy
Michael K. (Guest)
on 2008-10-23 01:41
Frederick C. wrote:
> Use the Xor operator ( ^ ) ?
>
> Fred

Sexy.  Thanks.

I changed above to:

class Dealer < ActiveRecord::Base
  validate :dealer_id?

private
  def dealer_id?
    if !(number.blank? ^ sub_number.blank?)
      errors.add_to_base("You must specify either a Dealer Number OR a
Sub Dealer Number.")
    end
  end
end

Makes me feel less dirty.
Michael K. (Guest)
on 2008-10-23 01:43
Roy P. wrote:
> How about:
>
> def validate_dealer_id
>   if number.blank? then
>     errors.add_to_base("You must specify either a Dealer Number OR a Sub
> Dealer Number.") if subnumber.blank?
>   else
>     erros.add_to_base("A dealer can't have both a dealer number AND a
> sub dealer number") unless subnumber.blank?
>   end
> end
>
> ?
>
> Extra bonus kibbitzing:
>  - Would it make things any easier to store both those
>    numbers in a single field, and keep track of whether
>    a given dealer is a dealer or a sub in a separate 'dealer_type'
>    field?
>  - FWIW--the ruby convention is that methods whose names
>    end in a ? return a boolean.
>
> Cheers,
>
> -Roy

I don't think that your above example is any cleaner then my original
solution.  However, your bonus kibbitzing (lol) I think is a really good
thought.  I am going to implement this logic on a later iteration.
Thanks for this.
Phillip K. (Guest)
on 2008-10-23 06:19
Michael K. wrote:

> I don't think that your above example is any cleaner then my original
> solution.  However, your bonus kibbitzing (lol) I think is a really good
> thought.  I am going to implement this logic on a later iteration.
> Thanks for this.

Hi Michael,

For future reference, I needed to do something similar a few months ago
and ended up creating a custom validation. I wrote about it if you want
to look into it:

http://per-snicket-y.blogspot.com/2008/04/custom-v...

Peace.
This topic is locked and can not be replied to.