Role Up

CanCan extension that adds some real-deal syntax and file organization lovin'!

Warning

  • THIS SHOULD BE FIXED - Changing rules in an ability class is not reflected on page reload in development mode

TODO

  • WRITE MORE Integration tests utilizing a complete Rails application
  • Tests against CanCan 2.0 code base

Convention

Authorization definitions with CanCan quickly become verbose in complex applications. By breaking them up per model and being able to depend on a few common extras, we can drastically clean up our code. Let's look at the following directory structure...

- app/
  - abilities/
    + widget_ability.rb
  - controllers/
  - etc...

As you can see, we've added a new folder to the app/ directory in our project. Here, we'll create an ability file for each of our models that need it to define our authorization abilities.

Ability Files

Here's an example ability file...

# app/abilities/widget_ability.rb
class WidgetAbility < Ability

  define_rules do |user|
    can :manage , Widget , :user_id => user.id
  end

end

The define_rules method accepts a block and yields the current authorization instance. This might be a User object, an instance of what is specified in the RoleUp.setup block, or the instance provided when the Ability class was instantiated. In this block, the standard CanCan ability definitions methods apply. If you have a set of standard authorization rules, you can reopen the provided Ability class and define a standard_rules block. Check it...

# app/abilities/ability.rb
class Ability

  standard_rules do |user|
    if user.admin?
      can :manage , :all
    end
  end

end

Standard rules will get evaluated last, and therefore take highest priority.

Model and Controller Helpers

The standard CanCan helpers apply.

Setup

You can configure the class that RoleUp will use to authorize with in the gem's setup block. The default is :user. You can also pass class constants or strings as opposed to a symbol e.g.

# app/initializers/role_up.rb
RoleUp.setup do |config|
  config.authorization_class = :cool_user # => CoolUser
  # or
  config.authorization_class = CoolUser # => CoolUser
  # or
  config.authorization_class = "cool_user" # => CoolUser
  # or
  config.authorization_class = "my_namespace/cool_user" # => MyNamspace::CoolUser
  # or
  config.authorization_class = "MyNamespace::CoolUser" # => MyNamspace::CoolUser
end