I have setup a role based access controll system with the following models:
Users are only allowed to be responsible for a project if they have a specific UserRole. This Userrole is name "responsible for projects" and has ID 2.
In User model there are two has_many associations :responsible_assignments and responsible_projects. This associations are only valid if the user has the UserRole "responsible for projects" with ID 2.
Is it possible to create a conditional association in user model for responsible_* association and is this a common way to setup this kind of relations?
What is the best practise to solve this kind of problems?
class Role < ActiveRecord::Base
has_many :assignments
has_many :users, :through => :assignments
class UserRole < Role
class ProjectRole < Role
class Assignment < ActiveRecord::Base
belongs_to :user
belongs_to :role
belongs_to :resource, :polymorphic => true
class User < ActiveRecord::Base
has_many :assignments
has_many :roles, :through => :assignments,
:class_name => "UserRole"
has_many :responsible_assignments, :class_name => "Assignment",
:conditions => { :role_id => 4 } // specific project role
has_many :responsible_projects, :through => :responsible_assignments,
:source => :resource,
:source_type => 'Project',
:conditions => { :status => 1 } // project is active
...
class Project < ActiveRecord
...
You cannot put such conditions in associations. Such things are handled in scopes.
Read http://guides.rubyonrails.org/active_record_querying.html#scopes for more information.
Example for your situation,
You want all assignments (ids) under a user with a specific project role
scope :responsible_users, where('users.role_id = 4')
scope :select_assignment_ids, select('assignments.id')
scope :responsible_assignments, joins(:assignments).responsible_users.select_assignment_ids
You want all projects (ids), under a user with a specific project role, which are active.
scope :active_projects, where('projects.status = 1')
scope :select_project_ids, select('projects.id')
scope :responsible_projects, joins(:assignments => :projects).responsible_users.active_projects.select_project_ids