Module: Shoulda::Matchers::ActiveRecord
Instance Method Summary collapse
- 
  
    
      #accept_nested_attributes_for(name)  ⇒ AcceptNestedAttributesForMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The accept_nested_attributes_formatcher tests usage of theaccepts_nested_attributes_formacro.
- 
  
    
      #belong_to(name)  ⇒ AssociationMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The belong_tomatcher is used to ensure that abelong_toassociation exists on your model.
- 
  
    
      #define_enum_for(attribute_name)  ⇒ DefineEnumForMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The define_enum_formatcher is used to test that theenummacro has been used to decorate an attribute with enum methods.
- 
  
    
      #have_and_belong_to_many(name)  ⇒ AssociationMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The have_and_belong_to_manymatcher is used to test that ahas_and_belongs_to_manyassociation exists on your model and that the join table exists in the database.
- 
  
    
      #have_db_column(column)  ⇒ HaveDbColumnMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The have_db_columnmatcher tests that the table that backs your model has a specific column.
- 
  
    
      #have_db_index(columns)  ⇒ HaveDbIndexMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The have_db_indexmatcher tests that the table that backs your model has a index on a specific column.
- 
  
    
      #have_many(name)  ⇒ AssociationMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The have_manymatcher is used to test that ahas_manyorhas_many :throughassociation exists on your model.
- 
  
    
      #have_one(name)  ⇒ AssociationMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The have_onematcher is used to test that ahas_oneorhas_one :throughassociation exists on your model.
- 
  
    
      #have_readonly_attribute(value)  ⇒ HaveReadonlyAttributeMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The have_readonly_attributematcher tests usage of theattr_readonlymacro.
- 
  
    
      #have_secure_token(token_attribute = :token)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    rubocop:disable Style/PredicateName. 
- 
  
    
      #serialize(name)  ⇒ SerializeMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The serializematcher tests usage of theserializemacro.
- 
  
    
      #validate_uniqueness_of(attr)  ⇒ ValidateUniquenessOfMatcher 
    
    
  
  
  
  
  
  
  
  
  
    The validate_uniqueness_ofmatcher tests usage of thevalidates_uniqueness_ofvalidation.
Instance Method Details
#accept_nested_attributes_for(name) ⇒ AcceptNestedAttributesForMatcher
The accept_nested_attributes_for matcher tests usage of the
accepts_nested_attributes_for macro.
class Car < ActiveRecord::Base
  accepts_nested_attributes_for :doors
end
# RSpec
RSpec.describe Car, type: :model do
  it { should accept_nested_attributes_for(:doors) }
end
# Minitest (Shoulda) (using Shoulda)
class CarTest < ActiveSupport::TestCase
  should accept_nested_attributes_for(:doors)
end
Qualifiers
allow_destroy
Use allow_destroy to assert that the :allow_destroy option was
specified.
class Car < ActiveRecord::Base
  accepts_nested_attributes_for :mirrors, allow_destroy: true
end
# RSpec
RSpec.describe Car, type: :model do
  it do
    should accept_nested_attributes_for(:mirrors).
      allow_destroy(true)
  end
end
# Minitest (Shoulda)
class CarTest < ActiveSupport::TestCase
  should accept_nested_attributes_for(:mirrors).
    allow_destroy(true)
end
limit
Use limit to assert that the :limit option was specified.
class Car < ActiveRecord::Base
  accepts_nested_attributes_for :windows, limit: 3
end
# RSpec
RSpec.describe Car, type: :model do
  it do
    should accept_nested_attributes_for(:windows).
      limit(3)
  end
end
# Minitest (Shoulda)
class CarTest < ActiveSupport::TestCase
  should accept_nested_attributes_for(:windows).
    limit(3)
end
update_only
Use update_only to assert that the :update_only option was
specified.
class Car < ActiveRecord::Base
  accepts_nested_attributes_for :engine, update_only: true
end
# RSpec
RSpec.describe Car, type: :model do
  it do
    should accept_nested_attributes_for(:engine).
      update_only(true)
  end
end
# Minitest (Shoulda)
class CarTest < ActiveSupport::TestCase
  should accept_nested_attributes_for(:engine).
    update_only(true)
