Restful_authentication: authorized? = NoMethodError (but logged_in? works fine…?)


I don't understand why one method would work and the other would throw a NoMethodError if they come from the same lib file.

# app/views/bunnies/show.html.erb
<% if logged_in? %>
  <%= current_user.login %> |
  <%= link_to 'Logout', logout_path %> |
  <% if authorized? %>
    <%= link_to 'Edit Details', edit_bunny_path(@broker) %> |
  <% end %>
  <%= link_to 'Back', bunnies_path %>
<% end %>

… throws a NoMethodError for authorized?. If I comment that if block out, the page works fine (with logged_in?).

# lib/authenticated_system.rb
def logged_in?

def authorized?
  current_user.login == "admin"

# app/controllers/application.rb
class ApplicationController < ActionController::Base
  include AuthenticatedSystem

What gives?

Best Solution

I'm guessing you are not logged in when the error is thrown. The NoMethod is not referring to #authorized?. It is actually referring to the #login method of current_user. If you aren't logged in, then current_user is nil, resulting in NoMethod when current_user.login is called within #authorized?.

Any helper like authorized? that checks user status should include checking logged_in? first to bypass this problem. Try this...

def authorized?
  logged_in? and current_user.login == "admin"

That way you bounce out of the conditional if not logged in, and you don't try to access #login method unless you actually have an object available.

You might also look into some of the available role-based authentication schemes that work with Restful_Authentication. If your access patterns are going to be any more complex than just checking for an admin, then it will be easier to use one of those plugins.

Incidentally, farther down in authenticated_system.rb you will find this code:

# Inclusion hook to make #current_user and #logged_in?
# available as ActionView helper methods.
def self.included(base)
  base.send :helper_method, :current_user, :logged_in?, :authorized? if base.respond_to? :helper_method

This is what makes methods in this module available as helper methods in the views. If you add a method to authenticated_system.rb that returns user status (for instance, something like #superuser?), you will need to add that method symbol to the base.send call in this code. Again, if you find yourself writing a lot of code for access control, learning one of the plugins would be in order.

Related Question