See it working at https://single-page-signup-signin.herokuapp.com/
A demo application for single page login registration using devise and without overriding any devise standard controller methods (index, new, show, edit, delete, destroy)
- Of course Devise will have to be installed in the app. Also it's convenient for the developers to generate the views of devise. It helps to do everybody's favourite task (copy & paste). Generate a user model.
- Generate a controller (in this example
dashboards_controller) that can be used as the root directory after authentication. It uses a show method for this task. Set the root path asroot to: 'dashboards#show'and appendbefore_action :authenticate_user!to thedashboards_controller. Also it's good to be able to logout. Adding the following code snippet to views/dashboards/show.html.erb does just that.<h2>Hello <i><%= @user.email %></i></h2> <% if user_signed_in? %> <li> <%= link_to('Logout', destroy_user_session_path, method: :delete) %> </li> <% else %> <li> <%= link_to('Login', new_user_session_path) %> </li> <% end %>
- Now the app needs a single controller and view to render the registration and login form. Generate a new controller and view (in this example
contents_controllerandcontents#new). Now copy and paste (cause we love it) the contents ofapp/views/users/registrations/new.html.erbandapp/views/users/sessions/new.html.erbtoapp/views/contents/new.html.erb(only if you follow me blindly otherwise different) respectively. Now the views should not find resources. To fix this, add following code toapp/helpers/contents_helper.rbmodule ContentsHelper def resource_name :user end def resource @resource ||= User.new end def devise_mapping @devise_mapping ||= Devise.mappings[:user] end end
- Now some housekeeping stuffs. First of all generate
RegistrationsControllerthat inheritsDevise::RegistrationsControllerandSessionsControllerthat inheritsDevise::SessionsController. Configure theroutes.rblike the following.Rails.application.routes.draw do root to: 'dashboards#show' devise_for :users, controllers: { registrations: 'registrations', sessions: 'sessions' } resources :contents end
The following cases should be realized. These are discussed and the way to overcome them are shown in the steps to follow.
- When user logs out, the browser does not get redirected to the
content#newrather it is redicted tosessions#new. To Overcome that add the following code to yourapp/controllers/application_controller.rbprotect_from_forgery with: :exception private def authenticate_user! unless user_signed_in? redirect_to new_content_path end end
- When there is some sort of failure in login process, it does not get redirected to the
content#newrather it is redicted tosessions#new. Following steps should overcome it.- Create
lib/custom_failure.rband add the following codeclass CustomFailure < Devise::FailureApp def redirect_url new_content_path end def respond if http_auth? http_auth else redirect end end end
- Configure the
config/initializers/devise.rbwith the followingconfig.warden do |manager| manager.failure_app = CustomFailure end
- Lastly, add the library file to the
config/application.rbconfig.autoload_paths << Rails.root.join('lib')
- Create