RankFu: Expressive user roles for Rails

Almost every Rails developer has written an app with more than one user role, but when is_admin? isn’t enough, where do you go? RankFu aims to solve this by giving you a rich toolset for roles. Now it’s free to allow users to have more than one role, so you can have modifiers such as ‘Trusted’ and ‘New’ trivially. It’s also easy to have sets of roles, with administrators outranking moderators. Sets are optional though, so you’re free not to put Telephone Sanitizers in one due to their obvious lack of importance.

Throughout this piece, I’ll be talking about the ubiquitous User model, but you can use RankFu with any model you wish to.

Rankin’ Fu

When you install RankFu, you can add several new methods to your models:

 User#has_role?  User#has_role User#"#{role}?" User#"#{role}_exactly?"	#This forces an exact comparison, useful if you want to test for a role which has a superset (e.g. moderators and  administrators) User#"make_#{role}           User#"remove_#{role}"  User#rank				#Returns a string listing all roles, modifiers first eg: "Trusted Administrator"  User#roles				#Returns an array of role names. 

There is also some sugar for disabling users, to make your code more readable. These examples assume the existence of role with :disabled as its key:

 User#disable_user  User#enable_user User#enabled?                        

Building on this, you can easily clean up your views. I DRY’d up many instances login check logic.

 def logged_in_as_mod? def logged_in_as?(user)   def logged_in_as_friend_of?(user)   def logged_in_as_or_as_friend_of?(user)    

There might have been a few others, but I don’t want to give any more ammunition to those who accuse me of pedantry.

InstallationFu

The easiest way to install is as a standard Rails plugin:

script/plugin install git://github.com/mjt/rank_fu.git

After installing this plugin, you’ll want to start by performing some admin:

 script/generate rank_fu user script/generate rank_fu roles 		#create migration for roles  

After that, you’ll probably want to add roles to your user model, so just add this line:

knows_rank_fu

Then you need to create some roles. I suggest using the excellent Seed Fu plugin so you can do something like this:

 Role.destroy_all roles = [ {:id => 1, :key => "root",      :name=> "Superuser", :value => 2**22, :set => 1}, 	      {:id => 2, :key => "admin",     :name=> "Administrator", :value => 2**21, :set => 1}, 	      {:id => 3, :key => "moderator", :name=> "Editor", :value => 2**20, :set => 1},      	      {:id => 5, :key => "member",    :name=> "Member", :value => 2**10, :is_default => true}]  roles.each do |role|                             Role.create role end 

What’s going on here?

Not much.

Internally, bitwise arithmetic is used to store each model’s role-state. Once a model knows RankFu, you can assign and remove roles freely, knowing that RankFu is a good citizen and uses update_attribute internally.

You may also find that you can reduce your use of STI by separating users by roles.

Please feel free to leave any feedback in the comments.