module Shoulda::Matchers::ActiveModel

Public Instance Methods

allow_mass_assignment_of(value) click to toggle source

The `allow_mass_assignment_of` matcher tests usage of Rails 3's `attr_accessible` and `attr_protected` macros, asserting that an attribute in your model is contained in either the whitelist or blacklist and thus can or cannot be set via mass assignment.

class Post
  include ActiveModel::Model
  include ActiveModel::MassAssignmentSecurity
  attr_accessor :title

  attr_accessible :title
end

class User
  include ActiveModel::Model
  include ActiveModel::MassAssignmentSecurity
  attr_accessor :encrypted_password

  attr_protected :encrypted_password
end

# RSpec
describe Post do
  it { should allow_mass_assignment_of(:title) }
end

describe User do
  it { should_not allow_mass_assignment_of(:encrypted_password) }
end

# Test::Unit
class PostTest < ActiveSupport::TestCase
  should allow_mass_assignment_of(:title)
end

class UserTest < ActiveSupport::TestCase
  should_not allow_mass_assignment_of(:encrypted_password)
end

#### Optional qualifiers

##### as

Use `as` if your mass-assignment rules apply only under a certain role *(Rails >= 3.1 only)*.

class Post
  include ActiveModel::Model
  include ActiveModel::MassAssignmentSecurity
  attr_accessor :title

  attr_accessible :title, as: :admin
end

# RSpec
describe Post do
  it { should allow_mass_assignment_of(:title).as(:admin) }
end

# Test::Unit
class PostTest < ActiveSupport::TestCase
  should allow_mass_assignment_of(:title).as(:admin)
end

@return [AllowMassAssignmentOfMatcher]

# File lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb, line 70
def allow_mass_assignment_of(value)
  AllowMassAssignmentOfMatcher.new(value)
end
allow_value(*values) click to toggle source

The `allow_value` matcher is used to test that an attribute of a model can or cannot be set to a particular value or values. It is most commonly used in conjunction with the `validates_format_of` validation.

#### should

In the positive form, `allow_value` asserts that an attribute can be set to one or more values, succeeding if none of the values cause the record to be invalid:

class UserProfile
  include ActiveModel::Model
  attr_accessor :website_url

  validates_format_of :website_url, with: URI.regexp
end

# RSpec
describe UserProfile do
  it do
    should allow_value('http://foo.com', 'http://bar.com/baz').
      for(:website_url)
  end
end

# Test::Unit
class UserProfileTest < ActiveSupport::TestCase
  should allow_value('http://foo.com', 'http://bar.com/baz').
    for(:website_url)
end

#### should_not

In the negative form, `allow_value` asserts that an attribute cannot be set to one or more values, succeeding if the first value causes the record to be invalid.

**This can be surprising** so in this case if you need to check that all of the values are invalid, use separate assertions:

class UserProfile
  include ActiveModel::Model
  attr_accessor :website_url

  validates_format_of :website_url, with: URI.regexp
end

describe UserProfile do
  # One assertion: 'buz' and 'bar' will not be tested
  it { should_not allow_value('fiz', 'buz', 'bar').for(:website_url) }

  # Three assertions, all tested separately
  it { should_not allow_value('fiz').for(:website_url) }
  it { should_not allow_value('buz').for(:website_url) }
  it { should_not allow_value('bar').for(:website_url) }
end

#### Qualifiers

##### on

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

class UserProfile
  include ActiveModel::Model
  attr_accessor :birthday_as_string

  validates_format_of :birthday_as_string,
    with: /^(\d+)-(\d+)-(\d+)$/,
    on: :create
end

# RSpec
describe UserProfile do
  it do
    should allow_value('2013-01-01').
      for(:birthday_as_string).
      on(:create)
  end
end

# Test::Unit
class UserProfileTest < ActiveSupport::TestCase
  should allow_value('2013-01-01').
    for(:birthday_as_string).
    on(:create)
end

##### with_message

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

class UserProfile
  include ActiveModel::Model
  attr_accessor :state

  validates_format_of :state,
    with: /^(open|closed)$/,
    message: 'State must be open or closed'
end

# RSpec
describe UserProfile do
  it do
    should allow_value('open', 'closed').
      for(:state).
      with_message('State must be open or closed')
  end
end

# Test::Unit
class UserProfileTest < ActiveSupport::TestCase
  should allow_value('open', 'closed').
    for(:state).
    with_message('State must be open or closed')
end

Use `with_message` with the `:against` option if the attribute the validation message is stored under is different from the attribute being validated.

class UserProfile
  include ActiveModel::Model
  attr_accessor :sports_team

  validate :sports_team_must_be_valid

  private

  def sports_team_must_be_valid
    if sports_team !~ /^(Broncos|Titans)$/i
      self.errors.add :chosen_sports_team,
        'Must be either a Broncos fan or a Titans fan'
    end
  end
end

# RSpec
describe UserProfile do
  it do
    should allow_value('Broncos', 'Titans').
      for(:sports_team).
      with_message('Must be either a Broncos or Titans fan',
        against: :chosen_sports_team
      )
  end
end

# Test::Unit
class UserProfileTest < ActiveSupport::TestCase
  should allow_value('Broncos', 'Titans').
    for(:sports_team).
    with_message('Must be either a Broncos or Titans fan',
      against: :chosen_sports_team
    )
end

@return [AllowValueMatcher]

# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 163
def allow_value(*values)
  if values.empty?
    raise ArgumentError, 'need at least one argument'
  else
    AllowValueMatcher.new(*values)
  end
end
ensure_exclusion_of(attr) click to toggle source

@deprecated Use {#validate_exclusion_of} instead. @return [ValidateExclusionOfMatcher]

# File lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb, line 94
def ensure_exclusion_of(attr)
  Shoulda::Matchers.warn_about_deprecated_method(
    :ensure_exclusion_of,
    :validate_exclusion_of
  )
  validate_exclusion_of(attr)
end
ensure_inclusion_of(attr) click to toggle source

@deprecated Use {#validate_inclusion_of} instead. @return [ValidateInclusionOfMatcher]

# File lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb, line 239
def ensure_inclusion_of(attr)
  Shoulda::Matchers.warn_about_deprecated_method(
    :ensure_inclusion_of,
    :validate_inclusion_of
  )
  validate_inclusion_of(attr)
end
ensure_length_of(attr) click to toggle source

@deprecated Use {#validate_length_of} instead. @return [ValidateLengthOfMatcher]

# File lib/shoulda/matchers/active_model/validate_length_of_matcher.rb, line 202
def ensure_length_of(attr)
  Shoulda::Matchers.warn_about_deprecated_method(
    :ensure_length_of,
    :validate_length_of
  )
  validate_length_of(attr)
end
have_secure_password() click to toggle source

The `have_secure_password` matcher tests usage of the `has_secure_password` macro.

#### Example

class User
  include ActiveModel::Model
  include ActiveModel::SecurePassword
  attr_accessor :password

  has_secure_password
end

# RSpec
describe User do
  it { should have_secure_password }
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should have_secure_password
end

@return [HaveSecurePasswordMatcher]

# File lib/shoulda/matchers/active_model/have_secure_password_matcher.rb, line 29
def have_secure_password
  HaveSecurePasswordMatcher.new
end
validate_absence_of(attr) click to toggle source

The `validate_absence_of` matcher tests the usage of the `validates_absence_of` validation.

class Artillery
  include ActiveModel::Model
  attr_accessor :arms

  validates_absence_of :arms
end

# RSpec
describe Artillery do
  it { should validate_absence_of(:arms) }
end

# Test::Unit
class ArtilleryTest < ActiveSupport::TestCase
  should validate_absence_of(:arms)
end

#### Qualifiers

##### with_message

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

class Artillery
  include ActiveModel::Model
  attr_accessor :arms

  validates_absence_of :arms,
    message: "We're fresh outta arms here, soldier!"
end

# RSpec
describe Artillery do
  it do
    should validate_absence_of(:arms).
      with_message("We're fresh outta arms here, soldier!")
  end
end

# Test::Unit
class ArtilleryTest < ActiveSupport::TestCase
  should validate_absence_of(:arms).
    with_message("We're fresh outta arms here, soldier!")
end

@return [ValidateAbsenceOfMatcher}

# File lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb, line 54
def validate_absence_of(attr)
  ValidateAbsenceOfMatcher.new(attr)
end
validate_acceptance_of(attr) click to toggle source

The `validate_acceptance_of` matcher tests usage of the `validates_acceptance_of` validation.

class Registration
  include ActiveModel::Model
  attr_accessor :eula

  validates_acceptance_of :eula
end

# RSpec
describe Registration do
  it { should validate_acceptance_of(:eula) }
end

# Test::Unit
class RegistrationTest < ActiveSupport::TestCase
  should validate_acceptance_of(:eula)
end

#### Qualifiers

##### with_message

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

class Registration
  include ActiveModel::Model
  attr_accessor :terms_of_service

  validates_acceptance_of :terms_of_service,
    message: 'You must accept the terms of service'
end

# RSpec
describe Registration do
  it do
    should validate_acceptance_of(:terms_of_service).
      with_message('You must accept the terms of service')
  end
end

# Test::Unit
class RegistrationTest < ActiveSupport::TestCase
  should validate_acceptance_of(:terms_of_service).
    with_message('You must accept the terms of service')
end

@return [ValidateAcceptanceOfMatcher]

# File lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb, line 54
def validate_acceptance_of(attr)
  ValidateAcceptanceOfMatcher.new(attr)
end
validate_confirmation_of(attr) click to toggle source

The `validate_confirmation_of` matcher tests usage of the `validates_confirmation_of` validation.

class User
  include ActiveModel::Model
  attr_accessor :email

  validates_confirmation_of :email
end

# RSpec
describe User do
  it { should validate_confirmation_of(:email) }
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_confirmation_of(:email)
end

#### Qualifiers

##### with_message

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

class User
  include ActiveModel::Model
  attr_accessor :password

  validates_confirmation_of :password,
    message: 'Please re-enter your password'
end

# RSpec
describe User do
  it do
    should validate_confirmation_of(:password).
      with_message('Please re-enter your password')
  end
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_confirmation_of(:password).
    with_message('Please re-enter your password')
end

@return [ValidateConfirmationOfMatcher]

# File lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb, line 54
def validate_confirmation_of(attr)
  ValidateConfirmationOfMatcher.new(attr)
end
validate_exclusion_of(attr) click to toggle source

The `validate_exclusion_of` matcher tests usage of the `validates_exclusion_of` validation, asserting that an attribute cannot take a blacklist of values, and inversely, can take values outside of this list.

If your blacklist is an array of values, use `in_array`:

class Game
  include ActiveModel::Model
  attr_accessor :supported_os

  validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
end

# RSpec
describe Game do
  it do
    should validate_exclusion_of(:supported_os).
      in_array(['Mac', 'Linux'])
  end
end

# Test::Unit
class GameTest < ActiveSupport::TestCase
  should validate_exclusion_of(:supported_os).
    in_array(['Mac', 'Linux'])
end

If your blacklist is a range of values, use `in_range`:

class Game
  include ActiveModel::Model
  attr_accessor :supported_os

  validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
end

# RSpec
describe Game do
  it do
    should validate_exclusion_of(:floors_with_enemies).
      in_range(5..8)
  end
end

# Test::Unit
class GameTest < ActiveSupport::TestCase
  should validate_exclusion_of(:floors_with_enemies).
    in_range(5..8)
end

#### Qualifiers

##### with_message

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

class Game
  include ActiveModel::Model
  attr_accessor :weapon

  validates_exclusion_of :weapon,
    in: ['pistol', 'paintball gun', 'stick'],
    message: 'You chose a puny weapon'
end

# RSpec
describe Game do
  it do
    should validate_exclusion_of(:weapon).
      in_array(['pistol', 'paintball gun', 'stick']).
      with_message('You chose a puny weapon')
  end
end

# Test::Unit
class GameTest < ActiveSupport::TestCase
  should validate_exclusion_of(:weapon).
    in_array(['pistol', 'paintball gun', 'stick']).
    with_message('You chose a puny weapon')
end

@return [ValidateExclusionOfMatcher]

# File lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb, line 88
def validate_exclusion_of(attr)
  ValidateExclusionOfMatcher.new(attr)
end
validate_inclusion_of(attr) click to toggle source

The `validate_inclusion_of` matcher tests usage of the `validates_inclusion_of` validation, asserting that an attribute can take a whitelist of values and cannot take values outside of this list.

If your whitelist is an array of values, use `in_array`:

class Issue
  include ActiveModel::Model
  attr_accessor :state

  validates_inclusion_of :state, in: %w(open resolved unresolved)
end

# RSpec
describe Issue do
  it do
    should validate_inclusion_of(:state).
      in_array(%w(open resolved unresolved))
  end
end

# Test::Unit
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:state).
    in_array(%w(open resolved unresolved))
end

If your whitelist is a range of values, use `in_range`:

class Issue
  include ActiveModel::Model
  attr_accessor :priority

  validates_inclusion_of :priority, in: 1..5
end

# RSpec
describe Issue do
  it { should validate_inclusion_of(:state).in_range(1..5) }
end

# Test::Unit
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:state).in_range(1..5)
end

#### Caveats

We discourage using `validate_inclusion_of` with boolean columns. In fact, there is never a case where a boolean column will be anything but true, false, or nil, as ActiveRecord will type-cast an incoming value to one of these three values. That means there isn't any way we can refute this logic in a test. Hence, this will produce a warning:

it { should validate_inclusion_of(:imported).in_array([true, false]) }

The only case where `validate_inclusion_of` could be appropriate is for ensuring that a boolean column accepts nil, but we recommend using `allow_value` instead, like this:

it { should allow_value(nil).for(:imported) }

#### Qualifiers

##### with_message

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

class Issue
  include ActiveModel::Model
  attr_accessor :severity

  validates_inclusion_of :severity,
    in: %w(low medium high),
    message: 'Severity must be low, medium, or high'
end

# RSpec
describe Issue do
  it do
    should validate_inclusion_of(:severity).
      in_array(%w(low medium high)).
      with_message('Severity must be low, medium, or high')
  end
end

# Test::Unit
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:severity).
    in_array(%w(low medium high)).
    with_message('Severity must be low, medium, or high')
