Method: Shoulda::Matchers::ActiveModel#validate_presence_of

Defined in:
lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb

#validate_presence_of(attr) ⇒ ValidatePresenceOfMatcher

The ‘validate_presence_of` matcher tests usage of the `validates_presence_of` validation.

class Robot
  include ActiveModel::Model
  attr_accessor :arms

  validates_presence_of :arms
end

# RSpec
RSpec.describe Robot, type: :model do
  it { should validate_presence_of(:arms) }
end

# Minitest (Shoulda)
class RobotTest < ActiveSupport::TestCase
  should validate_presence_of(:arms)
end

#### Caveats

Under Rails 4 and greater, if your model ‘has_secure_password` and you are validating presence of the password using a record whose password has already been set prior to calling the matcher, you will be instructed to use a record whose password is empty instead.

For example, given this scenario:

class User < ActiveRecord::Base
  has_secure_password validations: false

  validates_presence_of :password
end

RSpec.describe User, type: :model do
  subject { User.new(password: '123456') }

  it { should validate_presence_of(:password) }
end

the above test will raise an error like this:

The validation failed because your User model declares
`has_secure_password`, and `validate_presence_of` was called on a
user which has `password` already set to a value. Please use a user
with an empty `password` instead.

This happens because ‘has_secure_password` itself overrides your model so that it is impossible to set `password` to nil. This means that it is impossible to test that setting `password` to nil places your model in an invalid state (which in turn means that the validation itself is unnecessary).

#### Qualifiers

##### allow_nil

Use ‘allow_nil` if your model has an optional attribute.

class Robot
  include ActiveModel::Model
  attr_accessor :nickname

  validates_presence_of :nickname, allow_nil: true
end

# RSpec
RSpec.describe Robot, type: :model do
  it { should validate_presence_of(:nickname).allow_nil }
end

# Minitest (Shoulda)
class RobotTest < ActiveSupport::TestCase
  should validate_presence_of(:nickname).allow_nil
end

##### on

Use ‘on` if your validation applies only under a certain context.

class Robot
  include ActiveModel::Model
  attr_accessor :arms

  validates_presence_of :arms, on: :create
end

# RSpec
RSpec.describe Robot, type: :model do
  it { should validate_presence_of(:arms).on(:create) }
end

# Minitest (Shoulda)
class RobotTest < ActiveSupport::TestCase
  should validate_presence_of(:arms).on(:create)
end

##### with_message

Use ‘with_message` if you are using a custom validation message.

class Robot
  include ActiveModel::Model
  attr_accessor :legs

  validates_presence_of :legs, message: 'Robot has no legs'
end

# RSpec
RSpec.describe Robot, type: :model do
  it do
    should validate_presence_of(:legs).
      with_message('Robot has no legs')
  end
end

# Minitest (Shoulda)
class RobotTest < ActiveSupport::TestCase
  should validate_presence_of(:legs).
    with_message('Robot has no legs')
end


129
130
131
# File 'lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb', line 129

def validate_presence_of(attr)
  ValidatePresenceOfMatcher.new(attr)
end