views:

79

answers:

2

I'm using has_many :through to specify a many-to-many association between two entities and I want to be able to retrieve the model from the join table easily. Here are the main entities:

class Group < ActiveRecord::Base
    has_many :memberships
    has_many :members, :through => :memberships
end 

class Member < ActiveRecord::Base
    has_many :memberships
    has_many :groups, :through => :memberships
end

The join table is called 'memberships' and has an additional attribute 'admin' which indicates that the user can act as a group admin for that group. Here's the migration snippit:

create_table :memberships do |t|
  t.integer :group_id
  t.integer :member_id
  t.boolean :admin

  t.timestamps
end

Now, in my controller I want to check if a particular member is an admin of a group. I currently have the following code (which works):

membership = @member.memberships.find_by_group_id(@group.id)

My question: Is there a more elegant way of retrieving the join object (a membership) than using the find_by_group_id helper?

+4  A: 

You could ask:

  @member.is_admin?(@group)

with something like this.

  class Member < ActiveRecord::Base

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

    def is_admin?(group)
      memberships.find_by_group_id(group.id).admin?
    end

  end
eggdrop
Yes, this is nice but I guess what I was really looking for was whether I was overlooking a more natural way of access the join model, without writing a helper.
Denis Hennessy
+4  A: 

Avoding helper methods, you could write:

  @member.admin?(@group)

with something like this (untested!).

  class Member < ActiveRecord::Base

    has_many :memberships
    has_many :groups, :through => :memberships
    named_scope :admin?, :through => :memberships, 
    lambda {|group|:conditions=> ["admin = 'true' and group_id = ?"], group.id }
  end
eggdrop
Thanks - that's very good.
Denis Hennessy