Pergunta

I'm using Rails 3.2 and Authlogic. I have the following code:

class ApplicationController < ActionController::Base
  private

  def store_location
    session[:return_to] = request.url
  end

  def redirect_back_or_default(default)
    redirect_to(session[:return_to] || default)
    session[:return_to] = nil
  end
end

class UserSessionsController < ApplicationController  
  before_filter :require_no_user, :only => [:new, :create]
  before_filter :require_user, :only => :destroy

  def new
    @user_session = UserSession.new
    @header_title = "Login"
  end

  def create
    @user_session = UserSession.new(params[:user_session])
    if @user_session.save
      flash[:success] = "Login successful!"
      redirect_back_or_default root_url
    else
      render 'new'
    end
  end

  def destroy
    current_user_session.destroy
    flash[:success] = "Logout successful!"
    redirect_back_or_default root_url
  end
end

This code is quite generic. When we use the before_filter:

  before_filter :require_user, :only => [:new, :edit, :update, :create]

It will automatically store_location and redirect us back to the proper page. However, how do I do this:

  1. I'm in posts/1 which doesn't require_user.
  2. I click the login link on my top navigation bar.
  3. It shows the login page.
  4. Once login, I will be redirected back to posts/1 instead of the root_url.
Foi útil?

Solução 2

I added a store_referrer_location to make it work:

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

  def store_referrer_location
    session[:return_to] = request.referrer
  end
end

# user_sessions_controller.rb
class UserSessionsController < ApplicationController
  def new
    store_referrer_location if session[:return_to].blank?
    @user_session = UserSession.new
    @header_title = "Login"
  end

  ...

  def destroy
    store_referrer_location if session[:return_to].blank?
    current_user_session.destroy
    flash[:success] = "Logout successful!"
    redirect_back_or_default root_url
  end
end

Outras dicas

Place a direct call to store_location in the sessions controller new action.

# user_sessions_controller.rb
def new
  store_location if session[:return_to].blank?
  @user_session = UserSession.new
  @header_title = "Login"
end

This will first check for an existing return_to pair in the sessions hash. You don't want to overwrite it in case, for example, a user is redirected to the new action because of a bad password.

This will also skip store_location if it was already called from require_user.

After a successful redirect, you have to delete the return_to pair from the sessions hash; setting it to nil is not enough:

  # application_controller.rb
  def redirect_back_or_default(default)
    redirect_to(session.delete(:return_to) || default)
  end
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top