A Fresh Cup is Mike Gunderloy's software development weblog, covering Ruby on Rails and whatever else I find interesting in the universe of software. I'm a full-time Rails developer and contributor, available for long- or short-term consulting, with solid experience in working as part of a distributed team. If you'd like to hire me, drop me a line. I'm also the author of Rails Rescue Handbook and Rails Freelancing Handbook.

Navigation
« Rails Release Dates | Main | Double Shot #324 »
Friday
31Oct2008

Filtering View Content by Role in Rails

It seems that a lot of the Rails applications I've been working on have a User model that has a many-to-many relation with a Role model, so that users can have a role like "admin" or "manager", or even multiple roles. Along with this comes the necessity to conditionally show things in views. Recently I've started moving away from having explicit @current_user.has_role("whatever") calls in the views, to some code in the application_helper.rb file:

[sourcecode language='ruby']
module ApplicationHelper

def admin_only(&block)
role_only("administrator", &block)
end

def manager_only(&block)
role_only("manager", &block)
end

private

def role_only(rolename, &block)
if not @current_user.blank? and @current_user.has_role?(rolename)
block.call
end
end
end
[/sourcecode]

Now in views I can easily mark off sections that should be displayed to only one user type:

[sourcecode language='ruby']
<% admin_only do %>

<% end %>
<% manager_only do %>

<% end %>
[/sourcecode]

It would be easy to extend the role_only method to take an array of roles and check for membership in any of them, but I haven't had need of that yet.

Hat tip to Aaron Longwell for introducing me to this technique.

Reader Comments (3)

Perfect, I had hacked something together to handle manager / employee views but this makes it a bit simpler. I'll give it a try tonight.

October 31, 2008 | Unregistered CommenterJohn

Nice solution. I've often wondered how to clean up the front end code and make anything on the View appear(or not appear) based on a role and still have nice clean code.

While I like putting all of your code in once place, I really don't like to modify production code every time there's a need to protect something.

One idea that I've worked with is URL parsing and storing the role/permission in the DB. It's very flexible.

I store the permission utilizing the rails convention of controller and action. Storing the path in the DB and assign it to a role. Then assign that role to a user. Now I can protect create, edit, update, delete per controller with very little code.

On the front end I say and my library will parse the path and check if they have that permission. While this abstracts some of the conditional logic on the front end but doesn't totally eliminate it. It does offer some very nice fine grained control.

November 6, 2008 | Unregistered CommenterBill Davenport

no reason why this same method and methodology couldn't be applied to a before_filter eh? of course we'd change the method's location from the ApplicationHelper to the ApplicationController or lib/ (which is my preference).

security wise, since it's server side, there isn't really any way a curl'r or someone nefarious could get around this, is there?

March 24, 2009 | Unregistered Commenterpjammer

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>