I have a data model that requires different roles on different
objects.
I was storing the object/user/role relationship in a memberships
model. The object is polymorphic. The role was basically an
enumeration of strings (owner, manager, member, etc).
The Migration:
create_table :relationships do |t|
t.references :user, :role
t.references :context, :polymorphic => true
t.timestamps
end
Relationship < ActiveRecord:Base
belongs_to :context, :polymorphic => true
belongs_to :user
belongs_to :role
Business
has_many :memberships, :class_name => 'Relationship', :conditions =>
{ :role => 'member' }
has_many :members, :through => :memberships, :source => :user
This did not work - the SQL generated for the join was barfing due to
the automated way rails generates join table name aliases. It
wouldn't recognize the 'role' column.
SO, then I tried Single Table Inheritance.
I created a Relationship class that had subclasses for Membership,
Ownership, etc.
When I tried to set up the Business
Business
has_many :memberships
has_many :members, :through => :memberships, :source => :user
has_many :ownerships
has_many :owners, :through => :ownerships, :source => :user
The sql generated by declarative auth to determine privileges ignored
the single table inheritance and returned the same list for members as
owners. A user with any relationship had every relationship. Just
using active record, the list of business.owners and business.managers
was correct. Not sure why declarative auth was unable to use this.
Back to the drawing board...
I ultimately created multiple tables (one for each role) and a module
to define 'Relationship'.
module Relationship
def self.included(base)
base.class_eval do
belongs_to :context, :polymorphic => true
belongs_to :user
validates_uniqueness_of :user_id, :scope =>
[:context_id, :context_type]
end
end
end
And for Membership, Ownership, etc. they are setup like so...
class Membership< ActiveRecord::Base
include Relationship
end
I like this as it is really fast for declarative auth to get the list
of users as you suggest, the downside of course - I have multiple
tables that are all pretty similar. Would rather use the STI.
- Mark