Как я могу создать область в модели, которая возвращает только те объекты с соответствующим рангом, превышающим ранг current_user?

Я пытаюсь создать область :readable в моей модели Page, чтобы вернуть все Pages, которые current_person имеют достаточный «ранг» для чтения:

scope :readable, lambda { |current_person| joins(:role_readable)
    .where(:role_readable[:rank].gte(current_person.roles.first.rank) ) }

Я пробовал много перестановок области, в том числе эту, безуспешно (приведенная выше дает ошибку «не удается преобразовать символ в целое число»).

Проблема усложняется тем, что Users (обрабатывающие аутентификацию и т. д. / синонимичные учетным записям) имеют_множество People, которые представляют присутствие User в организации, т.е. User может быть членом нескольких организаций, но ему нужен только один способ входа в систему...

Roles, из которых User's People имеет_много, дают ранг, который область использует для возврата :readable страниц. (т. е. Users обрабатывает аутентификацию, тогда как People обрабатывает авторизацию (среди прочего), поскольку User может быть членом нескольких организаций, для которых пользователь имеет разные Roles и, следовательно, иерархию и привилегии.)

class User < ActiveRecord::Base  
  has_many :people
  has_many :roles, through: :people    

class Person < ActiveRecord::Base
  belongs_to :user
  has_and_belongs_to_many :roles

class Role < ActiveRecord::Base
  #  name       :string(255)
  #  rank       :integer 
  has_and_belongs_to_many :people

class Page < ActiveRecord::Base
  belongs_to :role_readable, class_name: "Role", foreign_key: :role_read_id
  belongs_to :role_editable, class_name: "Role", foreign_key: :role_write_id

Роли имеют иерархию (например, Босс, Менеджер, Рабочий...), записанную как rank (целое число) — чем ниже целое число, тем выше иерархия (и, следовательно, привилегия). Если какой-либо из Roles Человека имеет ранг меньше или равен :role_readable из Page, то пользователь имеет право просматривать страницу.

Например. Person с ролью Manager может просматривать все страницы с :role_readable из Manager или Worker, но не Boss. Мне нужна область, в которой перечислены все такие читаемые страницы.

Roles имеют default_scope, который гарантирует, что они возвращаются в порядке возрастания ранга, поэтому role.first для Person будет возвращать роль с наибольшей иерархией (т. е. с самым низким значением ранга).

Я использую Rails 3.2 и Postgres 9.2.2.0, поэтому меня также смущает множество доступных опций query/Arel.

Заранее спасибо!

ОБНОВЛЕНИЕ:

Если я попробую эту область:

scope :readable, lambda { |current_person| where("role_readable.rank
  => ?",current_person.roles.first.rank) }

Я получаю эту ошибку:

PGError: ERROR:  missing FROM-clause entry for table "role_readable"
LINE 1: ...*) FROM "pages"  WHERE "pages"."team_id" = 2 AND (role_reada...
                                                         ^
: SELECT COUNT(*) FROM "pages"  WHERE "pages"."team_id" = 2 AND (role_readable.rank => 1)

Я не уверен, что делать с «отсутствующим предложением FROM»


person djoll    schedule 18.03.2013    source источник


Ответы (1)


И ответ довольно прост, после долгих экспериментов:

scope :readable, lambda { |current_person| joins(:role_readable)
      .where(["roles.rank >= ?", current_person.roles.first.rank]) }

Хотя объединение относится к имени ассоциации :role_readable, где должно использоваться имя таблицы, т.е. roles.rank не role_readable.rank.

Ловушка для новых игроков? Видимо.

Спасибо ctcherry и его ответу здесь, который выдал игру.

person djoll    schedule 18.03.2013