Is it possible to create a conditional association in model?

15,009

Solution 1

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

Solution 2

In case anyone finds this later - this feature is now actually available in rails 4:

http://guides.rubyonrails.org/association_basics.html

Syntax is:

has_many :orders, -> { where processed: true }

Solution 3

Those associations are created on loading the model. Your condition is unknown at that time. You can only include the conditions in the associations to filter out unwanted records.

Share:
15,009
tonymarschall
Author by

tonymarschall

Updated on June 05, 2022

Comments

  • tonymarschall
    tonymarschall almost 2 years

    I have setup a role based access controll system with the following models:

    • Role (as STI),
      • UserRole (global roles)
      • ProjectRole (project specific roles)
    • Assignment (Polymorphic with different resources)
    • User
    • Project (as one resource type for assignments)

    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
      ...