end

##### with_low_message

Use `with_low_message` if you have a custom validation message for when a given value is too low.

class Person
  include ActiveModel::Model
  attr_accessor :age

  validate :age_must_be_valid

  private

  def age_must_be_valid
    if age < 65
      self.errors.add :age, 'You do not receive any benefits'
    end
  end
end

# RSpec
describe Person do
  it do
    should validate_inclusion_of(:age).
      in_range(0..65).
      with_low_message('You do not receive any benefits')
  end
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_inclusion_of(:age).
    in_range(0..65).
    with_low_message('You do not receive any benefits')
end

##### with_high_message

Use `with_high_message` if you have a custom validation message for when a given value is too high.

class Person
  include ActiveModel::Model
  attr_accessor :age

  validate :age_must_be_valid

  private

  def age_must_be_valid
    if age > 21
      self.errors.add :age, "You're too old for this stuff"
    end
  end
end

# RSpec
describe Person do
  it do
    should validate_inclusion_of(:age).
      in_range(0..21).
      with_high_message("You're too old for this stuff")
  end
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_inclusion_of(:age).
    in_range(0..21).
    with_high_message("You're too old for this stuff")
end

##### allow_nil

Use `allow_nil` to assert that the attribute allows nil.

class Issue
  include ActiveModel::Model
  attr_accessor :state

  validates_presence_of :state
  validates_inclusion_of :state,
    in: %w(open resolved unresolved),
    allow_nil: true
