Предостережение: обычно не следует использовать такие извращенные названия моделей.
Предположим, что модели выглядят так:
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
Мы можем создать область для получения ModelY для всех ModelX, принадлежащих модели A:
class ModelY < ActiveRecord::Base
scope :find_by_a, lambda { |a| joins(:model_xes).\
where(:model_xes=>{:model_a_id=>a.id})}
end
затем простой метод для вызова области в экземпляре ModelA:
class ModelA < ActiveRecord::Base
def ys
ModelY.find_by_a(self)
end
end
Тест вроде так:
require 'spec_helper'
describe ModelA do
before(:each) do
@a = ModelA.create(:name=>"a")
2.times { @a.model_xes.create(:name=>"x") }
end
it "relates model_x" do
@a.model_xes.count.should == 2
end
it "relates model y" do
x = @a.model_xes.first
x.model_ies.create
x.model_ies.count.should == 1
end
it "relates model y through model x" do
@a.model_xes.each do |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
Обратите внимание, что HABTM потерял популярность, поэтому рекомендуется использовать has_many :through
.