Paige Paige - 4 months ago 33
Ruby Question

NoMethodError: undefined method 'user' for nil:NilClass

I'm working through the book APIs on Rails and am super stuck in chapter 5 trying to test the sessions controller. I'm getting the following error and can't seem to track it down. Is there a good method for hunting down these kinds of error? And what am I missing?

1) Api::V1::SessionsController POST #create when the credentials are correct returns the user record corresponding to the given credentials
Failure/Error: post :create, { session: credentials }
NoMethodError:
undefined method `user' for nil:NilClass


App is in Rails 4.0.2, Ruby 2.2.1

Here is my test:

require 'spec_helper'

describe Api::V1::SessionsController do

describe "POST #create" do

before(:each) do
@user = FactoryGirl.create :user
end

context "when the credentials are correct" do
puts @user

before(:each) do
credentials = { email: @user.email, password: "12345678" }
post :create, { session: credentials }
end

it "returns the user record corresponding to the given credentials" do
@user.reload
expect(json_response[:auth_token]).to eql @user.auth_token
end

it { should respond_with 200 }
end


end


end


Here is the Sessions Controller:

class Api::V1::SessionsController < ApplicationController
respond_to :json

def create
user_password = params[:session][:password]
user_email = params[:session][:email]
user = user_email.present? && User.find_by(email: user_email)

if user.valid_password? user_password
sign_in user, store: false
user.generate_authentication_token!
user.save
render json: user, status: 200, location: [:api, user]
else
render json: { errors: "Invalid email or password" }, status: 422
end
end

end


The User Controller:

class Api::V1::UsersController < ApplicationController
respond_to :json

def show
respond_with User.find(params[:id])
end

def create
user = User.new(user_params)
if user.save
render json: user, status: 201, location: [:api, user]
else
render json: { errors: user.errors }, status: 422
end
end

def update
user = User.find(params[:id])

if user.update(user_params)
render json: user, status: 200, location: [:api, user]
else
render json: { errors: user.errors }, status: 422
end
end

def destroy
user = User.find(params[:id])
user.destroy
head 204
end

private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end


end


The routes.rb:

require 'api_constraints'

MarketPlaceApi::Application.routes.draw do
mount SabisuRails::Engine => "/sabisu_rails"
devise_for :users
# Api definition
namespace :api, defaults: { format: :json }, constraints: { subdomain: 'api' }, path: '/' do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :users, :only => [:show, :create, :update, :destroy]
resources :sessions, :only => [:create, :destroy]
end
end
end


And the user model:

class User < ActiveRecord::Base
validates :auth_token, uniqueness: true


# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

before_create :generate_authentication_token!

def generate_authentication_token!
begin
self.auth_token = Devise.friendly_token
end while self.class.exists?(auth_token: auth_token)
end
end

Answer

Have you added devise_helper to spec/rails_helper.rb ?

RSpec.configure do |config|
  ...
  config.include Devise::TestHelpers, type: :controller
  ...
end
Comments