Dynamic finders in has_many associations

I have these 3 models.

class Ivr < ActiveRecord::Base   has_many :klusterings, :dependent => :destroy   has_many :klusters, :through => :klusterings, :uniq => true end

class Kluster < ActiveRecord::Base   has_many :klusterings, :dependent => :destroy   has_many :ivrs, :through => :klusterings, :uniq => true end

class Klustering < ActiveRecord::Base   belongs_to :kluster   belongs_to :ivr end

I faced 2 problems and didn't manage to find any good tutorial.

1. Given some Kluster A, I want to find all the Ivrs that aren't in A. 2. I want to find all the Ivrs that aren't in ANY Kluster.

-- I managed to do 1. with: @kluster = Kluster.find(params[:id]) @all_ivrs = Ivr.find(:all)

@ivrs = (@all_ivrs - @kluster.ivrs)

-- And I did 2. with: @all_ivrs = Ivr.find(:all).select{ |ivr| ivr.klusters.empty? }

But 1. does two SQL queries, one possibly very big (Ivr.find(:all)). And 2. does that too.

Any way to do this, preferibly with dynamic finders?

You need some lower level stuff:

Ivr.find :all, :joins => 'left outer join klusterings on klusterings.ivr_id = ivrs.id', :conditions => 'kluster_id IS NULL' finds ivrs associated with no klusters Ivr.find :all, :joins => "left outer join klusterings on klusterings.ivr_id = ivrs.id AND kluster_id = #{@kluster.id}", :conditions => 'kluster_id IS NULL' should find the ivrs not associated with @kluster (typed quickly in mail, so might be slightly off, but should get you there in the end)

Fred

I've done some similar lookups along these lines...

1. Given some Kluster A, I want to find all the Ivrs that aren't in A.

@kluster = Kluster.find(...A...) @ivrs = Ivr.find(:all, :conditions=>["id not in (?)", @kluster.ivr_ids.join(',')])

2. I want to find all the Ivrs that aren't in ANY Kluster.

ivr_ids = Kluster.find(:all).collect{|kluster| kluster.ivr_ds}.uniq @unklustered = Ivr.find(:all, :conditions=>["id not in (?)", ivr_ids.join(',')])