simple role system through associative table

So I have the Ninja model which has many Hovercrafts through ninja_hovercrafts (which stores the ninja_id and the hovercraft_id).

It is of my understanding that this kind of arrangement should be set in a way that the associative table stores only enough information to bind two different classes.

But I'd like to use the associative table to work as a very streamlined authorization hub on my application. So i'd also like this table to inform my system if this binding makes the ninja the pilot or co-pilot of a given hovercraft, through a "role" field in the table.

My questions are:

Is this ugly?

Is this normal?

Are there methods built into rails that would help me to automagically create Ninjas and Hovercrafts associations WITH the role? For exemple, could I have a nested form to create both ninjas and hcs in a way that the role field in ninjas_hovercrafts would be also filled?

If managing my application roles this way isn't a good idea, whats the non-resource heavy alternative (my app is being designed trying to avoid scalability problems such as excessive joins, includes, etc)

thank you

Daniel,

Adding attributes to the HMT model is an acceptable practice. Originally HABTM was used for many-to-many relationships and it assumed a simple table in the middle with the related ids. The problem was that the relationship table often needed to become a model of its own with additional attributes. This is why HMT came about and is the preferred method for many-to-many relationships.

I am not aware of a way to create all three models with the role in the field as you described. I believe you will have to code that in the controller.

If you do something like this and the association will set the role value for you…

class Pilot < ActiveRecord::Base

belongs_to :ninja

belongs_to :hovercraft

end

class Hovercraft < ActiveRecord::Base

has_many :pilots

has_many :piloted, :conditions => {:role => ‘pilot’}, :class_name => “Pilot”

has_many :copiloted, :conditions => {:role => ‘co-pilot’}, :class_name => “Pilot”

has_many :ninjas, :through => :pilots

has_many :copilot_ninjas, :through => :copiloted, :source => :ninja

has_many :pilot_ninjas, :through => :piloted, :source => :ninja

end

class Ninja < ActiveRecord::Base

has_many :pilots

has_many :piloted, :conditions => {:role => ‘pilot’}, :class_name => “Pilot”

has_many :copiloted, :conditions => {:role => ‘co-pilot’}, :class_name => “Pilot”

has_many :hovercrafts, :through => :pilots

has_many :copiloted_hovercrafts, :through => :copiloted, :source => :hovercraft

has_many :piloted_hovercrafts, :through => :piloted, :source => :hovercraft

end

Then you can do stuff like this…

Create hovercraft

hovercraft = …

Create pilot ninja

pilot_ninja = …

Create co-pilot ninja

copilot_ninja = …

Associate ninjas to hovercrafts

hovercraft.piloted.create(:ninja => pilot_ninja)

hovercraft.copiloted.create(:ninja => copilot_ninja)

Anthony Crumley

http://commonthread.com