Problem
I have two models a client
and a user
.
A client
can have many administrators
and a user
can be the administrator
of many clients
.
I found a couple of people that suggest using has_many :through
is the better way to model this relationship in my situation versus has_and_belongs_to_many
.
User model
class V1::User < ActiveRecord::Base
has_many :administrators,
class_name: 'V1::ClientAdministrator'
has_many :clients,
through: :administrators
class_name: 'V1::Clients'
Client model
class V1::Client < ActiveRecord::Base
has_many :users,
class_name: "V1::User"
has_many :administrators,
through: :users,
class_name: "V1::ClientAdministrator"
validates :administrators,
length: { minimum: 1}
ClientAdministrator model
class V1::ClientAdministrator < ActiveRecord::Base
belongs_to :v1_user
belongs_to :v1_client
end
Demo using rails c
u = V1::User.create!(name: 'test_user')
c = V1::Client.new(name: 'test_client')
c.administrators << u
ActiveRecord::AssociationTypeMismatch: V1::ClientAdministrator(#70347494104080) expected, got V1::User(#70347494299440)
Before switching to has_many :through
I was successfully using has_and_belongs_to_many
:
class V1::Client < ActiveRecord::Base
has_and_belongs_to_many :administrators,
-> { uniq },
join_table: :v1_client_administrators,
foreign_key: "v1_client_id",
association_foreign_key: "v1_user_id",
class_name: "V1::User"
The problem with this approach was I was not able to do any validation on the association such as before_destroy make sure there is still one administrator. Additionally, it's likely that I'll add metadata to that relationship in the future.
The ASK
- How can I get / set the
administrators
of theclient
? - Is there any way that
client.administrators
would be an array of users instead of forcing me toclient.administrators.each { |admin| admin.user}
to get access to the user? (If I eventually add metadata this probably can't doesn't make sense) - Is there a way to restrict the use of
client.users
in favor ofclient.administrators
? - Do model concerns help here?
- Is this the right approach for ensuring there is always at least one
administrator
?