Rails has_many той же модели, но другого экземпляра - PullRequest
0 голосов
/ 06 января 2020

Я создаю приложение для отслеживания тренировок. В настоящее время мои модели настроены таким образом ... пользователь has_many планирует расписание тренировок has_many, тренировка состоит из множества упражнений и упражнений в кругах has_many (включает в себя повторы / наборы / веса).

Это все работает нормально.

Но теперь я добавляю новые отношения, я не уверен, как их настроить. Я хотел бы иметь новую модель для пользователя has_many "complete_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

1 Ответ

1 голос
/ 06 января 2020

Для этого есть два возможных решения, оба из которых требуют определенной степени избыточности данных.

Решение 1. Добавьте модель user_workout, в которой хранится копия таблицы тренировок на определенный момент времени

. При таком подходе вы можете добавить модель user_workout так, как вы это сделали. запланировано, но вместо сохранения ссылки на workout вы можете скопировать необходимые атрибуты в модель user_workout. Это будет означать, что когда ваши значения workout изменятся позже, ваш user_workout будет продолжать отражать ценность тренировки, которую пользователь выполнил.

Структура таблицы:

  1. user_id: целое число
  2. workout_id: целое число (для справки)
  3. Все остальные столбцы тренировки

Преимущества:

  1. Значения тренировки пользователя не меняются, даже если тренировки меняются

Отключения:

  1. Дублирование данных ( Что в данном случае требуется до некоторой степени)
  2. Всякий раз, когда новые столбцы добавляются к workout, их также необходимо добавить к user_workout.

Однако, в случае, если вы храните значения только для целей отображения и не собираетесь выполнять какие-либо вычислительные операции над ними, вы можете просто иметь поле ha sh с именем worker_snapshot в user_workout вместо всех столбцов. Это позволит преодолеть второй недостаток.

Решение 2. Вносить новую запись в таблицу тренировок всякий раз, когда в нее вносятся изменения

Этот подход предполагает, что тренировки может иметь только фиксированные значения, и если что-то изменится в тренировке, это означает, что создается новая тренировка. Это означало бы, что нет таких вещей, как «обновления» тренировок, а просто создание новых тренировок с измененными значениями старых, если требуется обновление. Таблица user_workout может затем указывать на workout_id напрямую, не беспокоясь об изменении данных тренировки.

Преимущества:

  1. Не требует, чтобы таблица user_workout беспокоилась о изменяется на workouts

Недостатки:

  1. Может привести к переполнению таблицы тренировок

Оба эти подхода могут помочь в работе с вашим сценарием описано. Я лично предпочел бы первый подход с workout_snapshot га sh.

ПРИМЕЧАНИЕ: Я бы рекомендовал отменить нормализацию структуры базы данных. У пары ваших таблиц есть только name столбцы, и они связаны с другими таблицами как отношение многие ко многим. Некоторые вещи, которые я бы порекомендовал изменить:

  1. Вы можете иметь поле name в самом user_schedules и удалить таблицу schedules. У самого user_schedule могут быть различные упражнения.
  2. У упражнения может быть имя, а также workout_id, и таблицу workout_exercises можно удалить.

Эти это всего лишь рекомендации, которые, как я думал, могут помочь уменьшить сложность структуры БД. Я понимаю, что у меня очень ограниченное представление о том, что вы создаете, и эта рекомендация может быть довольно бесполезной, и в этом случае вы можете ее игнорировать!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...