Reputation: 2204
This question is for Rails 3.0.0.
I have 5 tables (contrived but reasonable example, only 4 matter):
capabilities
id
name
capability_roles
role_id
capability_id
user_roles
user_id
role_id
users
id
name
roles
id
name
Basically capabilities connects to roles_capabilities connects to user_roles connects to users.
The *_roles tables are simply maps. They have no primary key. The roles table itself is almost incidental to this question.
This allows the capabilities of each role be edited independently of the roles users are allowed to assume.
It would be nice to simply figure out which capabilities a user has.
Now set up associations:
users
has_many :user_roles # .joins( :user_roles ).to_sql # works
user_roles
belongs_to :user # .joins( :user ).to_sql # works
# .joins( :capability_roles ).to_sql # works (no corresponding belongs_to!)
has_many :capability_roles, :primary_key => role_id, :foreign_key => :role_id
# .joins( :capabilities ).to_sql # fails
has_many :capabilities, :through => :capability_roles
capability_roles
belongs_to :capabilities # .joins( :capabilities ).to_sql # works
# .joins( :user_roles ).to_sql # works (no corresponding belongs_to!)
has_many :user_roles, :primary_key => role_id, :foreign_key => :role_id
# .joins( :users ).to_sql # fails
has_many :users, :through => :user_roles
capabilities
has_many :capability_roles # .joins( :capability_roles ).to_sql # works
My question is:
Why doesn't has_many :through work here?
It seems like what has_many :through was designed for. I'm not sure if the missing/irrelevant belongs_to()'s are an issue.
The failure I see is: NoMethodError: undefined method `eq' for nil:NilClass
Upvotes: 2
Views: 379
Reputation: 2554
The join tables you are using are designed for has_and_belongs_to_many
relationships, not has_many
, and are not expected to have associated classes. I'd go with something like this:
Role
has_and_belongs_to_many :capabilities
has_and_belongs_to_many :users
User
has_and_belongs_to_many :roles
has_many :capabilities # use SQL with sub-select through roles to get the capabilities
Capability
has_and_belongs_to_many :roles
has_many :users # use SQL with sub-select through roles to get the users
Upvotes: 2