[英]How should I design/structure my database and ActiveRecord associations? has_many :through?
Using Rails 4 (and Postgres), I'm trying to work out the best way in which to structure my ActiveRecord associations and corresponding database tables/relationships for a diet tracking app. 我正在尝试使用Rails 4(和Postgres)来为饮食跟踪应用程序构造ActiveRecord关联和对应的数据库表/关系的最佳方法。
I want my app to be structured as follows: I have Document
and FoodEntry
models. 我希望我的应用程序的结构如下:我有
Document
和FoodEntry
模型。 Each Document
has a number of FoodEntries
. 每个
Document
都有许多FoodEntries
。 I want to be able to iterate over them like document.food_entries.each ...
(which is easy with your typical has_many
association). 我希望能够像
document.food_entries.each ...
那样遍历它们(使用典型的has_many
关联很容易)。
However all the FoodEntries
for each Document
need to be able (potentially but not necessarily) to be subdivided by day , as this is a natural division for which logic and calculations must be able to be performed, in addition to doing them for the whole document. 但是,每个
Document
所有FoodEntries
需要(可能但不一定)按天细分,因为这是自然的划分,除了对整个文档进行逻辑和计算外,还必须能够执行逻辑和计算。 For instance I'd be using something like document.day(1).food_entries.each ...
. 例如,我将使用诸如
document.day(1).food_entries.each ...
。
Furthermore, each day should be able to be subdivided (again, optionally) into meals in a similar manner, eg document.day(1).meal(1).food_entries.each ...
此外,每天应该能够以类似的方式细分(再次,可选地) 进餐 ,例如
document.day(1).meal(1).food_entries.each ...
Lastly, there must be a way to record the user-specified order that the FoodEntries
, meals, and days are in for each document. 最后,必须有一种方法来记录用户指定的每个文档的
FoodEntries
,进餐和天数的订单。 Presumably using number sequence(s)? 大概使用数字序列?
I was thinking there are a few ways I could do this: 我当时在想有几种方法可以做到这一点:
Use a simple has_many
relationship. 使用简单的
has_many
关系。 Have day
, meal
and sort
columns in the food_entries
table, where the value for day
and meal
is left blank or given a default value if a day/meal isn't provided. 在
food_entries
表中有day
, meal
和sort
列,其中day
meal
值保留为空白,或者如果未提供日/餐,则将其设置为默认值。 Use a logic-based approach to get and sort the entries for a day or meal. 使用基于逻辑的方法来获取和分类一天或一餐的条目。
Outline: 大纲:
class Document has_many :food_entries class FoodEntry belongs_to :document
Potential issues: 潜在问题:
Use has_many :through
to set up associations through days
and meals
(naming?) tables. 使用
has_many :through
通过days
和meals
(命名?)表建立关联。 Entries where a day/meal isn't specified get given a default. 未指定日期/餐点的条目将设置为默认值。 Both these tables have their own individual
sort
column, along with the food_entries
table. 这两个表都有自己的单独的
sort
列以及food_entries
表。
Outline: 大纲:
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
Potential issues: 潜在问题:
has_many :food_entries through: ...
in my Document
model if it would have to go through both tables? has_many :food_entries through: ...
在Document
模型中使用has_many :food_entries through: ...
吗? A compromise between the two approaches above: have a days
table but keep meal
in a column in the food_entries
table. 上面两种方法之间的折衷:有一个
days
表,但将meal
放在food_entries
表的一列中。
Something else? 还有吗 Polymorphic association(s)?
多态关联?
This is getting a bit complicated to wrap my head around, and so I'm really having a hard time working out what I should use. 我的头变得有点复杂,所以我真的很难确定应该使用什么。 What is the correct way to go about things?
做事情的正确方法是什么?
A couple of final questions which are related but completely optional: 几个相关的但完全可选的最终问题:
day
value could be either a datetime
value or an arbitrary string, depending on what the user sets. day
值可以是datetime
值或任意字符串,具体取决于用户设置的内容。 Is this possible? has_many :through has_many:通过
You'd only use a has_many :through
relationship if you wanted to attribute multiple FoodEntries
to Document
, like this: 如果要将多个
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
This would only allow you to associate many food_entries
with a similar number of documents
. 这样只会使您将许多
food_entries
与数量相似的documents
相关联。 Although you could add specific days
& meals
attributes to the join model, allowing you to call them as required 尽管您可以将特定的
days
和meals
属性添加到联接模型中,但可以根据需要调用它们
Scopes 领域
I believe a much better option for you is to use ActiveRecord scopes
: 我相信对您来说更好的选择是使用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
Because scopes can be chained, I believe you'd be able to do this: 由于范围可以链接在一起,因此我相信您可以做到这一点:
food = Document.day(1).meal(2).food_entries
Class Method 类方法
You could also create a class_method
to achieve something similar: 您也可以创建
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
I ended up implementing my #2 option. 我最终实现了我的#2选项。 This has given me the most flexibility and worked out well.
这给了我最大的灵活性,并且效果很好。 I think it has been the most elegant approach for my use case.
我认为这对于我的用例来说是最优雅的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.