Моя первая версия ответа была неверной, но эта работает отлично. Я сделал несколько опечаток в первый раз (опасность не создать приложение для тестирования), но на этот раз я проверил. И плагин нужен, но это легко. Сначала установите плагин:
script/plugin install git://github.com/ianwhite/nested_has_many_through.git
Это устанавливает обходной путь Яна Уайта и работает без проблем. Теперь модели, скопированные непосредственно из тестового приложения, которые я настроил, чтобы это работало:
class FoodItem < ActiveRecord::Base
has_many :food_category_items
has_many :food_categories, :through => :food_category_items
has_many :places, :through => :food_categories
end
class FoodCategory < ActiveRecord::Base
has_many :food_category_items
has_many :food_items, :through => :food_category_items
belongs_to :place
end
class FoodCategoryItem < ActiveRecord::Base
belongs_to :food_item
belongs_to :food_category
end
class Place < ActiveRecord::Base
has_many :food_categories
has_many :food_category_items, :through => :food_categories
has_many :food_items, :through => :food_category_items
end
Теперь "далекие" ассоциации работают так же хорошо. place_instance.food_items
и food_item.places
работают безупречно, также как и более простые ассоциации. Просто для справки, вот моя схема, показывающая, куда идут все внешние ключи:
create_table "food_categories", :force => true do |t|
t.string "name"
t.integer "place_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "food_category_items", :force => true do |t|
t.string "name"
t.integer "food_item_id"
t.integer "food_category_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "food_items", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "places", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
Надеюсь, это поможет!
ОБНОВЛЕНИЕ: Этот вопрос поднимался несколько раз в последнее время. Я написал статью, вложившую ваше has_many: через отношения , чтобы объяснить подробно. У него даже есть пример приложения на GitHub, который можно загрузить и поиграть.