ProGM
ProGM

Reputation: 7108

Rails: defining policy with pundit that depends on which page the user is visiting

I have the same partial in rails that is required in two pages, that shows a list of posts. The first is a news feed page, the second is a "details" page.

In the first one the user shouldn't be able to edit, in the second he should be able to.

The partial is something like that:

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

The policy is implemented like that:

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

But it seems that I can't access to method current_page?. Is there a way to know from policies what is the actual page I'm visiting?

Thank you

Upvotes: 0

Views: 714

Answers (2)

Benjamin Bouchet
Benjamin Bouchet

Reputation: 13181

Pundit classes does not have access to your controllers so natively you cannot call any helper that uses controller state or data. The only solution I see is to pass action_name as a parameter to your policy method

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

Then

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

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

end

Edit

I don't feel good like using ApplicationController.helpers.current_page? because of risks of thread safety issue on certain web servers, so I advise to pass the parameter to your policy method to eliminate all risks

Upvotes: 2

Vapire
Vapire

Reputation: 4588

Another possible solution might be to do this:

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

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

  ...
end

See this RailsCast and this Stackoverflow thread for more.

Upvotes: 1

Related Questions