【问题标题】:Creating a Restaurant Menu should I use a has_many through or habtm association?创建餐厅菜单我应该使用 has_many through 还是 habtm 关联?
【发布时间】:2020-01-08 16:03:26
【问题描述】:

我正在尝试创建一个餐厅项目并为菜单设计数据库。在创建数据库模式时,我似乎一直在思考如何在以下模型MenuItem, Menu, and a Menu Section 之间实现正确的关联。每次我通过has_many :throughhas_and_belongs_to_many 时,我都能看到两者的好处,但是当我实施它们时,我会感到困惑。此外,我对self join 感到困惑,这进一步让我失望。

我认为我的工程过度了,但对数据库架构进行一些输入会有所帮助。更具体地说,您认为我应该在以下场景中使用哪个关联?

到目前为止,我有三个类/表 Restaurant, Menu, and MenuItem 和我精心设计的场景:

class Restaurant
  has_many :menus  (#Desert, Drinks, Dinner, Lunch, etc.)
end

class Menu
  has_many :sections, class_name: "Menu", foreign_key: "sections_id"
  belongs_to :section, class_name: "Menu"

  has_many :menu_items, through: :sections

  belongs_to :restaurant
end

## Context for the Menu and Sections
If I had a drinks menu with the following sections, Non Alcoholic, 
Spirits, Wine, etc. These 'sections' are essentially menus with 
their own menu items. This is why I put a self join on the Menu 
class. Maybe Im mistaken.


 class MenuItem
   belongs_to :section, class_name: "Menu"
   belongs_to :menu
 end 

 ####
 The menu item for example of 'Yellow Tail Merlot' belongs to the 
 section "Wine" under the menu of "Drinks". This is precisely where
 I am getting thrown off. I get the feeling that I'm making this 
 too complicated but when I say it out loud to myself it makes 
 perfect sense. 

好的,现在这里是带有 habtm 的版本 2:

class Restaurant
  has_many :menus  (#Desert, Drinks, Dinner, Lunch, etc.)
end

class Menu
   has_and_belongs_to_many :menu_items
end


 class MenuItem
  has_and_belongs_to_many :menus
  has_and_belongs_to_many :sections, class_name: "Menu"
 end 

如您所见,第 2 版中的上述代码变得繁琐。事实上,我什至不知道 has_and_belongs_to_many 的部分是否可能。无论如何,这是我从 Rails Associations 文档中获取的基本原理。

has_and_belongs_to_many 关联创建与另一个模型的直接多对多连接,没有干预模型。例如,如果您的应用程序包含菜单和菜单项,每个菜单都有许多菜单项,并且每个菜单项出现在许多菜单中,您可以这样声明模型。

引用来自 rails 文档,但我用菜单和菜单项切换了组件和零件。以这种方式阅读它是完全有道理的。所以现在我问,你们怎么看?哪个更好用?谢谢。

【问题讨论】:

  • AFAIK HABTM 在 Rails 4 中被弃用,可能更早。我一直觉得 has_many through: 是一个更清洁的选择
  • 自连接在这里并不重要。一个适用的示例是您有一个用户表,其中员工在users.manager_id 上加入经理(也是用户表上的记录)。您正在构建的是一个层次结构,因此它绝对是适合这项工作的错误工具。

标签: mysql sql ruby-on-rails postgresql database-design


【解决方案1】:

我应该使用 has_many through 还是 habtm 关联?

它们都可以用来创建类似的多对多关联。主要区别在于has_and_belongs_to_many 不使用连接实体的模型。虽然这听起来简单而吸引人,但它确实有一些巨大的缺点:

  • 没有实用的方法可以在连接表上添加访问附加列。例如,您想添加一个“位置”列来对项目进行排序 - 您对 has_and_belongs_to_many 不走运。
  • 无法直接查询连接表。

所以has_and_belongs_to_many 非常适合那些零复杂度的情况,但在现实生活中并不是很好。对于其他所有内容,has_many through:

class Restaurant
  has_many :menus
  has_many :menu_sections, through: :menus
  has_many :menu_items, through: :menu_sections
end

class Menu
  belongs_to :restaurant
  has_many :menu_sections
  has_many :menu_items, through: :menu_sections
end

class MenuSection
  belongs_to :menu
  has_one :restaurant, through: :menu
  has_many :menu_items
end

class MenuItem
  belongs_to :menu_section
  has_one :menu, through: :menu_section
  has_one :restaurant, through: :menu
end

【讨论】:

    【解决方案2】:

    我将使用belongs_to,而不是在菜单表上使用自联接,而是创建一个名为Section 的新类/表。

    更新为:

    class Restaurant
      has_many :menus
    end
    
    class Menu
      has_many :menu_items
      has_many :sections
    
      belongs_to :restaurant
    end
    
    class Section 
      belongs_to :menu
      has_many :menu_items
    end
    
    
    class MenuItem
      belongs_to :menu
      belongs_to :section
    end 
    
    

    您描述的部分是更多类别,例如葡萄酒是一种酒精饮料,葡萄酒是菜单项,“酒精饮料”是类别。您甚至可以更进一步,将 Wine 与“酒”和“饮料”两个部分相关联。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-03
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 2016-08-04
      • 2012-09-18
      • 1970-01-01
      相关资源
      最近更新 更多