0

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 the client?
  • Is there any way that client.administrators would be an array of users instead of forcing me to client.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 of client.administrators?
  • Do model concerns help here?
  • Is this the right approach for ensuring there is always at least one administrator?
Community
  • 1
  • 1

1 Answers1

0

I believe here is what you're looking for, please namespace appropriately:

class User
  has_many :clients_users
  has_many :clients, through: :clients_users
end

class Client
    has_many :clients_users
    has_many :administrators, through: :clients_users, source: :user
    validates :adminstrators, presence: true # I think this should ensure at least one admin
end

class ClientsUser
    belongs_to :client
    belongs_to :user
end



Client.first.administrators # fetch all adminstrators
Client.first.adminstrators << User.first # add an administrator
oreoluwa
  • 5,553
  • 2
  • 20
  • 27