I am installing pundit on my app. My RestaurantPolicy file inherits from the ApplicationPolicy one (which by default gives access to none of the methods). When changing the methods in RestaurantPolicy (from false to true) it seems to have no effect as I still have access to none of the methods. BUT when changing falses to trues in the ApplicationPolicy file...I have the accesses ! Any idea why methods in the RestaurantPolicy file do not override the ApplicationPolicy's ones ? Thank youuu!!
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
include Pundit
# Pundit: white-list approach.
after_action :verify_authorized, except: :index, unless: :skip_pundit?
after_action :verify_policy_scoped, only: :index, unless: :skip_pundit?
private
def skip_pundit?
devise_controller? || params[:controller] =~ /(^(rails_)?admin)|(^pages$)/
end
end
restaurants_controller.rb
class RestaurantsController < ApplicationController
before_action :set_restaurant, only: [:show, :edit, :update, :destroy]
def index
@restaurants = Restaurant.all
authorize @restaurants
end
def show
end
def new
@restaurant = Restaurant.new
authorize @restaurant
end
def edit
end
def create
@restaurant = Restaurant.new(restaurant_params)
@restaurant.user = current_user
# OU : @restaurant = current_user.restaurants.build(restaurant_params)
respond_to do |format|
if @restaurant.save
format.html { redirect_to @restaurant, notice: 'Restaurant was successfully created.' }
format.json { render :show, status: :created, location: @restaurant }
else
format.html { render :new }
format.json { render json: @restaurant.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @restaurant.update(restaurant_params)
format.html { redirect_to @restaurant, notice: 'Restaurant was successfully updated.' }
format.json { render :show, status: :ok, location: @restaurant }
else
format.html { render :edit }
format.json { render json: @restaurant.errors, status: :unprocessable_entity }
end
end
end
def destroy
@restaurant.destroy
respond_to do |format|
format.html { redirect_to restaurants_url, notice: 'Restaurant was successfully destroyed.' }
format.json { head :no_content }
end
end
private
def set_restaurant
@restaurant = Restaurant.find(params[:id])
end
def restaurant_params
params.require(:restaurant).permit(:name)
end
end
restaurant.rb
class Restaurant < ApplicationRecord
belongs_to :user
end
user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :restaurants end
application_policy.rb
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
end
restaurant_policy.rb
class RestaurantPolicy < ApplicationPolicy
class Scope < Scope
def index?
true
end
def show?
scope.where(:id => record.id).exists?
end
def create?
true
end
def new?
create?
end
def update?
true
end
def edit?
update?
end
def destroy?
true
end
end
end
You must define your policy methods out of RestaurantPolicy::Scope, like so:
class RestaurantPolicy < ApplicationPolicy
class Scope < Scope
def index?
true
end
end
# Notice we have closed the definition of Scope class.
def show?
scope.where(:id => record.id).exists?
end
def create?
true
end
def new?
create?
end
def update?
true
end
def edit?
update?
end
def destroy?
true
end
end