Возможно ли создать условную ассоциацию в модели?


Я настроил систему управления доступом на основе ролей со следующими моделями:

  • роль (как ИППП),
    • роль пользователя (глобальные роли)
    • ProjectRole (проектные роли)
  • назначение (полиморфное с различными ресурсами)
  • пользователь
  • проект (как один из типов ресурсов для назначений)
Пользователи могут отвечать за проект только в том случае, если у них есть определенная роль пользователя. Эта роль пользователя называется " ответственный за проекты " и имеет ID 2.

В пользовательской модели есть две ассоциации has_many: responsible_assignments и responsible_projects. Эти ассоциации действительны только в том случае, если пользователь имеет роль пользователя "ответственный за проекты" с идентификатором 2.

Можно ли создать условную ассоциацию в пользовательской модели для ассоциации responsible_* и является ли это распространенным способом настройки такого рода отношений?

Какова наилучшая практика для решения такого рода проблем?

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

3 ответа:

Вы не можете ставить такие условия в ассоциациях. Такие вещи обрабатываются в области видимости.

Читать http://guides.rubyonrails.org/active_record_querying.html#scopes для получения дополнительной информации.

Пример для вашей ситуации,

Вы хотите, чтобы все назначения (идентификаторы) выполнялись пользователем с определенной ролью проекта

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

Вы хотите, чтобы все проекты (ID), находящиеся под пользователем с определенной ролью проекта, были активны.

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

В случае, если кто - то найдет это позже- эта функция теперь фактически доступна в rails 4:

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

Синтаксис:

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

Эти ассоциации создаются при загрузке модели. Ваше состояние на тот момент неизвестно. Вы можете только включить условия в ассоциации, чтобы отфильтровать нежелательные записи.