简体   繁体   中英

Rails, devise, SPA, redirect to custom url (with param in query string) after logout and login (sign_out, sign_in)

I have a default Rails app with devise gem and some routes are totally SPA (single page application).

If I go on that SPA pages (let's say " /home ") and I'm not authenticated (or the session is over) it redirects me to:

  • " localhost:3000/users/sign_out "
  • and then devise to " localhost:3000/users/sign_in "

Everything good, but.

What I need now is that if I go to let's say " /home/jobs " and like before I'm not authenticated or the session is over it redirects me to:

  • " localhost:3000/users/sign_out?continue=localhost:3000/home/jobs " (I do that with javascript "window.location.replace")
  • but then devise redirects me to " localhost:3000/users/sign_in "
  • and after that I loose my " continue " params in query string and I cannot proceed to "continue" URL after login.

I know about after_sign_in_path_for and after_sign_out_path_for but I think that doesn't work with params in query string, right?

Is this a crazy scenario?

That's one problem of mixing SPA routes and non-spa routes. I think it's preferable to loose some upfront time translating devise into an api only response and then making the user session routing be SPA as well.

I'm not sure if you can't access the request params in the devise controller, you should check, perhaps you can, but if not there is at least one other way you could work around this and that would be to have a before_action on your application_controller.rb before any devise logic, to just assign a session key based on the params, and in your after_action remove it, for example (just to illustrate):

#application_controller.rb
before_action :set_continue
#...

def set_continue
  if params[:continue]
    session[:continue] = params[:continue]
  end
end

This then would allow you to use it on the after_sign_in_path :

def after_sign_in_path_for(resource)
  if session[:continue]
     navigation = session[:continue]
     session[:continue] = nil
     navigation
  else
     your_regular_path_helper #or super I guess
  end
end

You can use stored_location_for and store_location_for . This example is taken from the Devise wiki's How To: redirect to a specific page on successful sign in .

# some_controller.rb (or even the application_controller)
if params[:redirect_to].present?
  store_location_for(resource, params[:redirect_to])    
end

# application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery

  protected  
    def after_sign_in_path_for(resource)
      sign_in_url = new_user_session_url
      if request.referer == sign_in_url
        super
      else
        stored_location_for(resource) || request.referer || root_path
      end
    end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM