model validation

I have an 'animal' model that has zero to many animal_options that are
other models. Some of these animal_options are mutually exclusive,
like 'wet' versus 'dry' and such. How can I validate the animal model
to only contain one of these mutually exclusive options?

Breakpointing shows me that my code in Animal.validate doesn't get ran
before the invalid animal_options get saved to the database:

class Animal < ActiveRecord::Base

  has_many :animal_animal_options
  has_many :animal_options, :through => :animal_animal_options

  def validate
    # validate mutually exclusive options
    dry = AnimalOption.find_by_name( 'Dry' )
    wet = AnimalOption.find_by_name( 'Wet' )
    if animal_options.include?( dry ) && animal_options.include?( wet )
      errors.add( :animal_options, 'Cannot be dry and wet at the same time' )
    end
  end

end

Another issue I'm having is how to make the options pre-selected when
editing an animal:

<%= select_tag 'animal_option_id[]',
options_from_collection_for_select( @animal_options, 'id', 'name',
@animal.animal_options ), { :multiple => true, :size =>
@animal_options.size } %>

I get no errors from that tag but it doesn't pre-select anything either.

Any help would be appreciated.

Greg,

I think your problem is that in the validate below the finds are returning arrays into "dry" and "wet". In addition, they aren't linked to your current Animal. Your current Animal is accessible as "self" in the validate and since you have the relationship defined you can simply do this:

def validate
    # create array of option names associated with the current animal
    options = self.animal_options.map {|option| option.name}

    # Animal can't be both wet and dry
    if options.include?( 'Wet' ) and options.include( 'Dry' )
       errors.add( :animal_options, 'Cannot be dry and wet at the same time' )
    end

    # Other option comparisons
end

David

Greg Donald wrote: