Devise and stored_location_for: how do you store the return location?

前端 未结 5 1808
我寻月下人不归
我寻月下人不归 2020-12-25 13:11

I have a page whose path is (e.g.) /premises/92 on which I\'m displaying \"please [log in] or [register] for additional information\" if the user is not logged in, and I wan

相关标签:
5条回答
  • 2020-12-25 13:27

    I do like this:

    class ApplicationController < AC::Base
      after_filter :clear_attached_unit # UPDATED
    
      protected
      def clear_attached_unit
        session[:attached_unit_path] = nil unless keep_attached_unit_path?
      end
    
      def keep_attached_unit_path? # UPDATED
        @keep_attached_unit_path   
      end                           
    end
    
    
    class UnitController < ApplicationController
      before_filter :attach_unit, :only => [:show]
    
      protected
      def attach_unit
        session[:attached_unit_path] = request.url if request.get? && !request.xhr?
      end
    end
    
    class SessionsController < Devise::SessionsController
      before_filter :keep_attached_unit_path! # UPDATED
    
      protected
      def keep_attached_unit_path! # UPDATED
        @keep_attached_unit_path = true
      end
    
      def after_sign_in_path_for(resource_or_scope)
        if resource_or_scope.is_a?(User) && session[:attached_unit_path].present?
          session[:attached_unit_path]
        else
          super
        end
      end 
    end
    

    And extract this to module.

    0 讨论(0)
  • 2020-12-25 13:34

    I found this whole devise redirect thing quite confusing.

    Where @rorra says Devise uses session["#{scope}_return_to"], he means that Devise default after_sign_in_path_for(resource) will use that variable through the method stored_location_for(resource).

    So you should save the location you want to store in the variable session["#{scope}_return_to"], which will usually be session["user_return_to"]. To do this place the following in your application_controller.rb:

    after_action :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" &&
          request.fullpath != "/users/sign_out" &&
          !request.xhr?) # don't store ajax calls
        session["user_return_to"] = request.fullpath 
      end
    end
    

    In some cases you will not need to define an after_sign_in_path_for(resource) method as devise's default method will do all the redirects for you and if their is no redirect url available you will be redirected to the resource root path (usually user root path) and if that doesn't exist you will be redirected to the root path. If however, you would like to customise where the user is sent if there is no redirect url available, add the following to your application_contorller.rb (and change root_path accordingly):

    def after_sign_in_path_for(resource)
      stored_location_for(resource) || root_path
    end
    
    0 讨论(0)
  • 2020-12-25 13:35

    Devise looks for the key "#{resource}_return_to" in the session.

    Here I am quoting the API:

    By default, it first tries to find a valid #{resource}_return_to key in the session, then it fallbacks to #{resource}_root_path, otherwise it uses the root_path.

    Here is the link to the API

    0 讨论(0)
  • 2020-12-25 13:41

    Devise use

    session["#{scope}_return_to"]
    

    So you can use session["user_return_to"] if your model for authentication is User.

    0 讨论(0)
  • 2020-12-25 13:43

    here's the best I could come up with. Works perfectly also with facebook authentication. by adding more restrictions to the prepending of urls to the session variable you can remove more and more paths you don't want the user to return too (e.g. callbacks, splash pages, landing pages, etc)

    #ApplicationsController
    
    after_filter :store_location
    
    def store_location
      session[:previous_urls] ||= []
      # store unique urls only
      session[:previous_urls].prepend request.fullpath if session[:previous_urls].first != request.fullpath && request.fullpath != "/user" && request.fullpath != "/user/login" && request.fullpath != "/" && request.fullpath != "/user/logout" && request.fullpath != "/user/join" && request.fullpath != "/user/auth/facebook/callback"
      # For Rails < 3.2
      # session[:previous_urls].unshift request.fullpath if session[:previous_urls].first != request.fullpath 
      session[:previous_urls].pop if session[:previous_urls].count > 3
    end
    
    def after_sign_in_path_for(resource) 
      @url = session[:previous_urls].reverse.first
      if @url != nil
        "http://www.google.com" + @url
      else
        root_path
      end
    end
    
    0 讨论(0)
提交回复
热议问题