在rails中加入has_many_through

时间:2018-11-25 16:15:18

标签: ruby-on-rails join associations has-many-through has-many

我有以下三种型号。

class Order
 belongs_to :item
 belongs_to :category
end

class Item
 has_many :orders
 belongs_to :category
end

class Category
 has_many :items
 has_many :orders, through: :items
end

我想加入Order.joins(:item).joins(:category)之类的表,但是不起作用。

所需的SQL是

SELECT * FROM `orders` 
INNER JOIN `items` ON `items`.`id` = `orders`.`item_id` 
INNER JOIN `categories` ON `items`.`category_id` = `categories`.`id`

希望您能帮上忙。

3 个答案:

答案 0 :(得分:1)

您要寻找的语法是

Order.joins(item: :category)

检查here以获得更多信息。

答案 1 :(得分:1)

我有点困惑,因为Order和Item都属于Categories和Category已经具有该设置的许多Orders,:through选项是不必要的。

对于您想要的输出,我想您想进行嵌套联接(顺序>项目>类别),而不是多个联接(顺序>项目+类别)

https://guides.rubyonrails.org/active_record_querying.html#joining-multiple-associations

  

12.1.3.1加入嵌套关联(单个级别)   Article.joins(评论::guest)

     

这将产生:

     

选择文章。*从文章     内联接在comments.article_id = article.id上发表评论     INNER JOIN来宾上guest.comment_id = comments.id

因此,您应该执行类似Order.joins(item: :category)

的操作

答案 2 :(得分:1)

设置这些关联的正确方法是:

class Order < ApplicationRecord
  belongs_to :item
  # This references items.category_id
  has_one :category, through: :item
end

class Item < ApplicationRecord
  has_many :orders
  belongs_to :category
end

class Category < ApplicationRecord
  has_many :item, through: :orders
  has_many :orders
end

您要删除orders.category_id列(如果存在),并通过items表使用间接关联以避免重复。 belongs_tohas_one的语义可能会造成混淆,但是belongs_to假定外键在此模型(顺序)上,而has_one放在其他型号表(项目)上。

这将使您可以通过以下方式加入/包含/渴望加载关联:

irb(main):002:0> Order.joins(:category)
  Order Load (1.4ms)  SELECT  "orders".* FROM "orders" INNER JOIN "items" ON "items"."id" = "orders"."item_id" INNER JOIN "categories" ON "categories"."id" = "items"."category_id" LIMIT $1  [["LIMIT", 11]]

正如您所看到的,Rails会自动处理联接表(项目)。

如果您希望同时加载两个关联,则可以使用散列或仅列出两者:

Order.eager_load(item: :category) 
Order.eager_load(:item, :category)