I've been searching through the Devise RDocs, Google, on this site for answers to my question, but no luck.
Let's say I have four Devise scopes/roles, and each one has their own attributes, login page, and separate web flows:
All of these use the User class and have the following attribues in common.
Here is an example of the routes I have established to set this up:
devise_for :students, :class_name => 'User'
devise_for :professors, :class_name => 'User'
devise_for :deans, :class_name => 'User'
devise_for :faculties, :class_name => 'User'
devise_for :users
Then I generated the devise scoped views and played around with those.
After that I had to add some code in my application controller to override Devise::RegistrationsController which wanted to route everything to the root path:
def after_sign_in_path_for(resource)
user_role = resource.role
case user_role
when "professor"
professors_url
when "faculty"
faculties_url
when "dean"
deans_url
when "student"
students_url
else
root_path
end
end
def after_sign_out_path_for(resource)
case resource
when :faculty
new_faculty_session_path
when :professor
new_professor_session_path
when :dean
new_dean_session_path
when :student
new_student_session_path
else
root_path
end
end
I have access to excellent helpers such as signed_in? which tells me if any user in any one of the scopes mentioned above is logged in. Great!!! Now I need similar functionality for current_user.
I have access to the following helpers.
They work perfectly, but here is where I have issues. Let's say if I have a view that shares all of these scopes. Now if I try current_student on that view and I'm logged in as a professor it won't work.
For example: I have a partial that I want to include on every page to allow users to logout if they're logged in. This is how I went about it for a student. Works just fine.
<% if student_signed_in? %>
<div style="float: right;">Welcome <%= current_student.name %></div>
<div>
<%= link_to('Logout', destroy_student_session_path, :method => :delete) %>
</div>
<% end %>
What I want to do is something like this which will provide the ability to logout all my scopes/resources regardless if I'm logged in as a student, dean, professor, or faculty:
<% if signed_in? %>
<div style="float: right;">Welcome <%= current_resource.name %></div>
<div>
<%= link_to('Logout', destroy_resource_session_path, :method => :delete) %>
</div>
<% end %>
My next step would have been to add my own helper methods to determine the scope like so:
def current_resource
current_professor unless current_professor.nil?
current_student unless current_student.nil?
current_dean unless current_dean.nil?
current_faculty unless current_faculty.nil?
end
def destroy_resource_session_path
destroy_professor_session_path unless current_professor.nil?
destroy_student_session_path unless current_student.nil?
destroy_dean_session_path unless current_dean.nil?
destroy_faculty unless current_faculty.nil?
end
If this approach will work, I'd do it, but it seems highly inefficient and tedious if I decide to add more roles or common functionality in the future...
There has to be a better way? This makes me feel like I'm using Devise incorrectly, or am just missing something somewhere.
After much more research I found a Gem called CanTango that does exactly what I was looking for. It works with Devise and handles multiples User model types. Take a look and see.
https://github.com/kristianmandrup/cantango/wiki/Cantango-with-devise-accounts
Thanks for answering my questions guys. I learned a lot from your answers.