Rails has_many 型号相同,实例不同

Rails has_many of same model, but different instance

我正在构建一个锻炼跟踪应用程序。目前,我的模型设置为...... 一个用户 has_many 安排 时间表 has_many 锻炼 一个锻炼有很多练习 一个练习 has_many 电路(包括 reps/sets/weights)。

一切正常。

但现在我要添加一个新关系,但我不确定如何设置。 我想要一个新模型 a user 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

workout.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 模型,用于存储锻炼的时间点副本 table

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

Table结构:

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

优点:

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

缺点:

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

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

解决方案 2:每当对其进行编辑时,为锻炼创建一个新条目table

此方法假定锻炼只能具有固定值,并且如果锻炼中有任何变化,则意味着正在创建新的锻炼。这意味着锻炼没有 "updates" 之类的东西,如果需要更新,只需创建具有旧值修改值的新锻炼。然后 user_workout table 可以直接指向 workout_id 而不必担心锻炼数据发生变化。

优点:

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

缺点:

  1. 可能会使锻炼膨胀 table

这两种方法都可能有助于处理您描述的情况。我个人更喜欢使用 workout_snapshot 散列的第一种方法。

注意: 我建议对数据库结构进行反规范化。您的几个 table 仅具有 name 列,并以多对多关系链接到其他 table。我建议更改的一些内容:

  1. 您可以在 user_schedules 本身中有一个 name 字段,并删除 schedules table。 user_schedule本身可以有各种练习。
  2. 一个练习可以有一个名字和一个 workout_idworkout_exercises table 可以被删除。

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