I've tried the code on Devise's github. In my application controller, i have:
after_filter :store_location
def store_location
# store last url - this is needed for post-login redirect to whatever the user last visited.
if (request.fullpath != "/users/sign_in" &&
request.fullpath != "/users/sign_up" &&
request.fullpath != "/users/password" )
session[:previous_url] = request.fullpath
puts 'stores location'
end
end
def after_update_path_for(resource)
session[:previous_url] || dashboard_path
puts 'after update'
end
When I check my server, the puts statement from the store_location method appears, but the puts statement from after_update_path_for does not. How do I get the after_update_redirect to work?
Here is what devise says to do, but it isn't working:
https://github.com/plataformatec/devise/wiki/How-To:-Redirect-back-to-current-page-after-sign-in,-sign-out,-sign-up,-update
From the documentation:
(Object) after_update_path_for(resource) (protected)
The default url to be used after updating a resource. You need to overwrite this method in your own RegistrationsController.
So creating your ow RegistrationsController is correct. Here is a simpler solution though:
after_update_path_for calls signed_in_root_path(resource) which looks a home #{scope}_root_path. Scope here is often user (but if not you probably know what it is). In the case of 'user', implementing user_root_path in your application controller, returning your dashboard_url, should work.
def user_root_path
dashboard_url
end
Although it seemed a bit hackish to me at first, I believe it is quite 'ok'; the root path for the user-scope is could indeed be the dashboard page.
Here's how i solved the problem:
class RegistrationsController < Devise::RegistrationsController
protected
def after_update_path_for(resource)
puts 'this is happening yoyo mama'
flash[:notice] = "Account succesfully updated"
edit_user_registration_path
end
end
routes:
devise_for :users, :controllers => { :registrations => :registrations }
The only problem is that this will only do the redirect if changing the password is successful. If not, the redirect does not happen. Does anyone know how to make it so the redirect will also happen if there are errors?
As per the Devise docs, override the default and add the route. There's no need to set the flash message unless of course you want to change that as well.
# Example subclass/override (registrations_controller.rb)
class Users::RegistrationsController < Devise::RegistrationsController
protected
def after_update_path_for(resource)
user_path(resource)
end
end
# Example routing config (in routes.rb):
devise_for :users, :controllers => { :registrations => :registrations }
respond_with resource, :location => after_update_path_for(resource) is the code which set the redirection path after update. To change the default redirect, override following method in your application controller by adding the following code
def after_update_path_for(resource_or_scope)
dashboard_url
end
Overriding the route in the ApplicationController also did not work for me, but adding it to the Users::RegistrationsController worked.
For example,
class Users::RegistrationsController < Devise::RegistrationsController
def after_update_path_for(resource)
current_user
end
on a related note, the after_sign_in_path can be added to the SessionsController
class Users::SessionsController < Devise::SessionsController
def after_sign_in_path_for(resource)
current_user
end
my routes look like this:
devise_for :users, controllers: {
confirmations: "users/confirmations",
passwords: "users/passwords",
registrations: "users/registrations",
sessions: "users/sessions",
unlocks: "users/unlocks",
}
Related
I am using Rails and devise with AJAX. I implemented this tutorial.
Everything works well so far.( I can log in and logout)
I want to redirect the user back to the previous page after successful sign in/sign up.
However, I've tried everything but I could not override after_sign_in_path_for method in ApplicationController/SessionController.
My ApplicationController:
class ApplicationController < ActionController::Base
helper_method :resource_name, :resource, :devise_mapping, :resource_class
def resource_name
:user
end
def resource
#resource ||= User.new
end
def resource_class
User
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
end
Route:
devise_for :users, path: '', controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations',
passwords: 'users/passwords'
}
Then I realized that even if I typed something like below into SessionsController, I couldn't override after_sign_in_path_for;
def after_sign_in_path_for(resource)
'/somepage'
end
Whatever I write, the system redirects me to the root page.
I've tried this , this and this links but no hope.
I think my problem is caused by AJAX. Any idea?
Thanks in advance.
When i try to restrict access to signup, it seems impossible. I tried
class RegistrationsController < Devise::RegistrationsController
skip_before_filter :require_no_authentication
end
in app/registrations_controller.rb and changed routes to
devise_for :accounts, :controllers => { :registrations => "registrations" }
This does not work. Any suggestions why and what i could do/where i should look would be appreciated.
EDIT:
Does not work means: when i try to access /accounts/sign_up while being signed out, it actually works, but i should be redirected to sign_in.
WORKAROUND:
class RegistrationsController < Devise::RegistrationsController
skip_before_filter :require_no_authentication
private
def authenticate_account!(opts={})
opts[:scope] = :account
warden.authenticate!(opts) # if !devise_controller? || opts.delete(:force)
end
end
This removes the hardcoded check that skips authentication for EVERY Devise-controller. The code comes from lib/devise/controllers/helpers.rb.
So you want to change after sign-out path.
If you haven't set your root to devise sign in then
class ApplicationController < ActionController::Base
private
# Overwriting the sign_out redirect path method
def after_sign_out_path_for(resource_or_scope)
new_user_session_path
end
end
Using Devise to manage users sessions / registrations I would need to perform specific tasks (updating some fields in the users table for this specific user for example) each time a user signs in, and before he gets redirected by devise to the home page for connected users.
Do I have to override devise SessionsController, and if yes, how?
Alternatively, you can create your own sessions controller
class SessionsController < Devise::SessionsController
def new
super
end
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
if !session[:return_to].blank?
redirect_to session[:return_to]
session[:return_to] = nil
else
respond_with resource, :location => after_sign_in_path_for(resource)
end
end
end
And in routes.rb add:
devise_for :users, controllers: {sessions: "sessions"}
If you look at Devise's implementation of sessions_controller#create, you'll notice that they yield if you pass a block.
So, just subclass their sessions controllers and pass a block when you call super. To do that, first tell Devise in routes.rb that you'd like to use your own sessions controller:
devise_for :users, controllers: { sessions: 'users/sessions' }
And then create a SessionsController class and pass a block when you call super in your create method. It would look something like this:
# app/controllers/users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
layout "application"
# POST /login
def create
super do |user|
if user.persisted?
user.update(foo: :bar)
end
end
end
end
Most of the Devise controller methods accept a block, so you could do this for registration, forgot password, etc as well.
Devise provides after_database_authentication callback method.You have full access for the current authenticated user object over there.
If you want to update current user name after every successful login you can do that like below.
class User < ActiveRecord::Base
devise :database_authenticatable
def after_database_authentication
self.update_attributes(:name => "your name goes here")
end
end
configure devise for using your controller changing config/routes.rb devise_for :users, controllers: { ... , sessions: "sessions", ... }
create a app/controllers/sessions_controller.rb or generate it using rails g devise:controllers users -c=sessions
prepend_before_action
class SessionsController < Devise::SessionsController
prepend_before_action :your_task, only: [:create] # Change this to be any actions you want to protect.
private
def your_task
return if your_task_is_OK # if your task is good, return to the super method otherwise render the new
self.resource = resource_class.new sign_in_params
respond_with_navigational(resource) do
flash.now[:alert] = "your notice message"
render :new
end
end
end
How can I create an after-confirmation redirect in Devise?
Before I added the confirmation module the custom after_sign_up_path worked fine for the first time login/signup but now when I click the confirmation link in the email it redirects to the path I set for the after-login path (user profile).
My goal is to create a form wizard and "getting started" page to collect additional information. The obvious caveat being that this redirect will only happen one time, upon confirmation.
I tried some other solutions that have been posted on Stack Overflow but none of them seem to work any longer.
A less intrusive way of achieving this might be just overriding the after_confirmation_path_for method of Devise::ConfirmationsController.
Create a new confirmations_controller.rb in app/controllers directory:
class ConfirmationsController < Devise::ConfirmationsController
private
def after_confirmation_path_for(resource_name, resource)
your_new_after_confirmation_path
end
end
In config/routes.rb, add this line so that Devise will use your custom ConfirmationsController. This assumes Devise operates on users table (you may edit to match yours).
devise_for :users, controllers: { confirmations: 'confirmations' }
Restart the web server, and you should have it.
Essentially, you want to change around line 25 of Devise's ConfirmationsController.
This means you need to override the show action modifying the "happy path" of that if statement in the show action to your heart's content:
class ConfirmationsController < Devise::ConfirmationsController
def new
super
end
def create
super
end
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_navigational_format?
sign_in(resource_name, resource)
respond_with_navigational(resource){ redirect_to confirmation_getting_started_path }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
end
end
end
And a scoped route for it (I put the view and action in the registrations controller but you can change it to whatever):
devise_for :users, controllers: { confirmations: 'confirmations' }
devise_scope :user do
get '/confirmation-getting-started' => 'registrations#getting_started', as: 'confirmation_getting_started'
end
The default show action is referring to the protected after_confirmation_path_for method, so as another option, you could just modify what that method returns.
Have you checked the Devise wiki? It explains how to do this, with the after_signup_path_for being the path to define in your case.
From the wiki:
Make a new controller "registrations_controller.rb" and customize the appropriate method:
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
'/an/example/path'
end
end
Then add a route to use it:
Modify config/routes.rb to use the new controller
devise_for :users, :controllers => { :registrations => "registrations" }
The solution given by #Lee Smith is working perfectly but I wish to add a little addition: We don't need to add the new and create actions while overriding the Devise confirmations controller for this case:
class ConfirmationsController < Devise::ConfirmationsController
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_navigational_format?
sign_in(resource_name, resource)
respond_with_navigational(resource){ redirect_to your_desired_redirect_path }
else
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render_with_scope :new }
end
end
end
Then in the route file, just add routing for the confirmations controller.
devise_for :users, controllers: { confirmations: "confirmations" }
I just went through all of this and none of the other answers worked (2015-04-09 with devise 3.4.1).
After signup, I wanted the user to be redirected to the login page with a message about a confirmation email. To get that working, here's what I had to do:
class RegistrationsController < Devise::RegistrationsController
protected
# This is the method that is needed to control the after_sign_up_path
# when using confirmable.
def after_inactive_sign_up_path_for(resource)
new_user_session_path
end
end
I just found this comment which would have sent me exactly where I needed to be much sooner.
Here is the reference to the after_inactive_sign_up_path_for that
mentions Niels: Devise wiki – marrossa Nov 13 '12 at 3:38
The confirmation_path also must be configured while working with refinerycms integrated in a rails app
I have looked all over the place, and found a lot of info... but nothing works for me and I don't get it :(
I know that you are suppose to override the registration controller, like this:
class Users::RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
authors_waiting_path
end
end
Then following the example showed by Tony Amoyal http://www.tonyamoyal.com/2010/07/28/rails-authentication-with-devise-and-cancan-customizing-devise-controllers/, I am supposed to change my routes to update the access the new controller:
devise_for :users, :controllers => { :registrations => "users/registrations" } do
#get '/author/sign_up', :to => 'devise/registrations#new'
#get '/client/sign_up', :to => 'devise/registrations#new'
get '/author/sign_up', :to => 'users/registrations#new'
get '/client/sign_up', :to => 'users/registrations#new'
end
Yes, I have something a bit strange here, because I am catching some specific path to send them to the registration page, this allows me to create effectively 2 registration scenario.
I commented what I had before I had overridden the registration controller.
Even with all this and my authors_waiting_path being a valid path, it just keeps on going to the sign-in page after registration :(
This is really frustrating.
Alex
edit: I also found this on the devise wiki: https://github.com/plataformatec/devise/wiki/How-To:-Redirect-after-registration-(sign-up)
But I have no idea where to define this create method ? should I override the session controller ???
edit 2:
I put a dummy override of the controller:
class Pouets::RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
authors_waiting_path
end
def new
super
end
def create
puts "was here"
super
end
def edit
super
end
def update
super
end
def destroy
super
end
def cancel
super
end
end
And I never the "was here" in my logs.... I really have the feeling that it's totally ignoring the override... I must be doing something wrong :(
Ok... I am able to override it so you should be either :0
Create folder app/controllers/users
put there registrations_controller.rb with: (option with session - but it will try sign_in and later redirect - it may be not intended behavior for you ). Furthermore this is from devise wiki and I am not sure if it works
class Users::RegistrationsController < Devise::RegistrationsController
def create
session["#{resource_name}_return_to"] = complete_path
super
end
end
restart application (just for ensure you don't trust anything)
All in all you must override Create If you want redirect only Users... if you want define some more complex scenario you should monkeypatch sign_in_and_redirect
so your controller will looks like
class Users::RegistrationsController < Devise::RegistrationsController
# POST /resource/sign_up
def create
build_resource
if resource.save
set_flash_message :notice, :signed_up
#sign_in_and_redirect(resource_name, resource)\
#this commented line is responsible for sign in and redirection
#change to something you want..
else
clean_up_passwords(resource)
render_with_scope :new
end
end
end
second option try to monkeypatch helper ....
module Devise
module Controllers
# Those helpers are convenience methods added to ApplicationController.
module Helpers
def sign_in_and_redirect(resource_or_scope, resource=nil, skip=false)
#intended behaviour for signups
end
end
end
end
I have tried the above solution and while it works, reading devise code, I have found that all you actually need in order to sign-out just registered user and redirect is:
to add is_approved or similar to your user table and
to add active_for_authentication? method in your User model
Code:
class User < ActiveRecord::Base
# ... some code
def active_for_authentication?
super && is_approved
end
end
Was a bit hard to find when I needed it, but that is all. I am actually writing it here in case someone else needs it.