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
AndyV
(AndyV)
April 24, 2008, 4:58pm
3
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(',')])