end
| 93 94 95 | # File 'lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb', line 93 def accept_nested_attributes_for(name) AcceptNestedAttributesForMatcher.new(name) end | 
#belong_to(name) ⇒ AssociationMatcher
The belong_to matcher is used to ensure that a belong_to association
exists on your model.
class Person < ActiveRecord::Base
  belongs_to :organization
end
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:organization) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:organization)
end
Note that polymorphic associations are automatically detected and do not need any qualifiers:
class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end
# RSpec
RSpec.describe Comment, type: :model do
  it { should belong_to(:commentable) }
end
# Minitest (Shoulda)
class CommentTest < ActiveSupport::TestCase
  should belong_to(:commentable)
end
Qualifiers
conditions
Use conditions if your association is defined with a scope that sets
the where clause.
class Person < ActiveRecord::Base
  belongs_to :family, -> { where(everyone_is_perfect: false) }
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should belong_to(:family).
      conditions(everyone_is_perfect: false)
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:family).
    conditions(everyone_is_perfect: false)
end
order
Use order if your association is defined with a scope that sets the
order clause.
class Person < ActiveRecord::Base
  belongs_to :previous_company, -> { order('hired_on desc') }
end
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:previous_company).order('hired_on desc') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:previous_company).order('hired_on desc')
end
class_name
Use class_name to test usage of the :class_name option. This
asserts that the model you're referring to actually exists.
class Person < ActiveRecord::Base
  belongs_to :ancient_city, class_name: 'City'
end
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:ancient_city).class_name('City') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:ancient_city).class_name('City')
end
with_primary_key
Use with_primary_key to test usage of the :primary_key option.
class Person < ActiveRecord::Base
  belongs_to :great_country, primary_key: 'country_id'
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should belong_to(:great_country).
      with_primary_key('country_id')
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:great_country).
    with_primary_key('country_id')
end
with_foreign_key
Use with_foreign_key to test usage of the :foreign_key option.
class Person < ActiveRecord::Base
  belongs_to :great_country, foreign_key: 'country_id'
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should belong_to(:great_country).
      with_foreign_key('country_id')
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:great_country).
    with_foreign_key('country_id')
end
dependent
Use dependent to assert that the :dependent option was specified.
class Person < ActiveRecord::Base
  belongs_to :world, dependent: :destroy
end
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:world).dependent(:destroy) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:world).dependent(:destroy)
end
To assert that any :dependent option was specified, use true:
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:world).dependent(true) }
end
To assert that no :dependent option was specified, use false:
class Person < ActiveRecord::Base
  belongs_to :company
end
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:company).dependent(false) }
end
counter_cache
Use counter_cache to assert that the :counter_cache option was
specified.
class Person < ActiveRecord::Base
  belongs_to :organization, counter_cache: true
end
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:organization).counter_cache(true) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:organization).counter_cache(true)
end
touch
Use touch to assert that the :touch option was specified.
class Person < ActiveRecord::Base
  belongs_to :organization, touch: true
end
# RSpec
RSpec.describe Person, type: :model do
  it { should belong_to(:organization).touch(true) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:organization).touch(true)
end
autosave
Use autosave to assert that the :autosave option was specified.
class Account < ActiveRecord::Base
  belongs_to :bank, autosave: true
end
# RSpec
RSpec.describe Account, type: :model do
  it { should belong_to(:bank).autosave(true) }
end
# Minitest (Shoulda)
class AccountTest < ActiveSupport::TestCase
  should belong_to(:bank).autosave(true)
end
inverse_of
Use inverse_of to assert that the :inverse_of option was specified.
class Person < ActiveRecord::Base
  belongs_to :organization, inverse_of: :employees
end
# RSpec
describe Person
  it { should belong_to(:organization).inverse_of(:employees) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:organization).inverse_of(:employees)
end
required
Use required to assert that the association is not allowed to be nil.
(Enabled by default in Rails 5+.)
class Person < ActiveRecord::Base
  belongs_to :organization, required: true
end
# RSpec
describe Person
  it { should belong_to(:organization).required }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:organization).required
end
optional
Use optional to assert that the association is allowed to be nil.
(Rails 5+ only.)
class Person < ActiveRecord::Base
  belongs_to :organization, optional: true
end
# RSpec
describe Person
  it { should belong_to(:organization).optional }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should belong_to(:organization).optional
end
| 296 297 298 | # File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 296 def belong_to(name) AssociationMatcher.new(:belongs_to, name) end | 
#define_enum_for(attribute_name) ⇒ DefineEnumForMatcher
The define_enum_for matcher is used to test that the enum macro has
been used to decorate an attribute with enum methods.
class Process < ActiveRecord::Base
  enum status: [:running, :stopped, :suspended]
end
# RSpec
RSpec.describe Process, type: :model do
  it { should define_enum_for(:status) }
end
# Minitest (Shoulda)
class ProcessTest < ActiveSupport::TestCase
  should define_enum_for(:status)
end
Qualifiers
with_values
Use with_values to test that the attribute has been defined with a
certain set of possible values.
class Process < ActiveRecord::Base
  enum status: [:running, :stopped, :suspended]
end
# RSpec
RSpec.describe Process, type: :model do
  it do
    should define_enum_for(:status).
      with_values([:running, :stopped, :suspended])
  end
end
# Minitest (Shoulda)
class ProcessTest < ActiveSupport::TestCase
  should define_enum_for(:status).
    with_values([:running, :stopped, :suspended])
end
backed_by_column_of_type
Use backed_by_column_of_type to test that the attribute is of a
certain column type. (The default is :integer.)
class LoanApplication < ActiveRecord::Base
  enum status: {
    active: "active",
    pending: "pending",
    rejected: "rejected"
  }
end
# RSpec
RSpec.describe LoanApplication, type: :model do
  it do
    should define_enum_for(:status).
      with_values(
        active: "active",
        pending: "pending",
        rejected: "rejected"
      ).
      backed_by_column_of_type(:string)
  end
end
# Minitest (Shoulda)
class LoanApplicationTest < ActiveSupport::TestCase
  should define_enum_for(:status).
    with_values(
      active: "active",
      pending: "pending",
      rejected: "rejected"
    ).
    backed_by_column_of_type(:string)
end
with_prefix
Use with_prefix to test that the enum is defined with a _prefix
option (Rails 5 only). Can take either a boolean or a symbol:
class Issue < ActiveRecord::Base
  enum status: [:open, :closed], _prefix: :old
end
# RSpec
RSpec.describe Issue, type: :model do
  it do
    should define_enum_for(:status).
      with_values([:open, :closed]).
      with_prefix(:old)
  end
end
# Minitest (Shoulda)
class ProcessTest < ActiveSupport::TestCase
  should define_enum_for(:status).
    with_values([:open, :closed]).
    with_prefix(:old)
end
with_suffix
Use with_suffix to test that the enum is defined with a _suffix
option (Rails 5 only). Can take either a boolean or a symbol:
class Issue < ActiveRecord::Base
  enum status: [:open, :closed], _suffix: true
end
# RSpec
RSpec.describe Issue, type: :model do
  it do
    should define_enum_for(:status).
      with_values([:open, :closed]).
      with_suffix
  end
end
# Minitest (Shoulda)
class ProcessTest < ActiveSupport::TestCase
  should define_enum_for(:status).
    with_values([:open, :closed]).
    with_suffix
end
| 135 136 137 | # File 'lib/shoulda/matchers/active_record/define_enum_for_matcher.rb', line 135 def define_enum_for(attribute_name) DefineEnumForMatcher.new(attribute_name) end | 
#have_and_belong_to_many(name) ⇒ AssociationMatcher
The have_and_belong_to_many matcher is used to test that a
has_and_belongs_to_many association exists on your model and that the
join table exists in the database.
class Person < ActiveRecord::Base
  has_and_belongs_to_many :awards
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_and_belong_to_many(:awards) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:awards)
end
Qualifiers
conditions
Use conditions if your association is defined with a scope that sets
the where clause.
class Person < ActiveRecord::Base
  has_and_belongs_to_many :issues, -> { where(difficulty: 'hard') }
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should have_and_belong_to_many(:issues).
      conditions(difficulty: 'hard')
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:issues).
    conditions(difficulty: 'hard')
