RubyRunt
RubyRunt

Reputation: 13

Has_many, through association

Warning:Total Rails Newb (TRN). This should be a pretty basic question so I'm hoping someone can spare a couple mins to help shed some light.

Let's say I have the following models: User, Group, and Member A user can have many groups (let's say friends, family, etc) A group can have many members, namely other users.

How would I structure this?

Initially I tried this:

class User < ActiveRecord::Base
  has_many :groups
  has_many :groups, :through => :members
end

class Groups < ActiveRecord::Base
  has_many :users, :through => :members
  belongs_to :user
end

class Member < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

However this gave me an error in User so I changed

has_many :groups, :through => :members

to

has_many :memberships, :through => :members, :source => :groups

Still getting an error about missing association when I try to do

group = Group.new
group.user.new

Upvotes: 1

Views: 5139

Answers (3)

fl00r
fl00r

Reputation: 83680

It will be useful: http://railscasts.com/episodes/47-two-many-to-many

class User < ActiveRecord::Base
  has_many :members
  has_many :groups, :through => :members
  has_many :groups_as_owner, :class_name => "Group"
end

class Groups < ActiveRecord::Base
  has_many :members
  has_many :users, :through => :members
  belongs_to :owner, :class_name => "User", :foreign_key => :user_id
end

class Member < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

Upvotes: 6

Ingo
Ingo

Reputation: 1815

basically has_many-through associations are n:m associations (join-tables) that (shall) have more attributes than just the id's of the joined record ids...

so you have a table Groups (with an id), a table Users (with an id) and a table Members (no id, but user_id and group_id)

basically, what you did is nearly correct, just think about how you access a group from a user or vice versa....

a user would first look up its member information and through that member information get access to the group information ... and vice versa for a group

so you first set up

has_many :members

and then call

has_many :groups, :through => :members

all you need is

class User < ActiveRecord::Base
  has_many :members
  has_many :groups, :through => :members
end

class Groups < ActiveRecord::Base
  has_many :members
  has_many :users, :through => :members
end

class Member < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

and you have another bug in your code above

you might want to use

user = group.users.new

instead of

user = group.user.new

Upvotes: 2

megas
megas

Reputation: 21791

Try this structure:

class User < ActiveRecord::Base
  has_many :members
  has_many :groups, :through => :members
end

class Groups < ActiveRecord::Base
  has_many :members
  has_many :users, :through => :members
end

class Member < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

Also take a look at has_and_belongs_to_many, if you don't need to do with class Member then you should use has_and_belongs_to_many. In this case don't forget to create joining table in the database

Upvotes: 1

Related Questions