Как сделать политику экспертов более СУХОЙ?

В одном из моих проектов я начал использовать Pundit Gem, и у меня очень простая политика, которая выглядит так:

class CompanyPolicy < ApplicationPolicy
  def index?
    true if user.is_a? Administrator
  end

  def new?
    true if user.is_a? Administrator
  end

  def create?
    new?
  end

  def edit?
    true if user.is_a? Administrator
  end

  def update?
    edit?
  end
end

И вопрос в том, как я могу избежать повторения этого:

true if user.is_a? Administrator

person Mateusz Urbański    schedule 16.02.2015    source источник
comment
попробуйте использовать before_filter и вызвать его во всех вышеперечисленных методах   -  person Deepesh    schedule 16.02.2015
comment
Это класс политики эксперта, а не контроллер, и я не могу использовать before_filter...   -  person Mateusz Urbański    schedule 16.02.2015


Ответы (3)


Я делаю трюк, который выглядит так:

class ApplicationPolicy

  private

  def self.permit_owner_to(*actions)
    actions.each do |action|
      define_method("#{action}?") do
        owner?
      end
    end
  end

  def owner?
    # owner logic
  end

end

И использовал его в других политиках

class ItemPolicy < ApplicationPolicy

  permit_owner_to :show, :update, :destroy, :confirm

end
person Sebastian    schedule 16.02.2015

Я на самом деле не думаю, что вам нужно удалить это. Повторяя это, вы явно говорите, что этот пользователь должен быть администратором для доступа к этому методу. Если вы действительно хотите, вы можете просто создать частный метод.

class CompanyPolicy < ApplicationPolicy
  def index?
    admin?
  end

  def new?
    admin?
  end

  def create?
    new?
  end

  def edit?
    admin?
  end

  def update?
    edit?
  end

  private 
     def admin?
        user.is_a? Administrator
     end
end

Полагаю, это вопрос личных предпочтений.

person Yule    schedule 16.02.2015
comment
Распределяя этот тест по кодовой базе, вы рискуете столкнуться с большой проблемой, если/когда решите реализовать тест по-другому. Например, что, если вы выбрали роль администратора, а не класс администратора? Много рефакторинга. - person AndyV; 03.03.2015

Вы можете использовать alias_method.

class CompanyPolicy < ApplicationPolicy
  def index?
    user.is_a? Administrator
  end

  alias_method :create?, :index?
  alias_method :update?, :index?
end

У вас есть базовый класс ApplicationPolicy, который, вероятно, уже содержит:

def new?
  create?
end

def edit?
  update?
end

поэтому вам не нужно повторять эти методы в своем подклассе.

.is_a? возвращает true или false, поэтому нет необходимости явно возвращать true if true.

Это намного лаконичнее, а? :)

person Brendon Muir    schedule 20.11.2015