end
order
Use order if your association is defined with a scope that sets the
order clause.
class Person < ActiveRecord::Base
  has_and_belongs_to_many :projects, -> { order('time_spent') }
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should have_and_belong_to_many(:projects).
      order('time_spent')
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:projects).
    order('time_spent')
end
class_name
Use class_name to test usage of the :class_name option. This
asserts that the model you're referring to actually exists.
class Person < ActiveRecord::Base
  has_and_belongs_to_many :places_visited, class_name: 'City'
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should have_and_belong_to_many(:places_visited).
      class_name('City')
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:places_visited).
    class_name('City')
end
join_table
Use join_table to test usage of the :join_table option. This
asserts that the table you're referring to actually exists.
class Person < ActiveRecord::Base
  has_and_belongs_to_many :issues, join_table: 'people_tickets'
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should have_and_belong_to_many(:issues).
      join_table('people_tickets')
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:issues).
    join_table('people_tickets')
end
validate
Use validate to test that the :validate option was specified.
class Person < ActiveRecord::Base
  has_and_belongs_to_many :interviews, validate: false
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should have_and_belong_to_many(:interviews).
      validate(false)
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:interviews).
    validate(false)
end
autosave
Use autosave to assert that the :autosave option was specified.
class Publisher < ActiveRecord::Base
  has_and_belongs_to_many :advertisers, autosave: true
end
# RSpec
RSpec.describe Publisher, type: :model do
  it { should have_and_belong_to_many(:advertisers).autosave(true) }
end
# Minitest (Shoulda)
class AccountTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:advertisers).autosave(true)
end
| 953 954 955 | # File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 953 def have_and_belong_to_many(name) AssociationMatcher.new(:has_and_belongs_to_many, name) end | 
#have_db_column(column) ⇒ HaveDbColumnMatcher
The have_db_column matcher tests that the table that backs your model
has a specific column.
class CreatePhones < ActiveRecord::Migration
  def change
    create_table :phones do |t|
      t.string :supported_ios_version
    end
  end
end
# RSpec
RSpec.describe Phone, type: :model do
  it { should have_db_column(:supported_ios_version) }
end
# Minitest (Shoulda)
class PhoneTest < ActiveSupport::TestCase
  should have_db_column(:supported_ios_version)
end
Qualifiers
of_type
Use of_type to assert that a column is defined as a certain type.
class CreatePhones < ActiveRecord::Migration
  def change
    create_table :phones do |t|
      t.decimal :camera_aperture
    end
  end
end
# RSpec
RSpec.describe Phone, type: :model do
  it do
    should have_db_column(:camera_aperture).of_type(:decimal)
  end
end
# Minitest (Shoulda)
class PhoneTest < ActiveSupport::TestCase
  should have_db_column(:camera_aperture).of_type(:decimal)
end
with_options
Use with_options to assert that a column has been defined with
certain options (:precision, :limit, :default, :null, :scale,
or :primary).
class CreatePhones < ActiveRecord::Migration
  def change
    create_table :phones do |t|
      t.decimal :camera_aperture, precision: 1, null: false
    end
  end
end
# RSpec
RSpec.describe Phone, type: :model do
  it do
    should have_db_column(:camera_aperture).
      with_options(precision: 1, null: false)
  end
end
# Minitest (Shoulda)
class PhoneTest < ActiveSupport::TestCase
  should have_db_column(:camera_aperture).
    with_options(precision: 1, null: false)
end
| 81 82 83 | # File 'lib/shoulda/matchers/active_record/have_db_column_matcher.rb', line 81 def have_db_column(column) HaveDbColumnMatcher.new(column) end | 
#have_db_index(columns) ⇒ HaveDbIndexMatcher
The have_db_index matcher tests that the table that backs your model
has a index on a specific column.
class CreateBlogs < ActiveRecord::Migration
  def change
    create_table :blogs do |t|
      t.integer :user_id
    end
    add_index :blogs, :user_id
  end
end
# RSpec
RSpec.describe Blog, type: :model do
  it { should have_db_index(:user_id) }
end
# Minitest (Shoulda)
class BlogTest < ActiveSupport::TestCase
  should have_db_index(:user_id)
