Где писать ассоциации в Single Table Inheritance в рельсах? - PullRequest
0 голосов
/ 14 октября 2019

У меня есть базовый класс с именем User, и у него есть 2 подкласса с именами Manager и Creator. Я реализовал наследование одной таблицы для моделей User, Manager и Creator.
Есть 2 другие модели с именами Project и Bug.

class User < ApplicationRecord
end

class Manager < User
end

class Creator < User
end

class Project < ApplicationRecord
end

class Bug < ApplicationRecord
end

Ассоциации, которые я хочу иметь,

  • Проект может иметь много пользователей
  • У менеджера может быть много проектов
  • Создатель может создавать много ошибок

Я понимаю отношения, но не могу понять, где разместить ассоциации (для пользователя и его подклассов),
Например,
Для ассоциации: Создатель может создать много ошибок

class Creator < User
   has_many :bugs
end

Где я могу разместить другую сторону декларации ассоциации? Я пишу это внутри класса User или класса Creator?
то есть

class Bug < ApplicationRecord
   belongs_to :user
end

или

class Bug < ApplicationRecord
   belongs_to :creator
end

Какой из них является правильным способом сделать это?
Суть вопроса в следующем:
В наследовании одной таблицы я устанавливаю ассоциации (других моделей) с родительской моделью или дочерней моделью?

1 Ответ

1 голос
/ 14 октября 2019

В ответ на ваш комментарий ниже приведен потенциальный способ моделирования перечисляемых ассоциаций с использованием только User, Project, Bug и ProjectUser без ИППП.

Простой способ моделирования A Creator can create many Bugs может выглядеть примерно так:

class User < ApplicationRecord
  has_many :bugs, foreign_key: :creator_id
end

А для вашей Bug модели:

# == Schema Information
#
# Table name: bugs
#
#  id                     :integer          not null, primary key
#  creator_id             :integer
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#
class Bug < ApplicationRecord
  belongs_to :creator, class_name: 'User'
end

В этом случаероль подразумевается определением ассоциации, но у вас нет явной модели Role. Поэтому, если у вас есть экземпляр @user, вы можете сделать что-то вроде:

@user.bugs.create bug_attributes

Если у вас есть @bug, то вы можете сделать:

@bug.creator

.. .и верните User, который создал Bug.

Аналогично модели A Manager can have many Projects вы можете сделать что-то вроде:

class User < ApplicationRecord
  has_many :bugs, foreign_key: :creator_id
  has_many :managed_projects, class_name: 'Project', foreign_key: :manager_id
end

# == Schema Information
#
# Table name: projects
#
#  id                     :integer          not null, primary key
#  manager_id             :integer
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#
class Project < ApplicationRecord
  belongs_to :manager, class_name: 'User'
end

Опять же, роль неявнаяк определению ассоциации. А с @user вы можете сделать:

@user.managed_projects.create project_attributes

Для модели A Project can have many Users (при условии, что User can belong to many projects), вы можете использовать модель ProjectUser, которая может выглядеть примерно так:

# == Schema Information
#
# Table name: project_users
#
#  id                     :integer          not null, primary key
#  project_id             :integer
#  user_id                :integer
#  created_at             :datetime         not null
#  updated_at             :datetime         not null
#
class ProjectUser < ApplicationRecord
  belongs_to :project
  belongs_to :user
end

Тогда в вашем Project вы можете сделать:

class Project < ApplicationRecord
  belongs_to :manager, class_name: 'User'
  has_many :project_users
  has_many :users, through: :project_users
end

А в вашем User вы можете сделать:

class User < ApplicationRecord
  has_many :bugs, foreign_key: :creator_id
  has_many :managed_projects, class_name: 'Project', foreign_key: :manager_id
  has_many :project_users
  has_many :projects, through: :project_users
end

Теперь вы можетеделайте такие вещи, как @project.users и @user.projects.

В зависимости от вашего домена и вариантов использования, вы можете сделать Role явным классом. Но это совсем другой котелок с рыбой.

...