ruby-on-rails - Rails has_many 相同的模型,但不同的实例
问题描述
我正在构建一个锻炼跟踪应用程序。目前,我的模型设置如下......
这一切都很好。
但是现在我正在添加一个新的关系,我不确定如何设置。我想要一个用户 has_many "completed_workouts" 的新模型,它包含锻炼模型的所有属性。
我的第一个想法是添加一个 user_workout 模型;为用户和锻炼提供外键。但这意味着每当我对锻炼进行更改时,它也会反映在 user.workouts 中;这不是我想要的。
架构.rb
create_table "circuits", force: :cascade do |t|
t.integer "weight"
t.integer "reps"
t.integer "rest"
t.integer "exercise_id"
end
create_table "exercises", force: :cascade do |t|
t.string "name"
end
create_table "schedules", force: :cascade do |t|
t.string "name"
end
create_table "user_schedules", force: :cascade do |t|
t.integer "user_id"
t.integer "schedule_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
t.string "username"
end
create_table "workout_exercises", force: :cascade do |t|
t.integer "workout_id"
t.integer "exercise_id"
end
create_table "workout_schedules", force: :cascade do |t|
t.integer "workout_id"
t.integer "schedule_id"
end
create_table "workouts", force: :cascade do |t|
t.string "name"
end
用户.rb
class User < ApplicationRecord
has_many :user_schedules
has_many :schedules, through: :user_schedules
end
日程安排.rb
class Schedule < ApplicationRecord
has_many :user_schedules
has_many :users, through: :user_schedules
has_many :workout_schedules
has_many :workouts,through: :workout_schedules
accepts_nested_attributes_for :workouts
end
锻炼.rb
class Workout < ApplicationRecord
has_many :workout_exercises
has_many :exercises,through: :workout_exercises
has_many :workout_schedules
has_many :schedules,through: :workout_schedules
end
解决方案
我可以想到两种可能的解决方案,两者都需要一定程度的数据冗余。
解决方案 1:添加 user_workout 模型,该模型存储锻炼表的时间点副本
在这种方法中,您可以按计划添加模型,但您可以将所需的属性复制到user_workout
模型中,而不是只保留对 的引用。这意味着当您的值稍后发生变化时,您将继续反映用户进行的锻炼的价值。workout
user_workout
workout
user_workout
表结构:
- user_id:整数
- 锻炼id:整数(供参考)
- 锻炼的所有其他列
优点:
- 即使锻炼发生变化,用户锻炼值也不会改变
缺点:
- 数据重复(在这种情况下在一定程度上是必需的)
- 每当将新列添加到 时
workout
,它们也需要添加到user_workout
。
但是,如果您只是出于显示目的而存储值并且不打算对它们执行任何计算操作,您可以简单地调用一个哈希字段worker_snapshot
而user_workout
不是所有列。这将克服第二个缺点。
解决方案 2:在锻炼表中创建一个新条目,无论何时对其进行编辑
这种方法假定锻炼只能具有固定值,如果锻炼中有任何变化,则意味着正在创建新的锻炼。这意味着没有锻炼的“更新”之类的东西,而只是在需要更新时使用修改过的旧锻炼值来创建新的锻炼。然后该user_workout
表可以直接指向workout_id
而不用担心锻炼数据的变化。
优点:
- 不需要
user_workout
担心表的变化workouts
缺点:
- 可能会使锻炼表膨胀
这两种方法都可能有助于处理您描述的场景。我个人更喜欢使用workout_snapshot
哈希的第一种方法。
注意:我建议对数据库结构进行非规范化。您的几个表只有name
列,并以多对多关系链接到其他表。我建议改变一些事情:
- 您可以自己拥有一个
name
字段user_schedules
,然后删除该schedules
表。user_schedule
本身可以有各种练习。 - 一个练习可以有一个名字和一个
workout_id
,并且workout_exercises
表格可以被删除。
这些只是我认为可能有助于降低数据库结构复杂性的建议。我知道我对您正在构建的内容的了解非常有限,并且此建议可能毫无用处,在这种情况下您可以忽略它!
推荐阅读
- python-3.x - 检查字符串 A 是否是另一个字符串 B 的子字符串的字谜
- python - 如何解释 LSA 模型的输出?
- acumatica - Acumatica - 引发多个错误/异常
- typescript - Sinon 存根函数不能与函数内部的函数一起使用
- flutter - Cubit State 不会在 BottomSheet 内刷新
- postgresql - PostgreSQL 中的外键过滤
- c# - 无法让 Identity Server 4 API 授权其自己的端点,而是发送登录页面
- python - 用于 KMeans 聚类每次迭代中的标签的 Scikit-learn api
- javascript - 用于 ECDH 输出的 Web 密码学实现 HKDF
- android - 如何在 kotlin 的帮助下从 Cloud Firestore 中删除 recyclerview 项目?