end
Qualifiers
unique
Use unique to assert that the index is unique.
class CreateBlogs < ActiveRecord::Migration
  def change
    create_table :blogs do |t|
      t.string :name
    end
    add_index :blogs, :name, unique: true
  end
end
# RSpec
RSpec.describe Blog, type: :model do
  it { should have_db_index(:name).unique(true) }
end
# Minitest (Shoulda)
class BlogTest < ActiveSupport::TestCase
  should have_db_index(:name).unique(true)
end
Since it only ever makes sense for unique to be true, you can also
leave off the argument to save some keystrokes:
# RSpec
RSpec.describe Blog, type: :model do
  it { should have_db_index(:name).unique }
end
# Minitest (Shoulda)
class BlogTest < ActiveSupport::TestCase
  should have_db_index(:name).unique
end
| 68 69 70 | # File 'lib/shoulda/matchers/active_record/have_db_index_matcher.rb', line 68 def have_db_index(columns) HaveDbIndexMatcher.new(columns) end | 
#have_many(name) ⇒ AssociationMatcher
The have_many matcher is used to test that a has_many or has_many
:through association exists on your model.
class Person < ActiveRecord::Base
  has_many :friends
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:friends) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:friends)
end
Note that polymorphic associations are automatically detected and do not need any qualifiers:
class Person < ActiveRecord::Base
  has_many :pictures, as: :imageable
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:pictures) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:pictures)
end
Qualifiers
conditions
Use conditions if your association is defined with a scope that sets
the where clause.
class Person < ActiveRecord::Base
  has_many :coins, -> { where(quality: 'mint') }
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:coins).conditions(quality: 'mint') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:coins).conditions(quality: 'mint')
end
order
Use order if your association is defined with a scope that sets the
order clause.
class Person < ActiveRecord::Base
  has_many :shirts, -> { order('color') }
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:shirts).order('color') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:shirts).order('color')
end
class_name
Use class_name to test usage of the :class_name option. This
asserts that the model you're referring to actually exists.
class Person < ActiveRecord::Base
  has_many :hopes, class_name: 'Dream'
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:hopes).class_name('Dream') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:hopes).class_name('Dream')
end
with_primary_key
Use with_primary_key to test usage of the :primary_key option.
class Person < ActiveRecord::Base
  has_many :worries, primary_key: 'worrier_id'
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:worries).with_primary_key('worrier_id') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:worries).with_primary_key('worrier_id')
end
with_foreign_key
Use with_foreign_key to test usage of the :foreign_key option.
class Person < ActiveRecord::Base
  has_many :worries, foreign_key: 'worrier_id'
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:worries).with_foreign_key('worrier_id') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:worries).with_foreign_key('worrier_id')
end
dependent
Use dependent to assert that the :dependent option was specified.
class Person < ActiveRecord::Base
  has_many :secret_documents, dependent: :destroy
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:secret_documents).dependent(:destroy) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:secret_documents).dependent(:destroy)
end
through
Use through to test usage of the :through option. This asserts that
the association you are going through actually exists.
class Person < ActiveRecord::Base
  has_many :acquaintances, through: :friends
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:acquaintances).through(:friends) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:acquaintances).through(:friends)
end
source
Use source to test usage of the :source option on a :through
association.
class Person < ActiveRecord::Base
  has_many :job_offers, through: :friends, source: :opportunities
end
# RSpec
RSpec.describe Person, type: :model do
  it do
    should have_many(:job_offers).
      through(:friends).
      source(:opportunities)
  end
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:job_offers).
    through(:friends).
    source(:opportunities)
end
validate
Use validate to assert that the :validate option was specified.
class Person < ActiveRecord::Base
  has_many :ideas, validate: false
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_many(:ideas).validate(false) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_many(:ideas).validate(false)
end
autosave
Use autosave to assert that the :autosave option was specified.
class Player < ActiveRecord::Base
  has_many :games, autosave: true
end
# RSpec
RSpec.describe Player, type: :model do
  it { should have_many(:games).autosave(true) }
end
# Minitest (Shoulda)
class PlayerTest < ActiveSupport::TestCase
  should have_many(:games).autosave(true)
end
index_errors
Use index_errors to assert that the :index_errors option was
specified.
class Player < ActiveRecord::Base
  has_many :games, index_errors: true
