Serial joins in a Rails 3 model; how to associate through a many-to-many relationship? -
i have model x , model y associated through has_and_belongs_to_many macro. there's table in database retains data on many-to-many relationships between model x , model y.
i have model a, associated through has_many macro model x. want able run simple command reach model y objects associated model a. so, in other words, let's have following objects:
objecta.kind_of? modela = true objectx.kind_of? modelx = true objecty.kind_of? modely = true
i want able run objecta.objectys
, have returned me [objecty].
what must put in model definitions able this?
(i have tried placing in model a: (1) has_many :modely
; , (2) has_many :modely, :through => :modelx
. neither right.)
caveat: 1 wouldn't use such perverse model names.
assuming models this:
class modela < activerecord::base has_many :model_xes end class modelx < activerecord::base belongs_to :model_a has_and_belongs_to_many :model_ies, :class_name => 'modely', :join_table => 'model_x_model_ies' end class modely < activerecord::base has_and_belongs_to_many :model_xes, :class_name => 'modelx', :join_table => 'model_x_model_ies' end
we can create scope modely's modelx's belonging model a:
class modely < activerecord::base scope :find_by_a, lambda { |a| joins(:model_xes).\ where(:model_xes=>{:model_a_id=>a.id})} end
then simple method call scope on instance of modela:
class modela < activerecord::base def ys modely.find_by_a(self) end end
test so:
require 'spec_helper' describe modela before(:each) @a = modela.create(:name=>"a") 2.times { @a.model_xes.create(:name=>"x") } end "relates model_x" @a.model_xes.count.should == 2 end "relates model y" x = @a.model_xes.first x.model_ies.create x.model_ies.count.should == 1 end "relates model y through model x" @a.model_xes.each |x| 2.times { x.model_ies.create(:name=>"y") } end ys = @a.ys ys.count.should == 4 ys.all? { |y| y.name == "y" }.should be_true end end
note habtm has fallen out of favor, you're encouraged use has_many :through
instead.
Comments
Post a Comment