使用Rails 4(和Postgres),我试图找出构建我的ActiveRecord关联和相应的数据库表/关系的最佳方式,用于饮食跟踪应用程序。
我希望我的应用程序结构如下:
我有Document
和FoodEntry
个模型。每个Document
都有FoodEntries
个。我希望能够像document.food_entries.each ...
一样迭代它们(通过典型的has_many
关联很容易)。
然而,每个FoodEntries
的所有Document
都需要能够(可能但不一定)被天细分,因为这是逻辑的自然划分除了为整个文档执行计算之外,还必须能够执行计算。例如,我使用的是document.day(1).food_entries.each ...
。
此外,每天应该能够以类似的方式(再次,可选地)细分为饭菜,例如document.day(1).meal(1).food_entries.each ...
最后,必须有一种方法来记录每个文档的FoodEntries
,用餐和日期的用户指定顺序。大概是使用数字序列?
我在想我有几种方法可以做到这一点:
使用简单的has_many
关系。 day
表中包含meal
,sort
和food_entries
列,如果没有提供日/餐,day
和meal
的值保留为空白或给出默认值。使用基于逻辑的方法来获取和分类一天或一餐的条目。
概要
class Document
has_many :food_entries
class FoodEntry
belongs_to :document
潜在问题:
使用has_many :through
通过days
和meals
(命名?)表格设置关联。日期/用餐不是&#39的条目; t指定获得默认值。这两个表都有自己的sort
列,以及food_entries
表。
概要
class Document
has_many :days
has_many :meals, through: :days
has_many :food_entries, through: :days (AND :meals???)
class Day
belongs_to :document
has_many :meals
has_many :food_entries, through: :meals
class Meal
belongs_to :day
has_many :food_entries
class FoodEntry
belongs_to :meal
潜在问题:
has_many :food_entries through: ...
模型中使用Document
,如果它必须通过两个表格?上述两种方法之间的折衷方案:拥有days
表,但在meal
表格的列中保留food_entries
。
还有别的吗?多态关联?
这让我的头脑变得有点复杂,所以我真的很难解决我应该使用的东西。 正确处理事情的方法是什么?
一些相关但完全可选的最终问题:
day
值可以是datetime
值或任意字符串,具体取决于用户设置的内容。这可能吗?答案 0 :(得分:1)
has_many:通过
如果您想将多个FoodEntries
归因于Document
,则只能使用has_many :through
关系,如下所示:
#app/models/document.rb
Class Document < ActiveRecord::Base
has_many :food_entries_types
has_many :food_entries, through: :food_entries_types
end
#app/models/food_entry_type.rb
Class FoodEntryType < ActiveRecord::Base
belongs_to :document
belongs_to :food_entry
end
#app/models/food_entry.rb
Class FoodEntry < ActiveRecord::Base
has_many :food_entries_types
has_many :documents, through: :food_entries_types
end
这只允许您将多个food_entries
与相似数量的documents
相关联。虽然您可以添加特定的days
&amp; meals
属性为连接模型,允许您根据需要调用它们
<强>作用域强>
我相信更好的选择是使用ActiveRecord scopes
:
#app/models/document.rb
Class Document < ActiveRecord::Base
has_many :food_entries
#uses [wday][3]
#needs to return dates for specific day
scope :day, ->(day = 1) { where(created_at: Date::DAYNAMES[day]) }
scope :meal, ->(meal = 1) { where(meal: meal) }
end
由于范围可以链接,我相信你能够做到这一点:
food = Document.day(1).meal(2).food_entries
课程方法
您还可以创建class_method
来实现类似的目标:
#app/models/document.rb
Class Document < ActiveRecord::Base
has_many :food_entries
def self.sorted(day = 1, meal = 1)
document = self.where("created_at = ? AND meal = ?", Date::DAYNAMES[day], meal)
end
end
#app/controllers/documents_controller.rb
def show
@document = Document.sorted
end
答案 1 :(得分:0)
我最终实现了我的#2选项。这给了我最大的灵活性并且运作良好。我认为这是我用例最优雅的方法。