3
votes

I'm starting with the Rails 4.1 Pundit / Devise app from RailsApps.org and continue to get undefined method errors when 'authorize User' is called in the User controller. The user can register, log in, and edit their account info. When the Users link is clicked, the following results:

NoMethodError in UsersController#index

undefined method `authorize' for #

Here is the UsersController...

class UsersController < ApplicationController

  before_filter :authenticate_user!
  after_action :verify_authorized

  def index
    @users = User.all
    authorize User    # <== This is the line the error occurs on
  end

  def show
    @user = User.find(params[:id])
    authorize @user
  end

  def update
    @user = User.find(params[:id])
    authorize @user
    if @user.update_attributes(secure_params)
      redirect_to users_path, :notice => "User updated."
    else
      redirect_to users_path, :alert => "Unable to update user."
    end
  end

  def destroy
    user = User.find(params[:id])
    authorize user
    user.destroy
    redirect_to users_path, :notice => "User deleted."
  end

  private

  def secure_params
    params.require(:user).permit(:role)
  end

end

and the ApplicationController:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end

Any thoughts on how to resolve this?

Thanks in advance!

Comment: This is from the RailsApp Pundit Quickstart guide to explain authorize

The keyword authorize is a helper method that provides a shortcut to a longer statement that implements the actual authorization. We never see the full statement because we use the helper method, but if we were to use it, it would look like this:

raise "not authorized" unless UserPolicy.new(current_user, User).index?

The authorize helper method finds a UserPolicy class and instantiates it, passing the current_user object and either the User class or an instance of the User model, and calling an index? method to return true or false. You may wonder why we can provide either the User class (as in the index action) or the @user instance variable (as in the show action).

Pundit looks for a policy object when authorize is called from a controller action. We already saw that Pundit will find a UserPolicy if given any of these arguments:

  • authorize User – the User class

  • authorize @user – an instance variable that is an instance of the User class

  • authorize user – a simple variable that is an instance of the User class

  • authorize @users – an array of User objects

To me, it seems as if the helper method is found sometimes like in show and update but not index.

2

2 Answers

3
votes

It looks like this issue is being discussed here: https://github.com/RailsApps/rails-devise-pundit/issues/10

Basically, your solutions are to: A) Restart the rails server and the problem should go away. You will have to do this whenever the problem shows up (editing the file, etc). (It shouldn't happen in production if it's any consolation)

B) Move the code in config/intiializers/pundit.rb in to ApplicationController (without the included do...end block)

0
votes

User is a class name, not an instance. Also authorize used for create/update/edit actions. For index you should use Policy.

For example, UserPolicy:

def index
  @users = UserPolicy::Scope.new(current_user, User).resolve
end