end
# RSpec
RSpec.describe Player, type: :model do
  it { should have_many(:games).index_errors(true) }
end
# Minitest (Shoulda)
class PlayerTest < ActiveSupport::TestCase
  should have_many(:games).index_errors(true)
end
inverse_of
Use inverse_of to assert that the :inverse_of option was specified.
class Organization < ActiveRecord::Base
  has_many :employees, inverse_of: :company
end
# RSpec
describe Organization
  it { should have_many(:employees).inverse_of(:company) }
end
# Minitest (Shoulda)
class OrganizationTest < ActiveSupport::TestCase
  should have_many(:employees).inverse_of(:company)
end
| 566 567 568 | # File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 566 def have_many(name) AssociationMatcher.new(:has_many, name) end | 
#have_one(name) ⇒ AssociationMatcher
The have_one matcher is used to test that a has_one or has_one
:through association exists on your model.
class Person < ActiveRecord::Base
  has_one :partner
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:partner) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:partner)
end
Qualifiers
conditions
Use conditions if your association is defined with a scope that sets
the where clause.
class Person < ActiveRecord::Base
  has_one :pet, -> { where('weight < 80') }
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:pet).conditions('weight < 80') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:pet).conditions('weight < 80')
end
order
Use order if your association is defined with a scope that sets the
order clause.
class Person < ActiveRecord::Base
  has_one :focus, -> { order('priority desc') }
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:focus).order('priority desc') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:focus).order('priority desc')
end
class_name
Use class_name to test usage of the :class_name option. This
asserts that the model you're referring to actually exists.
class Person < ActiveRecord::Base
  has_one :chance, class_name: 'Opportunity'
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:chance).class_name('Opportunity') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:chance).class_name('Opportunity')
end
dependent
Use dependent to test that the :dependent option was specified.
class Person < ActiveRecord::Base
  has_one :contract, dependent: :nullify
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:contract).dependent(:nullify) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:contract).dependent(:nullify)
end
with_primary_key
Use with_primary_key to test usage of the :primary_key option.
class Person < ActiveRecord::Base
  has_one :job, primary_key: 'worker_id'
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:job).with_primary_key('worker_id') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:job).with_primary_key('worker_id')
end
with_foreign_key
Use with_foreign_key to test usage of the :foreign_key option.
class Person < ActiveRecord::Base
  has_one :job, foreign_key: 'worker_id'
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:job).with_foreign_key('worker_id') }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:job).with_foreign_key('worker_id')
end
through
Use through to test usage of the :through option. This asserts that
the association you are going through actually exists.
class Person < ActiveRecord::Base
  has_one :life, through: :partner
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:life).through(:partner) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:life).through(:partner)
end
source
Use source to test usage of the :source option on a :through
association.
class Person < ActiveRecord::Base
  has_one :car, through: :partner, source: :vehicle
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:car).through(:partner).source(:vehicle) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:car).through(:partner).source(:vehicle)
end
validate
Use validate to assert that the the :validate option was specified.
class Person < ActiveRecord::Base
  has_one :parking_card, validate: false
end
# RSpec
RSpec.describe Person, type: :model do
  it { should have_one(:parking_card).validate(false) }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:parking_card).validate(false)
end
autosave
Use autosave to assert that the :autosave option was specified.
class Account < ActiveRecord::Base
  has_one :bank, autosave: true
end
# RSpec
RSpec.describe Account, type: :model do
  it { should have_one(:bank).autosave(true) }
end
# Minitest (Shoulda)
class AccountTest < ActiveSupport::TestCase
  should have_one(:bank).autosave(true)
end
required
Use required to assert that the association is not allowed to be nil.
(Rails 5+ only.)
class Person < ActiveRecord::Base
  has_one :brain, required: true
end
# RSpec
describe Person
  it { should have_one(:brain).required }
end
# Minitest (Shoulda)
class PersonTest < ActiveSupport::TestCase
  should have_one(:brain).required
end
| 795 796 797 | # File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 795 def have_one(name) AssociationMatcher.new(:has_one, name) end | 
#have_readonly_attribute(value) ⇒ HaveReadonlyAttributeMatcher
The have_readonly_attribute matcher tests usage of the
attr_readonly macro.
class User < ActiveRecord::Base
  attr_readonly :password
