Devise: redirect on sign up failure?

2019-01-23 05:46发布

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!

3条回答
叼着烟拽天下
2楼-- · 2019-01-23 06:07

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.

查看更多
成全新的幸福
3楼-- · 2019-01-23 06:17

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
查看更多
三岁会撩人
4楼-- · 2019-01-23 06:24

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"}
查看更多
登录 后发表回答