end

# RSpec
describe Issue do
  it do
    should validate_inclusion_of(:state).
      in_array(%w(open resolved unresolved)).
      allow_nil
  end
end

# Test::Unit
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:state).
    in_array(%w(open resolved unresolved)).
    allow_nil
end

##### allow_blank

Use `allow_blank` to assert that the attribute allows blank.

class Issue
  include ActiveModel::Model
  attr_accessor :state

  validates_presence_of :state
  validates_inclusion_of :state,
    in: %w(open resolved unresolved),
    allow_blank: true
end

# RSpec
describe Issue do
  it do
    should validate_inclusion_of(:state).
      in_array(%w(open resolved unresolved)).
      allow_blank
  end
end

# Test::Unit
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:state).
    in_array(%w(open resolved unresolved)).
    allow_blank
end

@return [ValidateInclusionOfMatcher]

# File lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb, line 233
def validate_inclusion_of(attr)
  ValidateInclusionOfMatcher.new(attr)
end
validate_length_of(attr) click to toggle source

The `validate_length_of` matcher tests usage of the `validates_length_of` matcher. Note that this matcher is intended to be used against string columns and not integer columns.

#### Qualifiers

##### is_at_least

Use `is_at_least` to test usage of the `:minimum` option. This asserts that the attribute can take a string which is equal to or longer than the given length and cannot take a string which is shorter.

class User
  include ActiveModel::Model
  attr_accessor :bio

  validates_length_of :bio, minimum: 15
end

# RSpec

describe User do
  it { should validate_length_of(:bio).is_at_least(15) }
end

# Test::Unit

class UserTest < ActiveSupport::TestCase
  should validate_length_of(:bio).is_at_least(15)
