Reputation: 21877
I have two tables:
Users
and Groups
a User has_many groups and a group, has_many a users:
u = User.last
u.groups
g = Group.last
g.users
Supposed I wanted a second list of different groups, for some strange reason. Where once again a User has may groups (called other_group in this example) and a group has many users.
u = User.last
u.other_groups
g = Group.last
g.other_users
How do I associate two models in this relationship, twice using Active Record? Do I need multiple has and belongs to many tables? perhaps a has and belongs to many "through". What does this look like?
Answer:
class Matter < ActiveRecord::Base
has_many :matters_lawfirms
has_many :matters_other_lawfirms
has_many :lawfirms, class_name: 'Lawfirm', through: :matters_lawfirms, :source => :lawfirm
has_many :other_lawfirms, class_name: 'Lawfirm', through: :matters_other_lawfirms, :source => :lawfirm
end
class Lawfirm < ActiveRecord::Base
has_many :matters_lawfirms
has_many :matters_other_lawfirms
has_many :matters, class_name: 'Matter', through: :matters_lawfirms, :source => :matter
has_many :other_matters, class_name: 'Matter', through: :matters_other_lawfirms, :source => :matter
end
class MattersLawfirm < ActiveRecord::Base
belongs_to :matter
belongs_to :lawfirm
end
class MattersOtherLawfirm < ActiveRecord::Base
belongs_to :matter
belongs_to :lawfirm
end
migrations:
class AddMatterOtherLawfirms < ActiveRecord::Migration
def change
create_table :matters_other_lawfirms, :id => false do |t|
t.references :matter, :lawfirm
end
add_index :matters_other_lawfirms, [:matter_id, :lawfirm_id],
name: "matters_other_lawfirms_index",
unique: true
end
end
class AddMatterLawfirmsHabtmt < ActiveRecord::Migration
def change
create_table :matters_lawfirms, :id => false do |t|
t.references :matter, :lawfirm
end
add_index :matters_lawfirms, [:matter_id, :lawfirm_id],
name: "matters_lawfirms_index",
unique: true
end
end
Upvotes: 0
Views: 2036
Reputation: 1645
Assuming you already know how to handle has_many relationships in your data model (the point to which Alper appears to be writing), it's quite easy to accomodate multiple relationships between two tables (I do something right now which involves linking users distinctly to a projects on which they are working, and to projects which they own. I believe this is very similar to what you're seeking to accomplish). The code would look something like this:
User Model
has_many :regular_groups, class_name: 'Group', through: :user_regular_groups
has_many :other_groups, class_name: 'Group', through: :user_other_groups
Group Model
has_many :regular_users, class_name: 'User', through: :user_regular_groups
has_many :other_users, class_name: 'User', through: :user_other_groups
Obviously in this case we're using two distinct association tables (user_regular_groups and user_other_groups), but you could accomplish something similar with one using a scope (along the lines of what Alper is recommending).
I hope that helps!
Upvotes: 0
Reputation: 2694
You simply can't define many to many relationship using belong_to
You should implement has_and_belongs_to_many
or has_many :through
relationship instead of has_many
- belongs_to
relationship.
EDIT
Ok i think i get it now,
You can't achive this using a single has_and_belongs_to_many table, i'd go for a has_many :through relation. If you have only two group category, set a flag for that category in your join table.
Not tested yet, but something similar should work
class GroupMembership #.. with category field or something
belongs_to :group
belongs_to :user
class User
has_many :group_memberships
has_many :local_groups, -> { where group_memberships: { category: 'local' } }, :through => :group_memberships, :source => :group
has_many :outside_groups, -> { where group_memberships: { category: 'outside' } }, :through => :group_memberships, :source => :group
class Group
has_many :group_memberships
has_many :local_users, -> { where group_memberships: { category: 'local' } }, :through => :group_memberships, :source => :user
has_many :outside_users, -> { where group_memberships: { category: 'outside' } }, :through => :group_memberships, :source => :user
For the HABTM relationship, you need to define more then one join table.
Upvotes: 0