I am using rails 3.2.14 and devise 3.2.1, and I have an "Admin" with an STI relationship with my devise "User" model.
When I register a new Admin with the form below, I get the following error:
undefined method `new_admin_session_path' for #<ActionDispatch::Routing::RoutesProxy:0x007fa6fe068f18>
because I have:
devise_for :users, :skip => :registrations do
in my routes.
How can I register a new "Admin" and then sign them in as a "User"?
Please note that if I exchange "Admin" for "User" in my form_for, and remove the skip registrations from "User" in my routes, then I get the behaviour I want apart from it is a "User" not an "Admin".
I have created a stand alone application to demonstrate my problem. https://github.com/deathwishdave/devise_test
user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
attr_accessible :email, :password, :password_confirmation, :remember_me
end
admin.rb
class Admin < User
end
index.html.erb
<h2>Sign up</h2>
<%= form_for(Admin.new, :as => :admin, :url => registration_path(:admin)) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email, :autofocus => true %></div>
<div><%= f.label :password %><br />
<%= f.password_field :password %></div>
<div><%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %></div>
<div><%= f.submit "Sign up" %></div>
<% end %>
routes.rb
devise_for :users, :skip => :registrations do
delete '/logout', :to => 'sessions#destroy', :as => :destroy_user_session
get '/login', :to => 'sessions#new', :as => :new_user_session
post '/login', :to => 'sessions#create', :as => :user_session
end
devise_for :admins, :skip => :sessions
authenticated :user do
root :to => "dashboard#index"
end
authenticated :admin do
root :to => "dashboard#index"
end
root :to => 'welcome#index'
Requirements…
Additional Information.
To satisfy these requirements, I considered multiple options including STI, polymorphic associations, authorisation gems and just separate models and tables.
polymorphic associations are a poor choice because the fields between roles are the same, and it may cause difficulties with user creation. Authorisation gems such as cancan are not an option, as the roles have different relationships with other model classes. If I were to use cancan, the User model would be polluted by relationships that don’t apply to all users. Having separate models, and tables would not allow for a single point of entry for all types of user.
STI seems like a good fit because all role fields are the same, so the database will be normalised. Additional users can be added with ease.
And from a purist perspective, it makes sense. My different roles are all users, with a user being an interface or contract for all other specialties.
Based on the requirements and information you give about the user does STI seems like fine solution, especially if there is different logic associated to each user. However polymorphic associations would work fine as well, even if each roles doesn't have any other database informations (see http://railscasts.com/episodes/394-sti-and-polymorphic-associations).
Correct me if im wrong but CanCan seems like a good solution still, also with STI. CanCan is roled based so you can check what type of user you are authorizing and then create the rules (with relations) based on that user type/role.
To answer you actual question on how to login a admin as a user should you be able to simply override the method sign_up
in registration controller, like this:
class Admin::RegistrationsController < Devise::RegistrationsController
def sign_up(resource_name, resource)
sign_in(:user, resource)
end
end
and add the following to your routes:
devise_for :admins, :skip => :sessions, :controllers => { :registrations => "admins/registrations" }
Also i find this link about STI and devise, it's a little different scenario than yours, but properly still some useful hints for you: http://adamrobbie.me/blog/2013-3-29-sti-with-rails-40-beta-and-devise