0

In my application, I store the user's ID in session[]. At the beginning of every controller action, I'm calling a method defined in the ApplicationController called current_user:

  def current_user
    @current_user ||= session[:current_user_id] && 
    User.find_by_id(session[:current_user_id])
  end

At the beginning of my controllers' methods, I have the following:

  @current_user = current_user
  if @current_user == nil     
    redirect_to :home         
    return                    
  end                         

This is obviously repetitive code and should be a method somewhere. I read the answer for this question, and tried putting my method into a parent class that my controller classes now descend from, however it seems like I can't redirect from that method now.

In my parent class, I have:

  def verify_user
    user = current_user
    if user == nil
      redirect_to "/"
      return
    end
    return user
  end

And now I've changed my controller methods to this:

  @current_user = verify_user

This doesn't work, and I think I know why. For one, I can't simply call return in my verify_user method, as that obviously will just return to the controller. The redirect doesn't seem to have any affect, probably because format.html is being called after the redirect call, which was the reason for the return in the original code.

So, what am I doing wrong here, and what suggestion do you have to solve it? Is this the wrong approach? My main goal is to keep the entire "check if user is logged in otherwise redirect" to one line of code per controller method.

2 Answers 2

2

Take a look at the devise gem https://github.com/plataformatec/devise. It handles a lot of this basic user authentication logic for you. This specific problem can we solved by adding before_filter :authenticate_user! to the controllers or actions that need to be guarded.

Sign up to request clarification or add additional context in comments.

Comments

1

Add the following logic to the ApplicationController class:

class ApplicationController < ActionController::Base

  def current_user
    ...
  end

  def logged_in?
    current_user.present?
  end

  def require_user
    return true if logged_in?
    render_error_message("You must be logged in to access this page", 
      new_user_session_url)
    return false
  end

  def render_message message
    respond_to do |format|
      format.html {
        if request.xhr? 
          render(:text => message, :status => :unprocessable_entity)
        else
          redirect_to(root_url, :notice => message)        
        end
      }
      format.json { render :json => message, :status => :unprocessable_entity }
      format.xml { render :xml => message, :status => :unprocessable_entity }
    end
  end

end

Now add a before_filter to your controller:

class OrdersController < ApplicationController

  before_filter :require_user

end

1 Comment

This indeed works, although I need to also check out device or others like it in sguha's post.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.