在 Rails 的单表继承中在哪里写关联?
Posted
技术标签:
【中文标题】在 Rails 的单表继承中在哪里写关联?【英文标题】:Where to write associations in Single Table Inheritance in rails? 【发布时间】:2019-10-14 13:07:10 【问题描述】:我有一个名为 User 的基类,它有两个名为 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
我想要的联想是
一个项目可以有多个用户 一个经理可以有多个项目 一个创造者可以创造许多错误我理解这些关系,但我无法理解将关联放在哪里(对于用户及其子类)。 例如 对于关联:一个 Creator 可以创建许多 Bug
class Creator < User
has_many :bugs
end
关联声明的另一面应该放在哪里?我是写在 User 类还是 Creator 类中? 即
class Bug < ApplicationRecord
belongs_to :user
end
或
class Bug < ApplicationRecord
belongs_to :creator
end
哪一种方法是正确的? 问题的底线是: 在单表继承中,我是与父模型还是子模型建立关联(其他模型)?
【问题讨论】:
User
、Manager
和 Creator
看起来都像是由 Person
担任的角色。我对您的域一无所知,但 STI 不是我的首选方法。
你建议用什么来代替 STI?我应该将所有这些实体作为我的域模型的一部分。
【参考方案1】:
作为对您的评论的回应,下面是一种潜在的方法,可以对您枚举的关联进行建模,仅使用 User
、Project
、Bug
和 ProjectUser
,而不使用 STI。
模拟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
...取回创建Bug
的User
。
同样,要对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
设为显式类。但是,这完全是另一回事。
【讨论】:
以上是关于在 Rails 的单表继承中在哪里写关联?的主要内容,如果未能解决你的问题,请参考以下文章