end

##### is_at_most

Use `is_at_most` to test usage of the `:maximum` option. This asserts that the attribute can take a string which is equal to or shorter than the given length and cannot take a string which is longer.

class User
  include ActiveModel::Model
  attr_accessor :status_update

  validates_length_of :status_update, maximum: 140
end

# RSpec
describe User do
  it { should validate_length_of(:status_update).is_at_most(140) }
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_length_of(:status_update).is_at_most(140)
end

##### is_equal_to

Use `is_equal_to` to test usage of the `:is` option. This asserts that the attribute can take a string which is exactly equal to the given length and cannot take a string which is shorter or longer.

class User
  include ActiveModel::Model
  attr_accessor :favorite_superhero

  validates_length_of :favorite_superhero, is: 6
end

# RSpec
describe User do
  it { should validate_length_of(:favorite_superhero).is_equal_to(6) }
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_length_of(:favorite_superhero).is_equal_to(6)
end

##### is_at_least + is_at_most

Use `is_at_least` and `is_at_most` together to test usage of the `:in` option.

class User
  include ActiveModel::Model
  attr_accessor :password

  validates_length_of :password, in: 5..30
end

# RSpec
describe User do
  it do
    should validate_length_of(:password).
      is_at_least(5).is_at_most(30)
  end
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_length_of(:password).
    is_at_least(5).is_at_most(30)
end

##### with_message

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

class User
  include ActiveModel::Model
  attr_accessor :api_token

  validates_length_of :api_token,
    minimum: 10,
    message: "Password isn't long enough"
end

# RSpec
describe User do
  it do
    should validate_length_of(:password).
      is_at_least(10).
      with_message("Password isn't long enough")
  end
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_length_of(:password).
    is_at_least(10).
    with_message("Password isn't long enough")
end

##### with_short_message

Use `with_short_message` if you are using a custom “too short” message.

class User
  include ActiveModel::Model
  attr_accessor :secret_key

  validates_length_of :secret_key,
    in: 15..100,
    too_short: 'Secret key must be more than 15 characters'
end

# RSpec
describe User do
  it do
    should validate_length_of(:secret_key).
      is_at_least(15).
      with_short_message('Secret key must be more than 15 characters')
  end
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_length_of(:secret_key).
    is_at_least(15).
    with_short_message('Secret key must be more than 15 characters')
end

##### with_long_message

Use `with_long_message` if you are using a custom “too long” message.

class User
  include ActiveModel::Model
  attr_accessor :secret_key

  validates_length_of :secret_key,
    in: 15..100,
    too_long: 'Secret key must be less than 100 characters'
end

# RSpec
describe User do
  it do
    should validate_length_of(:secret_key).
      is_at_most(100).
      with_long_message('Secret key must be less than 100 characters')
  end
end

# Test::Unit
class UserTest < ActiveSupport::TestCase
  should validate_length_of(:secret_key).
    is_at_most(100).
    with_long_message('Secret key must be less than 100 characters')
end

@return [ValidateLengthOfMatcher]

# File lib/shoulda/matchers/active_model/validate_length_of_matcher.rb, line 196
def validate_length_of(attr)
  ValidateLengthOfMatcher.new(attr)
end
validate_numericality_of(attr) click to toggle source

The `validate_numericality_of` matcher tests usage of the `validates_numericality_of` validation.

class Person
  include ActiveModel::Model
  attr_accessor :gpa

  validates_numericality_of :gpa
end

# RSpec
describe Person do
  it { should validate_numericality_of(:gpa) }
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:gpa)
end

#### Qualifiers

##### only_integer

Use `only_integer` to test usage of the `:only_integer` option. This asserts that your attribute only allows integer numbers and disallows non-integer ones.

class Person
  include ActiveModel::Model
  attr_accessor :age

  validates_numericality_of :age, only_integer: true
end

# RSpec
describe Person do
  it { should validate_numericality_of(:age).only_integer }
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:age).only_integer
end

##### is_less_than

Use `is_less_than` to test usage of the the `:less_than` option. This asserts that the attribute can take a number which is less than the given value and cannot take a number which is greater than or equal to it.

class Person
  include ActiveModel::Model
  attr_accessor :number_of_cars

  validates_numericality_of :number_of_cars, less_than: 2
end

# RSpec
describe Person do
  it do
    should validate_numericality_of(:number_of_cars).
      is_less_than(2)
  end
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:number_of_cars).
    is_less_than(2)