end
# RSpec
RSpec.describe User, type: :model do
  it { should have_readonly_attribute(:password) }
end
# Minitest (Shoulda)
class UserTest < ActiveSupport::TestCase
  should have_readonly_attribute(:password)
end
| 23 24 25 | # File 'lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb', line 23 def have_readonly_attribute(value) HaveReadonlyAttributeMatcher.new(value) end | 
#have_secure_token(token_attribute = :token) ⇒ Object
rubocop:disable Style/PredicateName
| 33 34 35 | # File 'lib/shoulda/matchers/active_record/have_secure_token_matcher.rb', line 33 def have_secure_token(token_attribute = :token) HaveSecureTokenMatcher.new(token_attribute) end | 
#serialize(name) ⇒ SerializeMatcher
The serialize matcher tests usage of the serialize macro.
class Product < ActiveRecord::Base
  serialize :customizations
end
# RSpec
RSpec.describe Product, type: :model do
  it { should serialize(:customizations) }
end
# Minitest (Shoulda)
class ProductTest < ActiveSupport::TestCase
  should serialize(:customizations)
end
Qualifiers
as
Use as if you are using a custom serializer class.
class ProductSpecsSerializer
  def load(string)
    # ...
  end
  def dump(options)
    # ...
  end
end
class Product < ActiveRecord::Base
  serialize :specifications, ProductSpecsSerializer
end
# RSpec
RSpec.describe Product, type: :model do
  it do
    should serialize(:specifications).
      as(ProductSpecsSerializer)
  end
end
# Minitest (Shoulda)
class ProductTest < ActiveSupport::TestCase
  should serialize(:specifications).
    as(ProductSpecsSerializer)
end
as_instance_of
Use as_instance_of if you are using a custom serializer object.
class ProductOptionsSerializer
  def load(string)
    # ...
  end
  def dump(options)
    # ...
  end
end
class Product < ActiveRecord::Base
  serialize :options, ProductOptionsSerializer.new
end
# RSpec
RSpec.describe Product, type: :model do
  it do
    should serialize(:options).
      as_instance_of(ProductOptionsSerializer)
  end
end
# Minitest (Shoulda)
class ProductTest < ActiveSupport::TestCase
  should serialize(:options).
    as_instance_of(ProductOptionsSerializer)
end
| 88 89 90 | # File 'lib/shoulda/matchers/active_record/serialize_matcher.rb', line 88 def serialize(name) SerializeMatcher.new(name) end | 
#validate_uniqueness_of(attr) ⇒ ValidateUniquenessOfMatcher
The validate_uniqueness_of matcher tests usage of the
validates_uniqueness_of validation. It first checks for an existing
instance of your model in the database, creating one if necessary. It
then takes a new instance of that model and asserts that it fails
validation if the attribute or attributes you've specified in the
validation are set to values which are the same as those of the
pre-existing record (thereby failing the uniqueness check).
class Post < ActiveRecord::Base
  validates :permalink, uniqueness: true
end
# RSpec
RSpec.describe Post, type: :model do
  it { should validate_uniqueness_of(:permalink) }
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:permalink)
end
Caveat
This matcher works a bit differently than other matchers. As noted
before, it will create an instance of your model if one doesn't already
exist. Sometimes this step fails, especially if you have database-level
restrictions on any attributes other than the one which is unique. In
this case, the solution is to populate these attributes with values
before you call validate_uniqueness_of.
For example, say you have the following migration and model:
class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :title
      t.text :content, null: false
    end
  end
end
class Post < ActiveRecord::Base
  validates :title, uniqueness: true
end
You may be tempted to test the model like this:
RSpec.describe Post, type: :model do
  it { should validate_uniqueness_of(:title) }
end
However, running this test will fail with an exception such as:
Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher::ExistingRecordInvalid:
  validate_uniqueness_of works by matching a new record against an
  existing record. If there is no existing record, it will create one
  using the record you provide.
  While doing this, the following error was raised:
    PG::NotNullViolation: ERROR:  null value in column "content" violates not-null constraint
    DETAIL:  Failing row contains (1, null, null).
    : INSERT INTO "posts" DEFAULT VALUES RETURNING "id"
  The best way to fix this is to provide the matcher with a record where
  any required attributes are filled in with valid values beforehand.
