views:

215

answers:

3

I have a model class that has, among other things:

class Group < ActiveRecord::Base
  has_many :subscriptions
  has_many :users, :through => :subscriptions

  has_many :admins, :through => :subscriptions, :source => :user, :conditions => "subscriptions.role = #{ROLES[:admin]}"
  has_many :subscribers, :through => :subscriptions, :source => :user, :conditions => "subscriptions.role >= #{ROLES[:subscriber]}"
  has_many :authors, :through => :subscriptions, :source => :user, :conditions => "subscriptions.role >= #{ROLES[:author]}"
  has_many :pending_subscribers, :through => :subscriptions, :source => :user, :conditions => "subscriptions.pending = true"
end

The number of times :through => :subscriptions, :source => :user is repeated bothers me. I know in routes files, you can do map.with_options. Is there something like that for my model associations?

+2  A: 

You can create a method that calls has_many with the common conditions. Here's one way of drying it up with a block:

{ :admins => "subscriptions.role = #{ROLES[:admin]}",
  :subscribers => "subscriptions.role = #{ROLES[:subscriber]}",
  :authors => "subscriptions.role >= #{ROLES[:author]}",
  :pending_subscriptions => "subscriptions.pending = true" }.each do |property, condition| 
  has_many key, :through => :subscriptions, :source => :user, :conditions => condition
end
Chuck
+9  A: 

with_options is actually an extension on Object, so you can use it in your ActiveRecord::Base as well

with_options :through => :subscriptions, :source => :user do |obj|
  obj.has_many :admins, :conditions => "subscriptions.role = #{ROLES[:admin]}"
  obj.has_many :subscribers, :conditions => "subscriptions.role >= #{ROLES[:subscriber]}"
  obj.has_many :authors, :conditions => "subscriptions.role >= #{ROLES[:author]}"
  obj.has_many :pending_subscribers, :conditions => "subscriptions.pending = true"
end
Rob Di Marco
This worked great, thanks!
Matt Grande
A: 

Hi, This topic has been very useful for me. I've just implemented the solution of Rob and it works just fine !

Now I want to edit the group via a form. In the controller, I use

group.update_attributes(params[:group])

In my form I make the distinction between admins, subscribers, authors with different multiple select list.

But the new records in the subscriptions table got all the column role as NULL.

Any idea how to specify the role ?

Matt Grande