【问题标题】:Rails has_many of same model, but different instanceRails has_many 相同的模型,但不同的实例
【发布时间】:2020-01-06 19:03:50
【问题描述】:

我正在构建一个锻炼跟踪应用程序。目前,我的模型是这样设置的...... 一个用户有_很多时间表 有很多锻炼的时间表 锻炼有很多锻炼 一个练习 has_many 电路(包括代表/组/重量)。

一切正常。

但现在我正在添加一个新的关系,我不确定如何设置。 我想要一个新模型,用户 has_many "completed_workouts" 包含锻炼模型的所有属性。

我的第一个想法是添加一个 user_workout 模型;为用户和锻炼提供外键。但这意味着每当我对锻炼进行更改时,它也会反映在 user.workouts 中;这不是我想要的。

schema.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

user.rb

class User < ApplicationRecord
  has_many :user_schedules
  has_many :schedules, through: :user_schedules
end

schedule.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

【问题讨论】:

    标签: ruby-on-rails foreign-keys relational-database


    【解决方案1】:

    我能想到两种可能的解决方案,都需要一定程度的数据冗余。

    解决方案 1:添加存储锻炼表时间点副本的 user_workout 模型

    在这种方法中,您可以按计划添加user_workout 模型,但您可以将所需的属性复制到user_workout 模型中,而不是只保留对workout 的引用。这意味着当您的workout 值稍后发生变化时,您的user_workout 将继续反映用户进行的锻炼的价值。

    表结构:

    1. user_id:整数
    2. workout_id:整数(供参考)
    3. 锻炼的所有其他列

    优点:

    1. 即使锻炼发生变化,用户锻炼值也不会改变

    缺点:

    1. 数据重复(在这种情况下在一定程度上是必需的)
    2. 每当将新列添加到 workout 时,它们也需要添加到 user_workout

    但是,如果您只是为了显示目的而存储这些值并且不打算对它们执行任何计算操作,您可以在 user_workout 中简单地使用一个名为 worker_snapshot 的哈希字段而不是所有列。这将克服第二个缺点。

    解决方案 2:在锻炼表中创建一个新条目,无论何时对其进行编辑

    此方法假定锻炼只能具有固定值,如果锻炼中有任何变化,则意味着正在创建新的锻炼。这意味着没有锻炼的“更新”之类的东西,而只是在需要更新时使用修改过的旧锻炼值来创建新的锻炼。然后user_workout 表可以直接指向workout_id,而不用担心锻炼数据的变化。

    优点:

    1. 不需要user_workout 表担心对workouts 的更改

    缺点:

    1. 会使锻炼台膨胀

    这两种方法都可能有助于处理您所描述的场景。我个人更喜欢使用workout_snapshot 哈希的第一种方法。

    注意:我建议对数据库结构进行反规范化。您的几个表只有name 列,并以多对多关系链接到其他表。我建议改变一些事情:

    1. 您可以在user_schedules 本身中有一个name 字段,然后删除schedules 表。 user_schedule 本身可以进行各种练习。
    2. 练习可以有一个名称以及一个workout_id,并且可以删除workout_exercises 表。

    这些只是我认为可能有助于降低数据库结构复杂性的建议。我了解我对您正在构建的内容的了解非常有限,并且此建议可能毫无用处,在这种情况下您可以忽略它!

    【讨论】:

    • 感谢您对表格更改的建议。对于我的用例,我认为第一种方法更有意义。如果我采用第一个解决方案,user_workout 模型是否与锻炼模型文件相同?具有相同的关联?
    • 是的,如果您不使用快照哈希,它会。但是,就像我说的,如果只是为了显示或跟踪,我强烈建议只使用单个哈希来保存快照。
    • user_workout 模型上保持关联的缺点是,如果锻炼或它们的关系发生变化,保持关联可能会成为一场噩梦。例如,当与运动相关的电路发生变化时会发生什么?在这种情况下,user_workouts 也将开始指向新电路。这就是我更喜欢解决方案 1 + 快照哈希或解决方案 2 的原因,因为没有哈希的解决方案 1 可能会导致可维护性问题。
    猜你喜欢
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 2019-09-26
    • 1970-01-01
    相关资源
    最近更新 更多