Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Authentication from Scratch: current_user returns nil

I am building a role based authentication system from scratch using a Treehouse's course User Authentication in Rails as a general guide along with some other resources. The app I am building is a simple blog.

I posted a previous issue in Stack Overflow concerning an undefined method for 'admin?' for nil:NilClass that I suspected had more to do with the method following it...current_user. You can see my post here: http://stackoverflow.com/questions/29522637/testing-admin-authorization

It turns out that I am correct. I found the same failure popping up in my posts_controller_spec.rb as well, except the failure message is undefined method for 'posts' for nil:NilClass.

I tried many combos such as signing in/logging in a user before running the specs and simple syntax changes, but still find I'm at a loss. Any insight is very appreciated.

Here is my code.

Failures:

  1) PostsController#GET create with valid attributes 
     Failure/Error: post :create, post: attributes_for(:post)
     NoMethodError:
       undefined method `posts' for nil:NilClass
     # ./app/controllers/posts_controller.rb:16:in `create'
     # ./spec/controllers/posts_controller_spec.rb:40:in `block (4 levels) in <top (required)>'

spec/controllers/posts_controller_spec.rb

before :example do
        allow(controller).to receive(:require_auth)
        @user = build_stubbed(:user)
        sign_in(@user)
    end

    describe "#GET index" do
        before :each do
            @post = create(:post)
            get :index
        end

        it { expect(response).to be_success }
            it { expect(assigns(:posts)).to eq([@post]) }
    end


    describe '#GET show' do
        before :each do
            @post = create(:post)
            get :show, id: @post.id
        end

        it { expect(assigns(:post)).to eq(@post) }
    end



    describe '#GET create' do
        context 'with valid attributes' do
          before :each do
            post :create, post: attributes_for(:post), id: @user.id
          end

             it { expect(Post.count).to eq(1) }
             it { expect(flash[:success]).to eq('Your post has been saved!') }
             it { expect(assigns(:post)).to be_a(Post) }
             it { expect(assigns(:post)).to be_persisted }
             it { expect(response).to redirect_to Post.first }

             it "creates a post by the current_user" do
                @post = Post.last
                expect(@post.user).to eq(@user)
            end
        end

 #more tests.....

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  add_flash_types :success, :error

  private
  helper_method :current_user
  helper_method :logged_in?

  def logged_in?
    current_user
  end

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
    rescue ActiveRecord::RecordNotFound
  end

  def require_auth
    unless current_user
      session[:target] = request.fullpath
      redirect_to new_user_session_path, 
        notice: "You must be logged in to access that page."
    end
  end

  def require_admin
    unless current_user.admin?
      redirect_to post_path, 
        notice: "Access denied."
    end
  end


end

app/controllers/posts_controller.rb

class PostsController < ApplicationController

    before_action :require_auth, expect: [:index, :show]

     #some methods...

    def create
        @post = current_user.posts.new(post_params)

        if @post.save
            flash[:success] = "Your post has been saved!"
            redirect_to @post
        else
            flash[:error] = "There was an error saving your post."
            redirect_to new_post_path
        end
    end

    #some more methods...

end

1 Answer

Brandon Barrette
Brandon Barrette
20,485 Points

It appears to be a typo in your posts_controller:

before_action :require_auth, expect: [:index, :show]

Should be:

before_action :require_auth, except: [:index, :show]

except instead of expect

Thanks for catching that! However, I'm still running into the same error with undefinted method 'posts' for NilClass..