Shoulda-matchers: PG::Error: ERROR: null value in column "password_digest" violates not-null constraint

Created on 19 Sep 2012  路  2Comments  路  Source: thoughtbot/shoulda-matchers

My model:

    class User < ActiveRecord::Base
      attr_accessible :email, :password, :password_confirmation

      has_many :albums, dependent: :destroy

      has_secure_password

      validates :email, presence: true,
                        uniqueness: true,
                        format: { with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/ }
    end

and my spec:

    require 'spec_helper'

    describe User do
      it { should respond_to :email }
      it { should respond_to :password }
      it { should respond_to :password_confirmation }
      it { should respond_to :albums }

      it { should validate_presence_of :email }
      it { should validate_uniqueness_of :email }
      it { should_not allow_value('invalid@email').for(:email) }
    end

This raises an exception:

 1) User 
     Failure/Error: it { should validate_uniqueness_of :email }
     ActiveRecord::StatementInvalid:
       PG::Error: ERROR:  null value in column "password_digest" violates not-null constraint
       : INSERT INTO "users" ("created_at", "email", "password_digest", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"
     # ./spec/models/user_spec.rb:14:in `block (2 levels) in <top (required)>'

In my schema.rb I have a :null => false constraint ofcourse.

I saw some other issues but not a pull request that fixes this. Any ideas?

Most helpful comment

The validates_uniqueness_of matcher needs an instance in the database to work. If there isn't an instance, it creates one in this method.

It creates an instance of the described class (in this case User) with the given attribute (in this case :email) set, but sets no other attributes. It bypasses Rails validations with :validate => false. Of course, it can't bypass DB constraints, so it fails.

Manually creating a record should work, like so:

describe User do
  # ...other tests ...
  it "validates uniqueness of email" do
    User.new(:password_digest => 'whatever', :email => 'something').save!(:validate => false)
    should validate_uniqueness_of :email
  end
end

All 2 comments

The validates_uniqueness_of matcher needs an instance in the database to work. If there isn't an instance, it creates one in this method.

It creates an instance of the described class (in this case User) with the given attribute (in this case :email) set, but sets no other attributes. It bypasses Rails validations with :validate => false. Of course, it can't bypass DB constraints, so it fails.

Manually creating a record should work, like so:

describe User do
  # ...other tests ...
  it "validates uniqueness of email" do
    User.new(:password_digest => 'whatever', :email => 'something').save!(:validate => false)
    should validate_uniqueness_of :email
  end
end

I see. Thank you.

Was this page helpful?
0 / 5 - 0 ratings