4

When ever I create a new scaffold I'd like to use it the default pundit config which is available in app/policies/application_policy.rb. Without creating one model_name_policy.rb I always get unable to find policy errors.

How can I use the defaults when I didn't setup rules for a specific model?

wintermeyer
  • 8,178
  • 8
  • 39
  • 85
  • did you ever find a solution to this? I am in the same situation, and am curious about your final approach.. – geoboy Sep 21 '16 at 03:29

3 Answers3

2

The easiest way to do this is probably to rescue from the Pundit::NotDefinedError raised by Pundit::PolicyFinder#policy!.

Given your default policy:

# app/policies/application_policy.rb:
ApplicationPolicy = Struct.new :user, :record do
  def index?
    true
  end

  def show?
    true
  end

  # ... other sensible defaults

end

Assuming you are using this in a Rails controller:

# app/controllers/application_controller.rb:
class ApplicationController
  include Pundit

  # ...

  private

  def policy(record)
    super
  rescue Pundit::NotDefinedError
    ApplicationPolicy.new pundit_user, record
  end
end

Disclaimer: I should also state that creating implicit default policies is generally frowned upon. Except in the simplest cases or with the most pessimistic defaults (all false), it is all too easy for an overly permissive policy to slip through.

Steve
  • 6,618
  • 3
  • 44
  • 42
1

I don't know of a way without create a policy for each model, but you can create a policy that inherits from your application policy. Your ApplicationPolicy might look something like this:

class ApplicationPolicy
  def index?
    true
  end

  def show?
    true
  end

  ... More actions ...
end

When you set up a new scaffold, simply add a blank policy that inherits from your application policy:

class UserPolicy < ApplicationPolicy

end

The actions will inherit from ApplicationPolicy. If needed you can always override the defaults:

classUserPolicy < ApplicationPolicy
  show?
    @user.admin == true ? true : false
  end
end

Hope this helps!

Briant
  • 11
  • 1
  • Thanks for your advise. I'm searching for a true default where I don't have to create a policy file for a new class. – wintermeyer Dec 30 '14 at 11:00
1

I use pundit 2.1.0

authorize or policy_scope method use PolicyFinder to find policy classes, so it is useless to override policy method only if you use authorize or policy_scope to do the thing. I use the following way to set a default policy in my application:

Pundit::PolicyFinder.class_eval do
  def policy
    klass = find(object)
    (klass.is_a?(String) ? klass.safe_constantize : klass) || DefaultPolicy # set a default policy
  end
end

Maybe it is not the best method(it modifies the method in the original lib brutally and violates the design of the lib), but it is enough for me.

May it helps!