Сериализация разрешений (например, CanCan) с помощью active_model_serializers

Как сериализовать разрешения с помощью active_model_serializers? У меня нет доступа к методу current_user или can? в моделях и сериализаторах.


person Jo Liss    schedule 25.07.2012    source источник


Ответы (3)


Во-первых, чтобы получить доступ к current_user в контексте сериализатора, используйте новую функцию области видимости:

class ApplicationController < ActionController::Base
  ...
  serialization_scope :current_user
end

Если вы создаете сериализаторы вручную, обязательно передайте область действия:

model.active_model_serializer.new(model, scope: serialization_scope)

Затем внутри сериализатора добавьте пользовательские методы, чтобы добавить свои собственные псевдоатрибуты авторизации, используя scope (текущий пользователь) для определения разрешений.

Если вы используете CanCan, вы можете создать экземпляр класса Ability для доступа к методу can?:

attributes :can_update, :can_delete

def can_update
  # `scope` is current_user
  Ability.new(scope).can?(:update, object)
end

def can_delete
  Ability.new(scope).can?(:delete, object)
end
person Jo Liss    schedule 25.07.2012
comment
Я не понимаю, вы сразу ответили на свой вопрос? - person Jesse Wolgamott; 26.07.2012
comment
Да, видел — см. эту статью. Я хотел сохранить эту часть знаний, но нашел ее слишком тривиальной/специализированной для размещения в своем блоге, поэтому я разместил ее здесь, в стиле вопросов и ответов. - person Jo Liss; 26.07.2012
comment
@JoLiss В качестве альтернативы стилю super.merge вы можете сказать attributes :can_update, :can_delete, а затем определить can_update и can_delete как методы в сериализаторе. Хотя и то и другое работает. - person tee; 27.07.2012
comment
Вы также можете делегировать метод can? своей модели для еще большей удобочитаемости — см. stackoverflow.com/a/3293522/797639. - person pierrea; 16.10.2014

Мы создали гем, который обеспечивает эту функциональность: https://github.com/GroupTalent/active_model_serializers-cancan

person ghempton    schedule 20.03.2013

Я думаю, что вы можете передать что угодно serialization_scope, поэтому я просто передаю Способность.

class ApplicationController < ActionController::Base
 ...
 serialization_scope :current_ability

 def current_ability
   @current_ability ||= Ability.new(current_user)
 end

end


class CommentSerializer < ActiveModel::Serializer
  attributes :id, :content, :created_at, :can_update

  def can_update
    scope.can?(:update, object)
  end

end

Я не могу поступить иначе, так как мои способности на самом деле основаны на двух переменных (не в приведенном выше примере).
Если вам все еще нужен доступ к current_user, вы можете просто установить переменную экземпляра в Ability.

person Romain    schedule 23.05.2014