Rails: определение политики с помощью pundit, которая зависит от того, какую страницу посещает пользователь

У меня есть та же часть в рельсах, которая требуется на двух страницах, которая показывает список сообщений. Первая — это страница новостной ленты, вторая — страница «подробности».

В первом пользователь не должен иметь возможности редактировать, во втором — должен.

Партиал примерно такой:

<%= best_in_place_if policy(post).update?,
                     blahblah...
                     %>
<% end %>

Политика реализована так:

class PostPolicy < ApplicationPolicy
  include ActionView::Helpers::UrlHelper

  ...

  def update?
    ((@record.open? && not_blocked?) ||
    owner? ||
    collaborator?) &&
    !news_feed?
  end
  private

  def news_feed?
    current_page?(action: 'authenticated')
  end

  ...
end

Но похоже, что я не могу получить доступ к методу current_page?. Есть ли способ узнать из политик, какую именно страницу я посещаю?

Спасибо


person ProGM    schedule 01.07.2014    source источник
comment
Является ли current_page? вспомогательным методом в ваших контроллерах/представлениях?   -  person Vapire    schedule 03.07.2014
comment
@Vapire api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html Я пытался импортировать его, но у него много различий...   -  person ProGM    schedule 03.07.2014


Ответы (2)


Другим возможным решением может быть следующее:

class PostPolicy < ApplicationPolicy
  # remove this: include ActionView::Helpers::UrlHelper
  ...

  def news_feed?
    ApplicationController.helpers.current_page?(action: 'authenticated')
  end

  ...
end

См. этот RailsCast и этот поток Stackoverflow для получения дополнительной информации.

person Vapire    schedule 03.07.2014
comment
Использование ApplicationController.helpers.current_page? подвергает вас проблемам с безопасностью потоков на определенных веб-серверах. - person Benj; 08.07.2014
comment
Не могли бы вы уточнить это и / или, может быть, предоставить ссылку на некоторые ресурсы? - person Vapire; 08.07.2014
comment
Потому что helpers — это метод класса. Очень полезно для доступа к помощникам представлений вне представления. Но помощники представлений являются модулями и не зависят от вашего запроса. Здесь вы пытаетесь получить доступ к current_page?, который является методом, который зависит от текущего состояния вашего контроллера (т.е. запроса), поэтому вы должны получать данные из экземпляра контроллера, а не из каких-либо методов/переменных класса. Это очень простые соображения безопасности потоков OO. - person Benj; 08.07.2014

Классы Pundit не имеют доступа к вашим контроллерам, поэтому изначально вы не можете вызывать какой-либо помощник, который использует состояние или данные контроллера. Единственное решение, которое я вижу, это передать action_name в качестве параметра вашему методу политики.

<%= best_in_place_if policy(post).my_method(action_name), ... %>

Затем

class PostPolicy < ApplicationPolicy
  # Remove this: include ActionView::Helpers::UrlHelper

  def my_method(action_name)
    action_name == 'update' and ...
  end

end

Изменить

Мне не нравится использовать ApplicationController.helpers.current_page? из-за рисков проблем с безопасностью потоков на некоторых веб-серверах, поэтому я советую передать параметр в метод вашей политики, чтобы устранить все риски.

person Benj    schedule 03.07.2014