views:

48

answers:

1
def DogOwner < ActiveRecord::Base
  has_many :dogs
  has_many :breeds, :through => dogs

  def self.with_breeds(breeds)
    # returns a list of DogOwner records who own all breeds in the list

    # ex: DogOwner.with_breeds("Dalmation","Poodle")
    # or it could be DogOwner.with_breed_ids(1,3) which would only require
    # a join down to the dogs table - I could live with that.

    # do i need to hand generate SQL with n levels of subselects?
    # or is there something in ActiveRecord that handles this magically?
  end
end
+1  A: 

I figured out a way using a list of child ids:

DogOwner.all(:joins => :dogs, 
             :conditions => "dogs.breed_id in (#{list_of_breeds})", 
             :group => 'dog_owners.id', 
             :having => "count(*) = #{list_of_breeds.size}")

Credit: Ethan Vizitei's Blog Post inspired the solution.

ryw
@ryw, watch out for sql injections there ... sometimes I think certain things are just easier in pure SQL
Sam Saffron
Good point Sam - in my real use case the list is all generated from system data, no user input - and not as fun of a domain :)
ryw