You can improve your question by showing the code that you're using to query the cancan system (the api calls to cancan).
It looks like you're doing separate queries to see if the user is in the admin, manager, or user category.
You should order the queries to have the most likely user type queried first. Eg, if the odds are that a person is most likely a user, then query for that first.
Even better, cache the user's role in the session. That way you're only doing the queries one time.
Added
You can use after login/logout hooks with devise to set the value in the session. You can look up the role (from the session) with Action Controller filters. Session docs
Security issues
- Use devise after logout hook to clear the role in the session.
- Make sure your tests cover the sessions' role id
- You don't need to worry about people giving self-upgrades to their role: sessions are digitally signed against changes. See the session docs.
- Users being deleted/changed on the fly:
Depending on your level of security, you may need to cover the situation of where a user has been deleted or down-graded and you want the change to take place immediately (rather than waiting until the next time the user logs in).
Doing so can be tricky. Some techniques:
- One way is to store a role-checked-timestamp in the session along with the role_id. Then invalidate the role_id (look it up again) if its been more than 30 min, etc.
- Or store the role_id for the user in memcache, not the session store. Then the other process (which did the delete-user) can remove the role_id values from the cache for active user sessions.
- A simpler, brute force way: give admins a way to clear all current sessions (would require all current users to login again). This would take care of the infrequent situation of having to boot someone off the system.
- As many systems do, timeout all sessions after a couple of hours. Or clear all sessions once per day. If you do this, it is good to implement and test auto re-login. Including returning to the requested page after re-login. The re-login will stop people whose credentials have been changed.
Use constants You can store role_ids in the session (or memcache). But compare them with constants. Eg user.role_id === ROLE_ADMIN You can set constants at run time by looking up the role_ids from the db. Be sure to do this once per rails process in the initialization system. Not once per incoming request.