module Shoulda::Matchers::ActiveModel

This mixin provides matchers that are used to test behavior, such as validations, that you've added to your ActiveModel (or ActiveRecord) objects.

### Testing conditional validations

If your model defines a validation conditionally – meaning that the validation is declared with an `:if` or `:unless` option – how do you test it? You might expect the validation matchers here to have corresponding `if` or `unless` qualifiers, but this isn't what you use. Instead, before using the matcher in question, you place the record you're testing in a state such that the validation you're also testing will be run. A common way to do this is to make a new `context` and override the subject to populate the record accordingly. You'll also want to make sure to test that the validation is not run when the conditional fails.

Here's an example to illustrate what we mean:

class User
  include ActiveModel::Model

  attr_accessor :role, :admin

  validates_presence_of :role, if: :admin
end

# RSpec
RSpec.describe User, type: :model do
  context "when an admin" do
    subject { User.new(admin: true) }

    it { should validate_presence_of(:role) }
  end

  context "when not an admin" do
    subject { User.new(admin: false) }

    it { should_not validate_presence_of(:role) }
  end
end

# Minitest (Shoulda)
class UserTest < ActiveSupport::TestCase
  context "when an admin" do
    subject { User.new(admin: true) }

    should validate_presence_of(:role)
  end

  context "when not an admin" do
    subject { User.new(admin: false) }

    should_not validate_presence_of(:role)
  end
end

Attributes

options[R]
result[R]
values_to_preset[R]
values_to_set[R]

Public Instance Methods

_after_setting_value(&callback) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 388
def _after_setting_value(&callback)
  @after_setting_value_callback = callback
end
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
RSpec.describe Post, type: :model do
  it { should allow_mass_assignment_of(:title) }
end

RSpec.describe User, type: :model do
  it { should_not allow_mass_assignment_of(:encrypted_password) }
end

# Minitest (Shoulda)
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
RSpec.describe Post, type: :model do
  it { should allow_mass_assignment_of(:title).as(:admin) }
end

# Minitest (Shoulda)
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 (or its alias, `allow_values`) is used to ensure that an attribute is valid or invalid if set to one or more values.

Take this model for example:

class UserProfile
  include ActiveModel::Model
  attr_accessor :website_url

  validates_format_of :website_url, with: URI.regexp
end

You can use `allow_value` to test one value at a time:

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

# Minitest (Shoulda)
class UserProfileTest < ActiveSupport::TestCase
  should allow_value('http://foo.com').for(:website_url)
  should allow_value('http://bar.com').for(:website_url)
end

You can also test multiple values in one go, if you like. In the positive sense, this makes an assertion that none of the values cause the record to be invalid. In the negative sense, this makes an assertion that none of the values cause the record to be valid:

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

  it do
    should_not allow_values('http://foo.com', 'buz').
      for(:website_url)
  end
end

# Minitest (Shoulda)
class UserProfileTest < ActiveSupport::TestCase
  should allow_values('http://foo.com', 'http://bar.com/baz').
    for(:website_url)

  should_not allow_values('http://foo.com', 'buz').
    for(:website_url)
end

#### Caveats

When using `allow_value` or any matchers that depend on it, you may encounter an AttributeChangedValueError. This exception is raised if the matcher, in attempting to set a value on the attribute, detects that the value set is different from the value that the attribute returns upon reading it back.

This usually happens if the writer method (`foo=`, `bar=`, etc.) for that attribute has custom logic to ignore certain incoming values or change them in any way. Here are three examples we've seen:

  • You're attempting to assert that an attribute should not allow nil, yet the attribute's writer method contains a conditional to do nothing if the attribute is set to nil:

    class Foo
      include ActiveModel::Model
    
      attr_reader :bar
    
      def bar=(value)
        return if value.nil?
        @bar = value
      end
    end
    
    RSpec.describe Foo, type: :model do
      it do
        foo = Foo.new
        foo.bar = "baz"
        # This will raise an AttributeChangedValueError since `foo.bar` is now "123"
        expect(foo).not_to allow_value(nil).for(:bar)
      end
    end
    
  • You're attempting to assert that a numeric attribute should not allow a string that contains non-numeric characters, yet the writer method for that attribute strips out non-numeric characters:

    class Foo
      include ActiveModel::Model
    
      attr_reader :bar
    
      def bar=(value)
        @bar = value.gsub(/\D+/, '')
      end
    end
    
    RSpec.describe Foo, type: :model do
      it do
        foo = Foo.new
        # This will raise an AttributeChangedValueError since `foo.bar` is now "123"
        expect(foo).not_to allow_value("abc123").for(:bar)
      end
    end
    
  • You're passing a value to `allow_value` that the model typecasts into another value:

    RSpec.describe Foo, type: :model do
      # Assume that `attr` is a string
      # This will raise an AttributeChangedValueError since `attr` typecasts `[]` to `"[]"`
      it { should_not allow_value([]).for(:attr) }
    end
    

