MayMay
Installation
gem install may_may
Usage
MayMay automatically restricts access to actions on all controllers and then allows you to specify permitted actions. Because an action is restricted by default, you will never accidentally allow all users access to a new action that should have been restricted. Permitted actions are all listed in one place (a May model) for ease of maintenance.
No need to name roles in your views
Simplify your views. Show/hide view elements based on intended action instead of current user's roles:
<% may? (:edit, :people) do %>
  <%= link_to 'only visible if user may edit people', edit_people_path %>
<% end %>
Create a model named "may":
# in app/models/may.rb
class May
  May.permission_setup do
    controller :people do
      may :index # anyone can execute the index action
      may :create, :only => [:administrator] # only the administrator may create a person
      may :edit, :except => [:guest] # everyone except guests may edit a person
      may [:new, :update] do
        # return true to allow these actions
        # block executed in controller's scope
      end
    end # :destroy was never mentioned and so is not permitted for anyone
  end
end
Add a role_names method to your User object
Here is a simple example setup:
# in app/models/role.rb
class Role
  # roles table should have a "name" column
end
# in app/models/user_role.rb
class UserRole
  has_many :roles
end
# in app/models/user.rb
class User
  has_many :user_roles
  has_many :roles, through: :user_roles
  def role_names
    roles.map {|role| role.name.to_sym }
  end
end
# in app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  def current_user
    @current_user ||= User.find(session[:user_id]) rescue nil
  end
  def current_user=(value)
    value ? session[:user_id] = value.id : session.delete(:id)
    @current_user = value
  end
end
The important thing is to return an array of roles that can be matched against the roles specified in your May model. Your array may contain whatever types you'd like -- strings, symbols, models. Symbols are probably most readable, however, hence the example above.
You could instead define permissions within the controller itself:
class UsersController
  may :index, only: [:some, :roles]
  may :show, method: [:may_show?]
end
In more depth
MayMay adds a few methods to ActionController::Base:
*** may (class method)
Define permissions in your controller instead of May model. Shortcut for May.may(self, ...)
Usage:
class SomeController < ApplicationController
  may :index, except: [:this_role]
end
*** current_roles
Returns current_user.role_names or empty array if current_user returns nil or is missing
*** has_role?
Check current_roles for a specific role.
Usage: if has_role? :some_role
*** may? (helper method)
Check for permission to perform an action.
Usage: if may? :action_name, :controller_name
Licence
MIT-LICENSE