Devise override redirect after form submit - ruby-on-rails

How can I configure my Rails app such that after the form to create a new user is submitted (through devise), I redirect to my own desired page ?
Thank you

After the create user form is submitted the user is created and then logged in so the page you are being redirected to is actually the after log in page. If you only want to change this page when a user is created you can set session["#{resource_name}_return_to"] in a custom registration controller like this:
class Users::RegistrationsController < Devise::RegistrationsController
def create
session["#{resource_name}_return_to"] = some_custom_path
super
end
end
You can also create a root route for your user object in routes.rb which will redirect all users whenever they log in:
match "user_root" => "users#home"
Finally you can define the after_sign_in_path_for(resource_or_scope) method in your application_controller and this will allow you to conditionally redirect users:
def after_sign_in_path_for(resource_or_scope)
if resource_or_scope.is_a?(User)
some_custom_path
else
super
end
end

Related

Using devise for user registration/login redirect user to a different form page based on their response

I am using devise for user registration/login, after the user has successfully signed up, I want to show a page/a dialog box and redirect to another page based on user response. How can I do that?
User Model (By devise)
username
password
Student Model
name
student_id
Teacher Model
name
grade
First_page:
signup signin links
Signup link will show the devise views/devise/registrations/new.html.erb page.
After successful signup, it takes the user to root page. I have defined the root page in routes.rb:
` Rails.application.routes.draw do
devise_for :users
resources :students, :teachers
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root to: "students#index"
end `
At this point, the application doesn't have any idea who the user is.
So, I want to get the identity information(student/teacher) from the user.
How will I get this information?
Student/Teacher controller:
`class StudentsController < ApplicationController
before_action :authenticate_user!, only: [:new, :create]
def index
#students = Student.all
end
def new
#student = Student.new
end
def create
current_user.create_student(student_params)
redirect_to root_path
end
private
def student_params
params.require(:student).permit(:name, :skypid)
end
end`
After the user has successfully signed in, I want to ask if the user is a student or teacher. Based on what they select, redirect them to a student form page or teacher form page.
How can I do that in rails?
Thank you
You can write a custom after_sign_in_path_for function in your ApplicationController assuming you're using all the default Devise controllers otherwise. Any named path helper or other route that it returns will be where the user is redirected, so you could do something simple like always redirect to a selection page that presents the options and handles the choice on a subsequent action:
def after_sign_in_path_for(resource)
user_type_selection_path # whatever route in your app manages the selection
end
Alternately, you could invoke a custom method on the user model in that function to make a choice right there:
def after_sign_in_path_for(resource)
resource.student? ? student_path : teacher_path
end
You could hybridize these of course as well to do the latter when the selection has already been made and redirect otherwise, with something similar to the following:
def after_sign_in_path_for(resource)
if resource.user_type_chosen?
resource.student? ? student_path : teacher_path
else
user_type_selection_path
end
Bear in mind that none of those functions or paths are real, since I can't be more specific on the information you've provided, but hopefully this gets you headed in the right direction. The after_sign_in_path_for hook is your primary tool here, unless you get into the world of overriding the default devise controllers and interrupting the usual workflow there to accommodate this step, which doesn't seem strictly necessary by your description.

How do I generate a temporary page like confirmation page in rails?