(The exact error message will differ depending on which database you're using, but you get the idea.)
This happens because validate_uniqueness_of tries to create a new post
but cannot do so because of the content attribute: though unrelated to
this test, it nevertheless needs to be filled in. As indicated at the
end of the error message, the solution is to build a custom Post object
ahead of time with content filled in:
RSpec.describe Post, type: :model do
  describe "validations" do
    subject { Post.create(content: "Here is the content") }
    it { should validate_uniqueness_of(:title) }
  end
end
Or, if you're using
FactoryBot and you have a
post factory defined which automatically fills in content, you can
say:
RSpec.describe Post, type: :model do
  describe "validations" do
    subject { FactoryBot.create(:post) }
    it { should validate_uniqueness_of(:title) }
  end
end
Qualifiers
Use on if your validation applies only under a certain context.
class Post < ActiveRecord::Base
  validates :title, uniqueness: true, on: :create
end
# RSpec
RSpec.describe Post, type: :model do
  it { should validate_uniqueness_of(:title).on(:create) }
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:title).on(:create)
end
with_message
Use with_message if you are using a custom validation message.
class Post < ActiveRecord::Base
  validates :title, uniqueness: true, message: 'Please choose another title'
end
# RSpec
RSpec.describe Post, type: :model do
  it do
    should validate_uniqueness_of(:title).
      with_message('Please choose another title')
  end
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:title).
    with_message('Please choose another title')
end
scoped_to
Use scoped_to to test usage of the :scope option. This asserts that
a new record fails validation if not only the primary attribute is not
unique, but the scoped attributes are not unique either.
class Post < ActiveRecord::Base
  validates :slug, uniqueness: true, scope: :journal_id
end
# RSpec
RSpec.describe Post, type: :model do
  it { should validate_uniqueness_of(:slug).scoped_to(:journal_id) }
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:slug).scoped_to(:journal_id)
end
case_insensitive
Use case_insensitive to test usage of the :case_sensitive option
with a false value. This asserts that the uniquable attributes fail
validation even if their values are a different case than corresponding
attributes in the pre-existing record.
class Post < ActiveRecord::Base
  validates :key, uniqueness: { case_sensitive: false }
end
# RSpec
RSpec.describe Post, type: :model do
  it { should validate_uniqueness_of(:key).case_insensitive }
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:key).case_insensitive
end
ignoring_case_sensitivity
By default, validate_uniqueness_of will check that the
validation is case sensitive: it asserts that uniquable attributes pass
validation when their values are in a different case than corresponding
attributes in the pre-existing record.
Use ignoring_case_sensitivity to skip this check. This qualifier is
particularly handy if your model has somehow changed the behavior of
attribute you're testing so that it modifies the case of incoming values
as they are set. For instance, perhaps you've overridden the writer
method or added a before_validation callback to normalize the
attribute.
class User < ActiveRecord::Base
  validates :email, uniqueness: true
  def email=(value)
    super(value.downcase)
  end
end
# RSpec
RSpec.describe Post, type: :model do
  it do
    should validate_uniqueness_of(:email).ignoring_case_sensitivity
  end
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:email).ignoring_case_sensitivity
end
allow_nil
Use allow_nil to assert that the attribute allows nil.
class Post < ActiveRecord::Base
  validates :author_id, uniqueness: true, allow_nil: true
end
# RSpec
RSpec.describe Post, type: :model do
  it { should validate_uniqueness_of(:author_id).allow_nil }
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:author_id).allow_nil
end
allow_blank
Use allow_blank to assert that the attribute allows a blank value.
class Post < ActiveRecord::Base
  validates :author_id, uniqueness: true, allow_blank: true
end
# RSpec
RSpec.describe Post, type: :model do
  it { should validate_uniqueness_of(:author_id).allow_blank }
end
# Minitest (Shoulda)
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:author_id).allow_blank
end
| 255 256 257 | # File 'lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb', line 255 def validate_uniqueness_of(attr) ValidateUniquenessOfMatcher.new(attr) end |