Fortunately, if you understand why this is happening, and wish to get around this exception, it is possible to do so. You can use the `ignoring_interference_by_writer` qualifier like so:

it do
  should_not allow_value([]).
    for(:attr).
    ignoring_interference_by_writer
end

Please note, however, that this qualifier won't magically cause your test to pass. It may just so happen that the final value that ends up being set causes the model to fail validation. In that case, you'll have to figure out what to do. You may need to write your own test, or perhaps even remove your test altogether.

#### 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
RSpec.describe UserProfile, type: :model do
  it do
    should allow_value('2013-01-01').
      for(:birthday_as_string).
      on(:create)
  end
end

# Minitest (Shoulda)
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
RSpec.describe UserProfile, type: :model do
  it do
    should allow_value('open', 'closed').
      for(:state).
      with_message('State must be open or closed')
  end
end

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

Use `with_message` with a regexp to perform a partial match:

class UserProfile
  include ActiveModel::Model
  attr_accessor :state

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

# RSpec
RSpec.describe UserProfile, type: :model do
  it do
    should allow_value('open', 'closed').
      for(:state).
      with_message(/open or closed/)
  end
end

# Minitest (Shoulda)
class UserProfileTest < ActiveSupport::TestCase
  should allow_value('open', 'closed').
    for(:state).
    with_message(/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
RSpec.describe UserProfile, type: :model 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

# Minitest (Shoulda)
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

##### ignoring_interference_by_writer

Use `ignoring_interference_by_writer` to bypass an AttributeChangedValueError that you have encountered. Please read the Caveats section above for more information.

class Address < ActiveRecord::Base
  # Address has a zip_code field which is a string
end

# RSpec
RSpec.describe Address, type: :model do
  it do
    should_not allow_value([]).
      for(:zip_code).
      ignoring_interference_by_writer
  end
end

# Minitest (Shoulda)
class AddressTest < ActiveSupport::TestCase
  should_not allow_value([]).
    for(:zip_code).
    ignoring_interference_by_writer
end

@return [AllowValueMatcher]

# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 296
def allow_value(*values)
  if values.empty?
    raise ArgumentError, 'need at least one argument'
  else
    AllowValueMatcher.new(*values)
  end
end
Also aliased as: allow_values
allow_values(*values)

@private

Alias for: allow_value
description() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 500
def description
  ValidationMatcher::BuildDescription.call(self, simple_description)
end
does_not_match?(instance) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 398
def does_not_match?(instance)
  @instance = instance
  @result = run(:first_passing)
  @result.nil?
end
expected_message() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 365
def expected_message
  if options.key?(:expected_message)
    if Symbol === options[:expected_message]
      default_expected_message
    else
      options[:expected_message]
    end
  end
end
expects_custom_validation_message?() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 375
def expects_custom_validation_message?
  @expects_custom_validation_message
end
expects_strict?() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 384
def expects_strict?
  @expects_strict
end
failure_message() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 404
def failure_message
  attribute_setter = result.attribute_setter

  if result.attribute_setter.unsuccessfully_checked?
    message = attribute_setter.failure_message
  else
    validator = result.validator
    message = failure_message_preface.call
    message << ' valid, but it was invalid instead,'

    if validator.captured_validation_exception?
      message << ' raising a validation exception with the message '
      message << validator.validation_exception_message.inspect
      message << '.'
    else
      message << " producing these validation errors:\n\n"
      message << validator.all_formatted_validation_error_messages
    end
  end

  if include_attribute_changed_value_message?
    message << "\n\n" + attribute_changed_value_message.call
  end

  Shoulda::Matchers.word_wrap(message)
end
failure_message_when_negated() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 431
def failure_message_when_negated
  attribute_setter = result.attribute_setter

  if attribute_setter.unsuccessfully_checked?
    message = attribute_setter.failure_message
  else
    validator = result.validator
    message = failure_message_preface.call + ' invalid'

    if validator.type_of_message_matched?
      if validator.has_messages?
        message << ' and to'

        if validator.captured_validation_exception?
          message << ' raise a validation exception with message'
        else
          message << ' produce'

          if expected_message.is_a?(Regexp)
            message << ' a'
          else
            message << ' the'
          end

          message << ' validation error'
        end

        if expected_message.is_a?(Regexp)
          message << ' matching '
          message << Shoulda::Matchers::Util.inspect_value(
            expected_message
          )
        else
          message << " #{expected_message.inspect}"
        end

        unless validator.captured_validation_exception?
          message << " on :#{attribute_to_check_message_against}"
        end

        message << '. The record was indeed invalid, but'

        if validator.captured_validation_exception?
          message << ' the exception message was '
          message << validator.validation_exception_message.inspect
          message << ' instead.'
        else
          message << " it produced these validation errors instead:\n\n"
          message << validator.all_formatted_validation_error_messages
        end
      else
        message << ', but it was valid instead.'
      end
    elsif validator.captured_validation_exception?
      message << ' and to produce validation errors, but the record'
      message << ' raised a validation exception instead.'
    else
      message << ' and to raise a validation exception, but the record'
      message << ' produced validation errors instead.'
    end
  end

  if include_attribute_changed_value_message?
    message << "\n\n" + attribute_changed_value_message.call
  end

  Shoulda::Matchers.word_wrap(message)
end
for(attribute_name) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 337
def for(attribute_name)
  @attribute_to_set = attribute_name
  @attribute_to_check_message_against = attribute_name
  self
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
RSpec.describe User, type: :model do
  it { should have_secure_password }
end

# Minitest (Shoulda)
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
last_attribute_setter_used() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 512
def last_attribute_setter_used
  result.attribute_setter
end
last_value_set() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 516
def last_value_set
  last_attribute_setter_used.value_written
end
matches?(instance) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 392
def matches?(instance)
  @instance = instance
  @result = run(:first_failing)
  @result.nil?
end
model() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 508
def model
  instance.class
end
on(context) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 343
def on(context)
  if context.present?
    @context = context
  end

  self
end
simple_description() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 504
def simple_description
  "allow :#{attribute_to_set} to be #{inspected_values_to_set}"
end
strict(expects_strict = true) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 379
def strict(expects_strict = true)
  @expects_strict = expects_strict
  self
end
validate_absence_of(attr) click to toggle source

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

class PowerHungryCountry
  include ActiveModel::Model
  attr_accessor :nuclear_weapons

  validates_absence_of :nuclear_weapons
end

# RSpec
RSpec.describe PowerHungryCountry, type: :model do
  it { should validate_absence_of(:nuclear_weapons) }
end

# Minitest (Shoulda)
class PowerHungryCountryTest < ActiveSupport::TestCase
  should validate_absence_of(:nuclear_weapons)
end

#### Qualifiers

##### on

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

class PowerHungryCountry
  include ActiveModel::Model
  attr_accessor :nuclear_weapons

  validates_absence_of :nuclear_weapons, on: :create
end

# RSpec
RSpec.describe PowerHungryCountry, type: :model do
  it { should validate_absence_of(:nuclear_weapons).on(:create) }
end

# Minitest (Shoulda)
class PowerHungryCountryTest < ActiveSupport::TestCase
  should validate_absence_of(:nuclear_weapons).on(:create)
end

##### #with_message

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

class PowerHungryCountry
  include ActiveModel::Model
  attr_accessor :nuclear_weapons

  validates_absence_of :nuclear_weapons,
    message: "there shall be peace on Earth"
end

# RSpec
RSpec.describe PowerHungryCountry, type: :model do
  it do
    should validate_absence_of(:nuclear_weapons).
      with_message("there shall be peace on Earth")
  end
end

# Minitest (Shoulda)
class PowerHungryCountryTest < ActiveSupport::TestCase
  should validate_absence_of(:nuclear_weapons).
    with_message("there shall be peace on Earth")
end

@return [ValidateAbsenceOfMatcher}

# File lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb, line 75
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
RSpec.describe Registration, type: :model do
  it { should validate_acceptance_of(:eula) }
end

# Minitest (Shoulda)
class RegistrationTest < ActiveSupport::TestCase
  should validate_acceptance_of(:eula)
end

#### Qualifiers

##### on

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

class Registration
  include ActiveModel::Model
  attr_accessor :terms_of_service

  validates_acceptance_of :terms_of_service, on: :create
end

# RSpec
RSpec.describe Registration, type: :model do
  it do
    should validate_acceptance_of(:terms_of_service).
      on(:create)
  end
end

# Minitest (Shoulda)
class RegistrationTest < ActiveSupport::TestCase
  should validate_acceptance_of(:terms_of_service).on(:create)
end

##### #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
RSpec.describe Registration, type: :model do
  it do
    should validate_acceptance_of(:terms_of_service).
      with_message('You must accept the terms of service')
  end
end

# Minitest (Shoulda)
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 78
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
RSpec.describe User, type: :model do
  it { should validate_confirmation_of(:email) }
end

# Minitest (Shoulda)
class UserTest < ActiveSupport::TestCase
  should validate_confirmation_of(:email)
end

#### Qualifiers

##### on

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

class User
  include ActiveModel::Model
  attr_accessor :password

  validates_confirmation_of :password, on: :create
end

# RSpec
RSpec.describe User, type: :model do
  it { should validate_confirmation_of(:password).on(:create) }
end

# Minitest (Shoulda)
class UserTest < ActiveSupport::TestCase
  should validate_confirmation_of(:password).on(:create)
end

##### #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
RSpec.describe User, type: :model do
  it do
    should validate_confirmation_of(:password).
      with_message('Please re-enter your password')
  end
end

# Minitest (Shoulda)
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 75
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
RSpec.describe Game, type: :model do
  it do
    should validate_exclusion_of(:supported_os).
      in_array(['Mac', 'Linux'])
  end
end

# Minitest (Shoulda)
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
RSpec.describe Game, type: :model do
  it do
    should validate_exclusion_of(:floors_with_enemies).
      in_range(5..8)
  end
end

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

#### Qualifiers

##### on

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

class Game
  include ActiveModel::Model
  attr_accessor :weapon

  validates_exclusion_of :weapon,
    in: ['pistol', 'paintball gun', 'stick'],
    on: :create
end

# RSpec
RSpec.describe Game, type: :model do
  it do
    should validate_exclusion_of(:weapon).
      in_array(['pistol', 'paintball gun', 'stick']).
      on(:create)
  end
end

# Minitest (Shoulda)
class GameTest < ActiveSupport::TestCase
  should validate_exclusion_of(:weapon).
    in_array(['pistol', 'paintball gun', 'stick']).
    on(:create)
end

##### #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
RSpec.describe Game, type: :model do
  it do
    should validate_exclusion_of(:weapon).
      in_array(['pistol', 'paintball gun', 'stick']).
      with_message('You chose a puny weapon')
  end
end

# Minitest (Shoulda)
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 117
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: ['open', 'resolved', 'unresolved']
end

# RSpec
RSpec.describe Issue, type: :model do
  it do
    should validate_inclusion_of(:state).
      in_array(['open', 'resolved', 'unresolved'])
  end
end

# Minitest (Shoulda)
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:state).
    in_array(['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
RSpec.describe Issue, type: :model do
  it { should validate_inclusion_of(:state).in_range(1..5) }
end

# Minitest (Shoulda)
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 do
  should validate_inclusion_of(:imported).
    in_array([true, false])
end

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

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

class Issue
  include ActiveModel::Model
  attr_accessor :severity

  validates_inclusion_of :severity,
    in: %w(low medium high),
    on: :create
end

# RSpec
RSpec.describe Issue, type: :model do
  it do
    should validate_inclusion_of(:severity).
      in_array(%w(low medium high)).
      on(:create)
  end
end

# Minitest (Shoulda)
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:severity).
    in_array(%w(low medium high)).
    on(:create)
end

##### #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
RSpec.describe Issue, type: :model 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

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it do
    should validate_inclusion_of(:age).
      in_range(0..65).
      with_low_message('You do not receive any benefits')
  end
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it do
    should validate_inclusion_of(:age).
      in_range(0..21).
      with_high_message("You're too old for this stuff")
  end
end

# Minitest (Shoulda)
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: ['open', 'resolved', 'unresolved'],
    allow_nil: true
end

# RSpec
RSpec.describe Issue, type: :model do
  it do
    should validate_inclusion_of(:state).
      in_array(['open', 'resolved', 'unresolved']).
      allow_nil
  end
end

# Minitest (Shoulda)
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:state).
    in_array(['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: ['open', 'resolved', 'unresolved'],
    allow_blank: true
end

# RSpec
RSpec.describe Issue, type: :model do
  it do
    should validate_inclusion_of(:state).
      in_array(['open', 'resolved', 'unresolved']).
      allow_blank
  end
end

# Minitest (Shoulda)
class IssueTest < ActiveSupport::TestCase
  should validate_inclusion_of(:state).
    in_array(['open', 'resolved', 'unresolved']).
    allow_blank
end

@return [ValidateInclusionOfMatcher]

# File lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb, line 265
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

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

class User
  include ActiveModel::Model
  attr_accessor :password

  validates_length_of :password, minimum: 10, on: :create
end

# RSpec
RSpec.describe User, type: :model do
  it do
    should validate_length_of(:password).
      is_at_least(10).
      on(:create)
  end
end

# Minitest (Shoulda)
class UserTest < ActiveSupport::TestCase
  should validate_length_of(:password).
    is_at_least(10).
    on(:create)
end

##### 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

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

# Minitest (Shoulda)

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
RSpec.describe User, type: :model do
  it { should validate_length_of(:status_update).is_at_most(140) }
end

# Minitest (Shoulda)
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
RSpec.describe User, type: :model do
  it { should validate_length_of(:favorite_superhero).is_equal_to(6) }
end

# Minitest (Shoulda)
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
RSpec.describe User, type: :model do
  it do
    should validate_length_of(:password).
      is_at_least(5).is_at_most(30)
  end
end

# Minitest (Shoulda)
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 :password

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

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

# Minitest (Shoulda)
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
RSpec.describe User, type: :model 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

# Minitest (Shoulda)
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
RSpec.describe User, type: :model 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

# Minitest (Shoulda)
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 221
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
RSpec.describe Person, type: :model do
  it { should validate_numericality_of(:gpa) }
end

# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:gpa)
end

#### Qualifiers

##### on

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

class Person
  include ActiveModel::Model
  attr_accessor :number_of_dependents

  validates_numericality_of :number_of_dependents, on: :create
end

# RSpec
RSpec.describe Person, type: :model do
  it do
    should validate_numericality_of(:number_of_dependents).
      on(:create)
  end
end

# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should validate_numericality_of(:number_of_dependents).on(:create)
end

##### 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
RSpec.describe Person, type: :model do
  it { should validate_numericality_of(:age).only_integer }
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it do
    should validate_numericality_of(:number_of_cars).
      is_less_than(2)
  end
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it do
    should validate_numericality_of(:birth_year).
      is_less_than_or_equal_to(1987)
  end
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it { should validate_numericality_of(:weight).is_equal_to(150) }
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it do
    should validate_numericality_of(:height).
      is_greater_than_or_equal_to(55)
  end
end

# Minitest (Shoulda)
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 the `: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
RSpec.describe Person, type: :model do
  it do
    should validate_numericality_of(:legal_age).
      is_greater_than(21)
  end
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it { should validate_numericality_of(:birth_month).even }
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it { should validate_numericality_of(:birth_day).odd }
end

# Minitest (Shoulda)
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
RSpec.describe Person, type: :model do
  it do
    should validate_numericality_of(:number_of_dependents).
      with_message('Number of dependents must be a number')
  end
end

# Minitest (Shoulda)
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 Post
  include ActiveModel::Model
  attr_accessor :age

  validates_numericality_of :age, allow_nil: true
end

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

# Minitest (Shoulda)
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 301
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
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

##### 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

@return [ValidatePresenceOfMatcher]

# File lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb, line 108
def validate_presence_of(attr)
  ValidatePresenceOfMatcher.new(attr)
end
with_message(message, given_options = {}) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 351
def with_message(message, given_options = {})
  if message.present?
    @expects_custom_validation_message = true
    options[:expected_message] = message
    options[:expected_message_values] = given_options.fetch(:values, {})

    if given_options.key?(:against)
      @attribute_to_check_message_against = given_options[:against]
    end
  end

  self
end

Protected Instance Methods

attribute_changed_value_message() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 566
def attribute_changed_value_message
  @attribute_changed_value_message ||
    method(:default_attribute_changed_value_message)
end
attribute_setters_and_validators_for_values_to_set() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 595
def attribute_setters_and_validators_for_values_to_set
  @_attribute_setters_and_validators_for_values_to_set ||=
    AttributeSettersAndValidators.new(
      self,
      values_to_set.map { |value| [attribute_to_set, value] }
    )
end
attribute_setters_for_values_to_preset() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 590
def attribute_setters_for_values_to_preset
  @_attribute_setters_for_values_to_preset ||=
    AttributeSetters.new(self, values_to_preset)
end
default_attribute_changed_value_message() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 571
        def default_attribute_changed_value_message
          <<-MESSAGE.strip
As indicated in the message above, :#{result.attribute_setter.attribute_name}
seems to be changing certain values as they are set, and this could have
something to do with why this test is failing. If you've overridden the writer
method for this attribute, then you may need to change it to make this test
pass, or do something else entirely.
          MESSAGE
        end
default_attribute_message() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 618
def default_attribute_message
  default_error_message(
    options[:expected_message],
    default_attribute_message_values
  )
end
default_attribute_message_values() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 625
def default_attribute_message_values
  defaults = {
    model_name: model_name,
    instance: instance,
    attribute: attribute_to_check_message_against,
  }

  defaults.merge(options[:expected_message_values])
end
default_expected_message() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 610
def default_expected_message
  if expects_strict?
    "#{human_attribute_name} #{default_attribute_message}"
  else
    default_attribute_message
  end
end
default_failure_message_preface() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 540
def default_failure_message_preface
  ''.tap do |preface|
    if descriptions_for_preset_values.any?
      preface << 'After setting '
      preface << descriptions_for_preset_values.to_sentence
      preface << ', then '
    else
      preface << 'After '
    end

    preface << 'setting '
    preface << description_for_resulting_attribute_setter

    unless preface.end_with?('--')
      preface << ','
    end

    preface << " the matcher expected the #{model.name} to be"
  end
end
description_for_resulting_attribute_setter() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 586
def description_for_resulting_attribute_setter
  result.attribute_setter_description
end
descriptions_for_preset_values() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 581
def descriptions_for_preset_values
  attribute_setters_for_values_to_preset.
    map(&:attribute_setter_description)
end
failure_message_preface() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 536
def failure_message_preface
  @failure_message_preface || method(:default_failure_message_preface)
end
human_attribute_name() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 639
def human_attribute_name
  instance.class.human_attribute_name(
    attribute_to_check_message_against
  )
end
include_attribute_changed_value_message?() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 561
def include_attribute_changed_value_message?
  !ignore_interference_by_writer.never? &&
    result.attribute_setter.attribute_changed_value?
end
inspected_values_to_set() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 603
def inspected_values_to_set
  Shoulda::Matchers::Util.inspect_values(values_to_set).to_sentence(
    two_words_connector: " or ",
    last_word_connector: ", or "
  )
end
model_name() click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 635
def model_name
  instance.class.to_s.underscore
end
run(strategy) click to toggle source
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 531
def run(strategy)
  attribute_setters_for_values_to_preset.first_failing ||
    attribute_setters_and_validators_for_values_to_set.public_send(strategy)
end