Search code examples
ruby-on-railsrspecdeviserspec-rails

Rspec and current user id saved in different model from devise


I'm using Devise to manage users and my goal get the current user to be saved with the created record.

The current user is saved in the controller but my Rspec is wrong!

Thank you all for your help.

My record Model

class Record < ActiveRecord::Base
  #Associations
  belongs_to :user


  # Validations
  validates :title, :user, presence: true
end

My record Controller

class RecordsController < ApplicationController
  before_action :find_record, only: [:show, :edit, :update, :destroy]

  def create
    @record = Record.new(record_params)

    if @record.save
      redirect_to @record
    else
      @records = Record.all
      render 'index'
    end
  end

  def update
    if @record.update(record_params)
      flash[:notice] = "The record was updated successfully"
      redirect_to @record
    else
      render 'edit'
    end
  end

  private

    def find_record
      @record = Record.find(params[:id])
    end

    def record_params
      params.require(:record).permit(:title, :description, :user_id).merge(user: current_user) # as suggested 
    end
end

My Rspec

require 'rails_helper'

describe RecordsController do
  let(:record) { create(:record) }
  let(:user) { create(:user) }
  let(:title) { "Some title I would like to put in my record" }
  let(:description) { "description I would like to put in my record" }


  describe "#create" do
    it "creates a new record with the given title and description" do
      expect do
        post :create, record: { title: title, description: description, user_id: user }
      end.to change { Record.count }.by(1)

      expect(response).to redirect_to(assigns[:record])

      expect(assigns[:record].title).to eq(title)
      expect(assigns[:record].description).to eq(description)
    end

    it "fails to create a record and returns to the index page" do
      expect(post :create, record: { description: description }).to render_template(:index)
      expect(assigns[:records]).to eq(Record.all)
    end
  end

  describe "#update" do
    it "find the records and sets the new given values" do
      put :update, { id: record.id, record: { title: title, description: description } }

      record.reload
      expect(record.title).to eq(title)
      expect(record.description).to eq(description)

      expect(flash[:notice]).to eq("The record was updated successfully")
    end

    it "fails to create a record and returns to the edit page" do
      expect(put :update, { id: record.id, record: { title: "" } }).to render_template(:edit)
    end
  end
end

Now with the current user being saved Rspec throws me errors in create and update:

1) RecordsController#create creates a new record with the given title and description
     Failure/Error: post :create, record: { title: title, description: description, user_id: user }
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:9:in `create'
     # ./spec/controllers/records_controller_spec.rb:36:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/records_controller_spec.rb:35:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

  2) RecordsController#create fails to create a record and returns to the index page
     Failure/Error: expect(post :create, record: { description: description }).to render_template(:index)
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:9:in `create'
     # ./spec/controllers/records_controller_spec.rb:46:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

  3) RecordsController#update find the records and sets the new given values
     Failure/Error: put :update, { id: record.id, record: { title: title, description: description } }
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:20:in `update'
     # ./spec/controllers/records_controller_spec.rb:62:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

  4) RecordsController#update fails to create a record and returns to the edit page
     Failure/Error: expect(put :update, { id: record.id, record: { title: "" } }).to render_template(:edit)
     NoMethodError:
       undefined method `authenticate' for nil:NilClass
     # ./app/controllers/records_controller.rb:42:in `record_params'
     # ./app/controllers/records_controller.rb:20:in `update'
     # ./spec/controllers/records_controller_spec.rb:72:in `block (3 levels) in <top (required)>'

Solution

  • You need to login the user first before you can use the current_user. Something like:

    before do                                                                    
      sign_in :user, create(:user)
    end
    

    Also checkout How To: Test controllers with Rails 3 and 4 (and RSpec)