Rails 3 / Devise: Checking to see if users have any of multiple roles
I have a users model with Devise, and I've set up roles so users can be assigned either one or multiple roles. If I want to check for a user's role in say, a view, the fo开发者_运维技巧llowing code works...
<% if current_user.roles.include? Role.find_by_name('Administrator') %>
You are an administrator!
<% end %>
But now, let's say I want to check if a user has one of multiple roles, to see if they're either an Administrator or Editor. I was certain the following would work....
<% if current_user.roles.include? Role.find_by_name('Administrator' || 'Editor') %>
...but it doesn't, it only works if you're an administrator and ignores checking all other roles after the first one in that list. I've tried other combinations like Role.find_by_name(['Administrator','Editor']) and whatnot, to no success. Exactly how would I format this to accomplish checking for multiple roles? I've hunted all over Google but all examples uses a single role.
The first problem is that when you use the syntax 'Administrator' || 'Editor' it will not create an sql OR syntax. Instead what happens is that Ruby evaluates that 'Administrator' is considered a TRUE value and passes it on to the find_by_name method. Editor never gets send.
The second problem is that even if you change the syntax to ['Administrator', 'Editor'], the find_by_name method always returns only one record.
So I would probably do something like this:
Role.where(:name => ['Administrator', 'Editor']).all
That will return those two roles.
Edit
I thought a litte further about this because it's not really a best practice solution to place this kind of database logic in the views. Here is another way that is a little more along the MVC concept:
class User < ActiveRecord::Base
...
def has_role?(*role_names)
self.roles.where(:name => role_names).present?
end
end
# In the views
<% if current_user.has_role?('Administrator', 'Editor') %>
You should have a look on cancan: http://railscasts.com/episodes/192-authorization-with-cancan It will help you to keep authorization rules in one place, not spreading it through your views and controllers.
With devise 3 and above use current_user.has_any_role?(:Administrator, :Editor)
Below are all the devise methods for checking role that can be used;
current_user.has_role?(role_name, resource = nil)
current_user.has_all_roles?(*args)
current_user.only_has_role?(role_name, resource = nil)
current_user.has_any_role?(*args)
精彩评论