user3586702 user3586702 - 5 months ago 9
Ruby Question

Rails has_and_belongs_to_many relations with two types of Users and one type of Table

I have a problem related with this association. A pasted code is better than any title:

table.rb

class Table < ActiveRecord::Base
has_and_belongs_to_many :clients, class_name: 'User'
has_and_belongs_to_many :managers, class_name: 'User'
end


user.rb

class User < ActiveRecord::Base
has_and_belongs_to_many :tables
end


migration - join table

class UsersToTable < ActiveRecord::Migration
def change
create_table :tables_users, id: false do |t|
t.references :user, as: :client
t.references :user, as: :manager
t.references :table
end
end
end


Problem

tab = Table.new
tab.save
tab.clients.create
tab.clients.create
tab.clients.create
tab.managers.create

tab.managers.size # == 4
tab.clients.size # == 4


When I creating associated Objects(Users) they all are linked to both clients and managers.
I want to be able to create them separately - When creating a client - only number of clients rise, when creating manager, only number of managers rise.
In other words I want this:

tab.managers.size # == 1
tab.clients.size # == 3


Could you please help?

Answer

has_and_belongs_to_many :stuff, class_name: 'StuffClass' is just DSL for:

has_many "<inferred_join_table_name>"
has_many :stuff, through: "<inferred_join_table_name>"

It seems that since clients and managers are names for Users, the inferred join table get's to be "TablesUsers", and that is not right.

Try specifyng the join table for both and using different join tables for each relationship:

class Table
  has_many :tables_clients
  has_many :clients, through: :tables_clients

  has_many :tables_managers
  has_many :clients, through: :tables_managers
end

class TablesClients
  belongs_to :client, class_name: 'User'
  belongs_to :table
end

create_table :tables_clients, id: false do |t|
  t.references :client, index: true
  t.references :table, index: true
end

# and the same for tables_managers

Then the user belongs to Tables in too different ways:

class User
  has_many :client_tables_users, class_name: 'TablesUsers', foreign_key: :client_id
  has_many :tables_as_client, through: :client_tables_users, source: :table

  has_many :managed_tables_users, class_name: 'TablesUsers', foreign_key: :manager_id
  has_many :managed_tables, through: :managed_tables_users, source: :table
end
Comments