public
Rubygem
Description: Generic roles for you and your objects
Homepage: http://github.com/nakajima/roleful/tree/master/spec/roleful_spec.rb
Clone URL: git://github.com/nakajima/roleful.git
name age message
file .gemified Mon Oct 27 18:36:24 -0700 2008 added installation info [Pat Nakajima]
file README.textile Loading commit data...
directory lib/ Mon Dec 01 18:37:58 -0800 2008 removed dependency on nakajima gem, bumped up v... [Pat Nakajima]
file roleful.gemspec
directory spec/ Mon Dec 01 18:14:20 -0800 2008 fixed bug where #with_role would blow away sing... [Pat Nakajima]

Role-ful

Roles for you and your objects.

Like it? Then please recommend me on Working with Rails.

Usage

In your class, after including Roleful, declare your roles. It’s up to you to implement a role instance method for your objects that determines what kind of permissions they receive.

If an object doesn’t have a role method, or if the role returns an invalid role, the :null role will be used, which just returns false for all permissions.

Example Class:

class User
  include Roleful

  def initialize(name=nil)
    @role = name
  end

  def role
    @role
  end
end

Basic permissions

The role class method allows you to declare permissions for a given role:

class User

  role :admin do
    can :view_all_files
    can :view_all_pages
  end

  role :paid do
    can :view_all_pages
    can :view_invoice
  end

end

gets you:

User.new.null? # => true
User.new.can?(:view_invoice) # => false
User.new.can_view_all_pages? # => false
User.new.can_view_all_files? # => false

User.new(:paid).paid? # => true
User.new(:paid).can?(:view_invoice) # => true
User.new(:paid).can_view_all_pages? # => true
User.new(:paid).can_view_all_files? # => false

User.new(:admin).admin? # => true
User.new(:admin).can?(:view_invoice) # => false
User.new(:admin).can_view_all_pages? # => true
User.new(:admin).can_view_all_files? # => true

Super-users

If you pass role the :superuser option, then objects with that role will be considered super-users, meaning every permission declared for that class will be available:

class User

  role :super_admin, :superuser => true

end
User.new(:super_admin).can_view_all_pages? # => true
User.new(:super_admin).can_view_all_files # => true
User.new(:super_admin).can?(:view_invoice) # => true

Declaring permissions for more than one role

Sometimes you want to add the same permission to multiple roles. To do this, simply pass multiple role names when calling role, and each of the roles will be granted the permissions declared in the block.

Alternatively, you can just pass :all to role, and all of your roles besides the :null role will be granted the permissions declared in the block.

class User
  role :foo, :bar do
    can :be_both
  end

  role :all do
    can :pay_the_billz
  end
end
User.new(:foo).can_be_both? # => true
User.new(:bar).can_be_both? # => true
User.new(:admin).can_be_both? # => false

User.new(:foo).can_pay_the_billz? # => true
User.new(:bar).can_pay_the_billz? # => true
User.new(:admin).can_pay_the_billz? # => true

# The :null role still returns false
User.new(:null).can_pay_the_billz? # => false

Objects with more than one role

If an object’s role returns an Array, then the object will be granted all of the roles in that Array.

class User
  role :foo do
    can :be_foo
  end

  role :bar do
    can :be_bar
  end
end
user = User.new([:foo, :bar])

user.foo? # => true
user.bar? # => true

user.can_be_foo? # => true
user.can_be_bar? # => true

Advanced Permissions

Sometimes a permission is contingent upon some other conditions being met. You can handle these situations by passing the can call a block. This block will be called in the context of your object:

class User
  role :thinker do
    can :be_self do |that|
      self == that
    end
  end
end
me  = User.new(:thinker)
you = User.new(:thinker)

me.can_be_self?(me) # => true
me.can_be_self?(you) # => false

Role contexts

If you want to temporarily give an object a role, you can use the with_role method:

class User
  role :admin do
    can :do_anything
  end
end
user = User.new

user.admin? # => false
user.can_do_anything? # => false

user.with_role(:admin) do
  user.admin? # => true
  user.can_do_anything? # => true
end

user.admin? # => false
user.can_do_anything? # => false

Install

Install roleful like so:

gem install nakajima-roleful --source=http://gems.github.com

View the CI build

(c) Copyright 2008 Pat Nakajima, released under the MIT license