'Password digest missing on new record' when i test validation on my user_spec.rb for uniqueness of fields

StackOverflow https://stackoverflow.com/questions/17635189

Question

I've been struggling with this for a few hours now and i can't find an answer anywhere.

Basically i'm writing specs for my models using shoulda and for some reason even though my let works just fine and the actual application works fine(confirmed manually and with request specs), if i include:

it { expect(user).to validate_uniqueness_of :email }

in my describe block, i will get the following error:

1) User attributes should require case sensitive unique value for email
 Failure/Error: it { expect(user).to validate_uniqueness_of :email }
 RuntimeError:
   Password digest missing on new record
 # ./spec/models/user_spec.rb:14:in `block (3 levels) in <top (required)>'

I've gotten to a point where solving this spec is holding me back, which is never a good thing, since the implementation already works.

It would be great if someone could help me out here because i REALLY don't want to start skipping tests that are failing for some obscure reason just to get things moving.

I feel as if rspec was 'ignoring' the before method that is called for has_secure_password to save the digest but i'm not sure. I'm just assuming because if the request spec worked fine, this is doing something i'm not aware of.

I'm using rails 4.0.0

Below is the relevant code to this. I appreciate any help. Thanks

user_spec.rb

require  'spec_helper'

describe User do

  let(:user) { 
    user = User.new(:email => 'example@example.com', 
                    :username => 'theo', 
                    :password => 'secretpass',
                    :password_confirmation => 'secretpass')}

  describe "attributes" do

    it { expect(user).to validate_presence_of :email } 
    it { expect(user).to validate_uniqueness_of :email }

    it { expect(user).to validate_presence_of :username }
    it { expect(user).to validate_uniqueness_of :username }

    it "saves are saved" do
      user.save!
      expect(user).to be_valid
    end

  end  


end

user.rb

class User < ActiveRecord::Base
  has_secure_password


  validates :email, :username, presence: true, uniqueness: true
  validates :password, presence: true, :on => :create


end

users_controller.rb

class UsersController < ApplicationController
  def index
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      redirect_to root_path, :notice => 'You have successfully signed up.'
    else
      render 'new'
    end
  end

  private

  def user_params
    params.require(:user).permit(:email, :username, :password, :password_confirmation)
  end
end
Was it helpful?

Solution

Please make sure you have password_digest exist in your User schema, details please see here

create_table “users”, force: true do |t|
    ……
    t.text     “password_digest”
    …..
end

If it works in your development but not test, please check if you do the rake db:migration in test env, I mean RAILS_ENV=test rake db:migrate.


!!!Updated -- related to shouda-matchers gocha

It seems a bug for shoulda-matchers, cause when you do this the test will pass:

it "should be validate uniq of email " do
    user.save
    expect(user).to validate_uniqueness_of :email
end

the reason why I am doing the user.save is because of this , otherwise it will create a record for you, that will cause the error you got:

# https://github.com/thoughtbot/shoulda-matchers/blob/master/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb#L126
 def create_record_in_database(options = {})
      if options[:nil_value]
        value = nil
      else
        value = "arbitrary_string"
      end

      @subject.class.new.tap do |instance|
        instance.send("#{@attribute}=", value)
        instance.save(:validate => false) # the error happens here, not in your code
      end
    end

So above all, this is probably a bug of shouda-matchers, though I didn't have time to figure out how to fix it, for now you can use this method as a work around, or use some other method to test this.

Hope it helps :-)

OTHER TIPS

Probably a bug in shoulda-matchers, maybe related to this one https://github.com/thoughtbot/shoulda-matchers/issues/290

Cheers

Answer to your question is here: https://github.com/thoughtbot/shoulda-matchers/issues/371

In short, here is the underlying issue:

It appears that the Rails 4 version of has_secure_password adds a before_create to ensure that password_digest is filled in; however, the Rails 3 version does not have this check.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top