的has_many:通过has_and_belongs_to_many协会协会、has_many、has_and_belongs_to_many

2023-09-08 18:46:20 作者:愚人心悸

我试图做一个Ruby on Rails项目如下:

I am trying to do the following in a Ruby on Rails project:

class FoodItem < ActiveRecord::Base
  has_and_belongs_to_many :food_categories
  has_many :places, :through => :food_categories
end

class FoodCategory < ActiveRecord::Base
  has_and_belongs_to_many :food_items
  belongs_to :place
end

class Place < ActiveRecord::Base  
  has_many :food_categories
  has_many :food_items, :through => :food_category
end

但调用实例方法some_food_item.places使我有以下错误:

But calling the instance method some_food_item.places gives me the following error:

的ActiveRecord :: StatementInvalid:PGError:错误:列food_categories.food_item_id不存在 线路1:...鞋带.ID =food_categories.place_id WHERE((food_cate ...

ActiveRecord::StatementInvalid: PGError: ERROR: column food_categories.food_item_id does not exist LINE 1: ...laces".id = "food_categories".place_id WHERE (("food_cate...

:选择地方*从地方INNER JOINfood_categoriesON位.ID =food_categories.place_id WHERE((food_categories.food_item_id = 1))

: SELECT "places".* FROM "places" INNER JOIN "food_categories" ON "places".id = "food_categories".place_id WHERE (("food_categories".food_item_id = 1))

这是非常合情合理的 - 因为FoodItem和FoodCategory的HABTMs我有映射表名为food_categories_food_items

Which makes perfect sense - because of the HABTMs on FoodItem and FoodCategory I have the mapping table named food_categories_food_items.

我有什么做的就是some_food_item.places通过映射表看,而不是寻找的food_categories表food_item_id地方是否正确?

What do I have to do to get some_food_item.places to look places up correctly through the mapping table instead of looking for a food_item_id in the food_categories table?

推荐答案

在回答我的第一个版本是不正确的,但是这一次完美的作品。我做了几个错别字的第一次,但这次我验证(不是实际创建一个应用程序来测试这一危险)。和一个插件是必要的,但是这是容易的。首先,安装插件:

My first version of the answer was incorrect, but this one works perfectly. I made a couple of typos the first time (the hazard of not actually creating an app to test) but this time I verified. And a plugin is needed, but this is easy. first, install the plugin:

script/plugin install git://github.com/ianwhite/nested_has_many_through.git

本安装伊恩·怀特的解决办法,它可以无缝地。现在的机型,直接从测试应用程序,我设置复制到得到这个工作:

This installs Ian White's workaround, and it works seamlessly. Now the models, copied directly from the test app I setup to get this working:

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 两者完美的工作,以及所涉及的简单关联。仅供参考,这里是我的架构展现,所有的外键进入:

Now "far" associations work just as well. place_instance.food_items and food_item.places both work flawlessly, as well as the simpler associations involved. Just for reference, here's my schema to show where all the foreign keys go:

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

希望这有助于!

Hope this helps!

更新:这个问题已经拿出了几次最近。我写了一篇文章,nesting你的has_many:通过关系中详细讲解。它甚至有GitHub上的随附示例应用程序下载和玩。

UPDATE: This question has come up a few times recently. I wrote an article, nesting your has_many :through relationships, to explain in detail. It even has an accompanying example application on GitHub to download and play around with.