I am using devise and want to redirect users to a confirmation page upon signup, this is what I am doing right now:
users/registrations_controller.html.erb
class Users::RegistrationsController < Devise::RegistrationsController
def confirm_email
end
private
def after_inactive_sign_up_path_for(resource)
users_confirmyouremail_path
end
end
config/routes.rb
devise_scope :user do
get 'users/confirmyouremail' => 'users/registrations#confirm_email'
end
I have no problem with redirecting the page after signup. However, I think it is quite weird that anyone can visit the page with url like `host.com/confirmyouremail' and see the confirmation page. Are there any ways I can write a route that will use random code that is allow only for one time visit? Thanks in advance.
Maybe something like this:
before_action :authenticate_user!
def confirm_mail
redirect_to root_path if current_user.confirmed
...
end
You are storing in the database if the user has already confirmed his account. If his account is confirmed then he won't be able to access this page. You can redirect to whatever page you want. A user without any account won't be able to access this page because of the before action
In case the user is not logged in when he accesses this confirm_mail page you have different possibilities. You could use a session or a cookie:
# after sign up:
session[:confirm] = true
# alternatively a cookie
cookies[:confirm] = true
Then in the confirm mail action:
def confirm_mail
if session[:confirm].blank? # or cookies[:confirm].blank?
redirect_to root_path
end
# otherwise delete the field from the session
session.delete(:confirm)
# alternatively the cookie
cookies.delete(:confirm)
end
Another way would be by using a Token. You create a new model like ConfirmMailToken. Then on sign up you create a new token and redirect the user to the confirm page with the token as a URL param. Then in the confirm_mail action you check if a token is available and delete it if it is. This way you ensure that the page is only shown after redirect.

Conditional Route on sign_out using Devise with Rails

I am working on an app in which there is a model User with roles member and Admin.
As per requirement, I have to made two separate login pages for Admin and Member.
with http://localhost:3000/admin/admin_login
it goes to admin login page and with
http://localhost:3000/users/sign_in
it goes to member login page.
Just after login I route them according to their roles to Admin panel or simple website for members.
But at time of logout both goes to
http://localhost:3000
but I want admin to go to http://localhost:3000/admin/admin_login,
while http://localhost:3000 is fine for member's logout.
Is there a way to see User's Role at time of Sign_out and route them accordingly.
You can define a after sign out path according to resource in application controller..
class ApplicationController < ActionController::Base
private
# Overwriting the sign_out redirect path method
def after_sign_out_path_for(resource_or_scope)
root_path
end
end
In after_sign_out_for_for method you can check user role and redirect to
For more details visit devise wiki After Sign out path in devise
I think you can try like this
Just save whatever path you want to redirect user after sign_out based on the role after login in session and use that session in after_sign_out_path_for method
after_filter :store_location
def store_location
return unless session[:login_url].blank?
session[:login_url] = current_user.admin? ? admin_path : other_user_path
end
def after_sign_out_path_for(resource)
session[:login_url] || request.referer || root_path
end
there are one other way just overwrite devise sessoin controller and redirect user from there based on role
# routes.rb
devise_for :users, :controllers => { :sessions => "sessions" } # etc
# sessions_controller.rb
class SessionsController < Devise::SessionsController
def destroy
#login_path = set path in a variable based on user role before sing_out
#code to sign out
#
redirect_to login_path
end
end
Are the pages that they are clicking on the logout links different for admins and users? If so, you could check the request.referrer property in your after_sign_out_path method and route accordingly.
BTW if you are routing them to the right pages after logging in then why do you need separate login pages? you may want to just have one login page for simplicity.
You can also leave it config.sign_out_via =: get => config/initializers/devise.rb is not the best way but solved for me.

How to redirect to the same url in 'after_update_path_for' with devise ruby on rails

I want to redirect to the same page after updating the password.
I have two views:
edit.html.haml (account_path)
edit_password.html.haml (account_change_password_path)
When I update the account(edit or edit_password), it redirects me to root page (I want to re-direct to the same page).
When I try to change the password (with errors) in edit_password view it shows me the devise errors in "edit view" (it should show me the devise errors in edit_password view).
I tried to solve this with:
class RegistrationsController < Devise::RegistrationsController
# ...
protected
def after_update_path_for(resource)
redirect_to :back
end
end
but it does not work.
How can I make it redirect to the same url?
You've got it almost right. So those path helpers for devise, after_sign_up_path, after_sign_in_path, after_update_path are expecting a URL, specifically, just a string.
For others hitting this page: The keys to making after update work are:
Create a registrations controller to override the after_update_path method (see the docs on how to do this: https://github.com/plataformatec/devise#configuring-controllers
Add the method after_update_path in the protected section of your custom registration controller
Add the path, as a string or stored string as the only outputted element in that method
An example if you want to redirect back to the page you came from:
class RegistrationsController < Devise::RegistrationsController
# ...
protected
def after_update_path_for(resource)
request.referrer || edit_user_registration_path
end
end
So if the user was on edit_password_path, it takes them back there. However, if a security conscience user has antivirus or no-follow software that removes referrers from their browser, then your back-up is to take the user to the full registration path.

Rails, how to post a form to Devise?

I want to allow an admin on my app to sign in as any user. I found the following on the devise wiki:
class AdminController < ApplicationController
# Sign in as another user if you are an admin
def become
return unless current_user.is_an_admin?
sign_in(:user, User.find(params[:id]))
redirect_to root_path
end
end
In the view, how do you build a form to post to this?
Thanks
You wouldn't even need to build a form, you could simply allow the admin to go to the following url:
example.com/admin/become?id=25
where 25 is the id you want to log into as.
So with this method, you would just create a link for an admin to click on.

Resources