Последовательные соединения в модели Rails 3;как общаться через отношения многие ко многим? - PullRequest
0 голосов
/ 09 февраля 2011

У меня есть Модель X и Модель Y, которые связаны через макрос has_and_belongs_to_many. В базе данных есть таблица, в которой хранятся данные об отношениях «многие ко многим» между моделью X и моделью Y.

У меня также есть Модель A, которая связана с помощью макроса has_many с Моделью X. Я хочу иметь возможность выполнить очень простую команду для доступа ко всем объектам Модели Y, связанным с Моделью A. Итак, другими словами, скажем, У меня есть следующие объекты:

objectA.kind_of? ModelA = true
objectX.kind_of? ModelX = true
objectY.kind_of? ModelY = true

Я хочу иметь возможность запустить objectA.objectYs и вернулся ко мне [objectY].

Что я должен добавить в определения моей модели, чтобы сделать это?

(Я пытался поместить в модель A: (1) has_many :modelY; и (2) has_many :modelY, :through => :modelX. Ни один из них не прав.)

1 Ответ

1 голос
/ 10 февраля 2011

Предостережение: обычно не следует использовать такие извращенные названия моделей.

Предположим, что модели выглядят так:

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...