Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Devise: redirect on sign up failure?

I'm trying to redirect users that have failed the sign up form (e.g. they entered a username that is already taken, they left a field blank, etc...)

I have custom failure set up for users that fail the sign in form, code below:

class CustomFailure < Devise::FailureApp 

   def redirect_url 
      root_path 
   end 

   def respond 
      if http_auth? 
      http_auth 
   else 
      redirect 
   end 
 end

However, I've been stuck on how to set this up for sign up failure. Ideally I would just like to redirect them back/to root_path, any ideas? Thank you!

like image 805
ahuang7 Avatar asked Jun 05 '11 00:06

ahuang7


4 Answers

It's a bit tedious to modify certain parts of devise to suit your needs and I suspect it's because the gem does a good job to cover most common cases. However, edge-cases for use of devise are a lot and your question points to one of them. I had to do something similar, that is, make sure devise redirects to a specific page when a user does one of the following:

  1. submits form on an empty form
  2. submits an already existing email. Below is how I handled it.

First, create a controller called RegistrationsController that inherits from Devise::RegistrationsController like so:

 class RegistrationsController < Devise::RegistrationsController
 end

Inside this controller you will have override the create method in devise. Go to the devise github page here, https://github.com/plataformatec/devise/blob/master/app/controllers/devise/registrations_controller.rb to view the create method and copy the code in that method. Then create a private method to override the returning statment of the last block of the if statement. Your controller should look like so,

class RegistrationsController < Devise::RegistrationsController


 def create
   build_resource(sign_up_params)

   resource.save
   yield resource if block_given?
  if resource.persisted?
    if resource.active_for_authentication?
      set_flash_message! :notice, :signed_up
      sign_up(resource_name, resource)
      respond_with resource, location: after_sign_up_path_for(resource)
    else
      set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
      expire_data_after_sign_in!
      respond_with resource, location: after_inactive_sign_up_path_for(resource)
    end
  else
    clean_up_passwords resource
    set_minimum_password_length
    response_to_sign_up_failure resource    
  end
  end

private

def response_to_sign_up_failure(resource)
  if resource.email == "" && resource.password == nil
    redirect_to root_path, alert: "Please fill in the form"
  elsif User.pluck(:email).include? resource.email
    redirect_to root_path, alert: "email already exists"
  end
end
 end

It should work.

like image 88
Paa Yaw Avatar answered Nov 06 '22 03:11

Paa Yaw


In config/routes.rb:

devise_scope :user do
   get '/users', to: 'devise/registrations#new'
end
like image 32
B-M Avatar answered Nov 06 '22 02:11

B-M


You will probably need to subclass Devise::RegistrationsController and override the create action. Just copy over the create method from here and modify the redirect on failure to save.

# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController


  def create
    # modify logic to redirect to root url
  end


end 

Change your routes to tell Devise to use your controller:

# config/routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
like image 20
David Avatar answered Nov 06 '22 02:11

David


Tip:

To keep flash error messages add this line before the redirect_to in your override

    resource.errors.full_messages.each {|x| flash[x] = x}

So in your registrations_controller.rb :

def create
    build_resource(sign_up_params)

    if resource.save
        yield resource if block_given?
        if resource.active_for_authentication?
            set_flash_message :notice, :signed_up if is_flashing_format?
            sign_up(resource_name, resource)
            respond_with resource, location: after_sign_up_path_for(resource)
        else
            set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
            expire_data_after_sign_in!
            respond_with resource, location: after_inactive_sign_up_path_for(resource)
        end
    else
        clean_up_passwords resource
        resource.errors.full_messages.each {|x| flash[x] = x} # Rails 4 simple way
        redirect_to root_path 
    end
end
like image 5
DoctorRu Avatar answered Nov 06 '22 03:11

DoctorRu