I have a base class called User and it has 2 subclasses named Manager and Creator. I have implemented Single Table Inheritance for User, Manager and Creator models.
There are 2 other models named Project and Bug.
class User < ApplicationRecord
end
class Manager < User
end
class Creator < User
end
class Project < ApplicationRecord
end
class Bug < ApplicationRecord
end
The associations I want to have are
I understand the relations but I am unable to understand where to put the associations(for the User and it's subclasses).
For example
For the association: A Creator can create many Bugs
class Creator < User
has_many :bugs
end
Where do I put the other side of the association declaration? Do I write it inside the User class or the Creator class?
i.e
class Bug < ApplicationRecord
belongs_to :user
end
or
class Bug < ApplicationRecord
belongs_to :creator
end
Which one is the right way to do it?
The bottom line of the question is:
In Single Table Inheritance do I make associations(of other models) with the parent model or the child model?
In response to your comment, below is a potential way to model the associations you enumerate using only User
, Project
, Bug
, and ProjectUser
without STI.
A simple way to model A Creator can create many Bugs
might be something like:
class User < ApplicationRecord
has_many :bugs, foreign_key: :creator_id
end
And for your Bug
model:
# == 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
In this case, the role is implied by the association definition, but you don't have an explicit Role
model. So if you have an instance of @user
, you could do something like:
@user.bugs.create bug_attributes
If you have an @bug
, then you can do:
@bug.creator
...and get back the User
that created the Bug
.
Similarly, to model A Manager can have many Projects
, you could do something like:
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
Again, the role is implicit to the association definition. And, with @user
, you can do:
@user.managed_projects.create project_attributes
To model A Project can have many Users
(assuming that a User can belong to many projects
), you could use a ProjectUser
model that might look something like:
# == 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
Then in your Project
, you could do:
class Project < ApplicationRecord
belongs_to :manager, class_name: 'User'
has_many :project_users
has_many :users, through: :project_users
end
And in your User
, you could do:
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
Now you can do things like @project.users
and @user.projects
.
Depending on your domain and use cases, you might want to make Role
an explicit class. But, that's a whole other kettle of fish.