end

##### is_less_than_or_equal_to

Use `is_less_than_or_equal_to` to test usage of the `:less_than_or_equal_to` option. This asserts that the attribute can take a number which is less than or equal to the given value and cannot take a number which is greater than it.

class Person
  include ActiveModel::Model
  attr_accessor :birth_year

  validates_numericality_of :birth_year, less_than_or_equal_to: 1987
end

# RSpec
describe Person do
  it do
    should validate_numericality_of(:birth_year).
      is_less_than_or_equal_to(1987)
  end
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:birth_year).
    is_less_than_or_equal_to(1987)
end

##### is_equal_to

Use `is_equal_to` to test usage of the `:equal_to` option. This asserts that the attribute can take a number which is equal to the given value and cannot take a number which is not equal.

class Person
  include ActiveModel::Model
  attr_accessor :weight

  validates_numericality_of :weight, equal_to: 150
end

# RSpec
describe Person do
  it { should validate_numericality_of(:weight).is_equal_to(150) }
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:weight).is_equal_to(150)
end

##### is_greater_than_or_equal_to

Use `is_greater_than_or_equal_to` to test usage of the `:greater_than_or_equal_to` option. This asserts that the attribute can take a number which is greater than or equal to the given value and cannot take a number which is less than it.

class Person
  include ActiveModel::Model
  attr_accessor :height

  validates_numericality_of :height, greater_than_or_equal_to: 55
end

# RSpec
describe Person do
  it do
    should validate_numericality_of(:height).
      is_greater_than_or_equal_to(55)
  end
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:height).
    is_greater_than_or_equal_to(55)
end

##### is_greater_than

Use `is_greater_than` to test usage of tthe `:greater_than` option. This asserts that the attribute can take a number which is greater than the given value and cannot take a number less than or equal to it.

class Person
  include ActiveModel::Model
  attr_accessor :legal_age

  validates_numericality_of :legal_age, greater_than: 21
end

# RSpec
describe Person do
  it do
    should validate_numericality_of(:legal_age).
      is_greater_than(21)
  end
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:legal_age).
    is_greater_than(21)
end

##### even

Use `even` to test usage of the `:even` option. This asserts that the attribute can take odd numbers and cannot take even ones.

class Person
  include ActiveModel::Model
  attr_accessor :birth_month

  validates_numericality_of :birth_month, even: true
end

# RSpec
describe Person do
  it { should validate_numericality_of(:birth_month).even }
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:birth_month).even
end

##### odd

Use `odd` to test usage of the `:odd` option. This asserts that the attribute can take a number which is odd and cannot take a number which is even.

class Person
  include ActiveModel::Model
  attr_accessor :birth_day

  validates_numericality_of :birth_day, odd: true
end

# RSpec
describe Person do
  it { should validate_numericality_of(:birth_day).odd }
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:birth_day).odd
end

##### with_message

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

class Person
  include ActiveModel::Model
  attr_accessor :number_of_dependents

  validates_numericality_of :number_of_dependents,
    message: 'Number of dependents must be a number'
end

# RSpec
describe Person do
  it do
    should validate_numericality_of(:number_of_dependents).
      with_message('Number of dependents must be a number')
  end
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:number_of_dependents).
    with_message('Number of dependents must be a number')
end

##### allow_nil

Use `allow_nil` to assert that the attribute allows nil.

class Age
  include ActiveModel::Model
  attr_accessor :age

  validates_numericality_of :age, allow_nil: true
end

# RSpec
describe Post do
  it { should validate_numericality_of(:age).allow_nil }
end

# Test::Unit
class PostTest < ActiveSupport::TestCase
  should validate_numericality_of(:age).allow_nil
end

@return [ValidateNumericalityOfMatcher]

# File lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb, line 277
def validate_numericality_of(attr)
  ValidateNumericalityOfMatcher.new(attr)
end
validate_presence_of(attr) click to toggle source

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
describe Robot do
  it { should validate_presence_of(:arms) }
end

# Test::Unit
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

describe User 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

##### 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
describe Robot do
  it { should validate_presence_of(:arms).on(:create) }
end

# Test::Unit
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
describe Robot do
  it do
    should validate_presence_of(:legs).
      with_message('Robot has no legs')
  end
end

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

@return [ValidatePresenceOfMatcher]

# File lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb, line 108
def validate_presence_of(attr)
  ValidatePresenceOfMatcher.new(attr)
end