Module: Shoulda::Matchers::ActiveRecord
Instance Method Summary (collapse)
-
- (AcceptNestedAttributesForMatcher) accept_nested_attributes_for(name)
The
accept_nested_attributes_for
matcher tests usage of theaccepts_nested_attributes_for
macro. -
- (AssociationMatcher) belong_to(name)
The
belong_to
matcher is used to ensure that abelong_to
association exists on your model. -
- (DefineEnumForMatcher) define_enum_for(attribute_name)
The
define_enum_for
matcher is used to test that theenum
macro has been used to decorate an attribute with enum methods. -
- (AssociationMatcher) have_and_belong_to_many(name)
The
have_and_belong_to_many
matcher is used to test that ahas_and_belongs_to_many
association exists on your model and that the join table exists in the database. -
- (HaveDbColumnMatcher) have_db_column(column)
The
have_db_column
matcher tests that the table that backs your model has a specific column. -
- (HaveDbIndexMatcher) have_db_index(columns)
The
have_db_index
matcher tests that the table that backs your model has a index on a specific column. -
- (AssociationMatcher) have_many(name)
The
have_many
matcher is used to test that ahas_many
orhas_many :through
association exists on your model. -
- (AssociationMatcher) have_one(name)
The
have_one
matcher is used to test that ahas_one
orhas_one :through
association exists on your model. -
- (HaveReadonlyAttributeMatcher) have_readonly_attribute(value)
The
have_readonly_attribute
matcher tests usage of theattr_readonly
macro. -
- (SerializeMatcher) serialize(name)
The
serialize
matcher tests usage of theserialize
macro. -
- (ValidateUniquenessOfMatcher) validate_uniqueness_of(attr)
The
validate_uniqueness_of
matcher tests usage of thevalidates_uniqueness_of
validation.
Instance Method Details
- (AcceptNestedAttributesForMatcher) accept_nested_attributes_for(name)
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
describe Car 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
describe Car 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
describe Car 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
describe Car 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 |
- (AssociationMatcher) belong_to(name)
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
describe Person 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
describe Comment 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Account 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
258 259 260 |
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 258 def belong_to(name) AssociationMatcher.new(:belongs_to, name) end |
- (DefineEnumForMatcher) define_enum_for(attribute_name)
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
describe Process do
it { should define_enum_for(:status) }
end
end
# Minitest (Shoulda)
class ProcessTest < ActiveSupport::TestCase
should define_enum_for(:status)
end
Qualifiers
with
Use with
to test that the enum has been defined with a certain set of
known values.
class Process < ActiveRecord::Base
enum status: [:running, :stopped, :suspended]
end
# RSpec
describe Process do
it do
should define_enum_for(:status).
with([:running, :stopped, :suspended])
end
end
# Minitest (Shoulda)
class ProcessTest < ActiveSupport::TestCase
should define_enum_for(:status).
with([:running, :stopped, :suspended])
end
49 50 51 |
# File 'lib/shoulda/matchers/active_record/define_enum_for_matcher.rb', line 49 def define_enum_for(attribute_name) DefineEnumForMatcher.new(attribute_name) end |
- (AssociationMatcher) have_and_belong_to_many(name)
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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Publisher 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
859 860 861 |
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 859 def have_and_belong_to_many(name) AssociationMatcher.new(:has_and_belongs_to_many, name) end |
- (HaveDbColumnMatcher) have_db_column(column)
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
describe Phone 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
describe Phone 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
describe Phone 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 |
- (HaveDbIndexMatcher) have_db_index(columns)
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
describe Blog 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
describe Blog 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 since for unique
to be true
, you can also
leave off the argument to save some keystrokes:
# RSpec
describe Blog 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 |
- (AssociationMatcher) have_many(name)
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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Player do
it { should have_many(:games).autosave(true) }
end
# Minitest (Shoulda)
class PlayerTest < ActiveSupport::TestCase
should have_many(:games).autosave(true)
end
491 492 493 |
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 491 def have_many(name) AssociationMatcher.new(:has_many, name) end |
- (AssociationMatcher) have_one(name)
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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Person 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
describe Account do
it { should have_one(:bank).autosave(true) }
end
# Minitest (Shoulda)
class AccountTest < ActiveSupport::TestCase
should have_one(:bank).autosave(true)
end
701 702 703 |
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 701 def have_one(name) AssociationMatcher.new(:has_one, name) end |
- (HaveReadonlyAttributeMatcher) have_readonly_attribute(value)
The have_readonly_attribute
matcher tests usage of the
attr_readonly
macro.
class User < ActiveRecord::Base
attr_readonly :password
end
# RSpec
describe User 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 |
- (SerializeMatcher) serialize(name)
The serialize
matcher tests usage of the serialize
macro.
class Product < ActiveRecord::Base
serialize :customizations
end
# RSpec
describe Product 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
describe Product 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
describe Product 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 |
- (ValidateUniquenessOfMatcher) validate_uniqueness_of(attr)
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_uniqueness_of :permalink
end
# RSpec
describe Post 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:
describe Post 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:
describe Post do
describe "validations" do
subject { Post.new(content: "Here is the content") }
it { should validate_uniqueness_of(:title) }
end
end
Or, if you're using
FactoryGirl and you have a
post
factory defined which automatically fills in content
, you can
say:
describe Post do
describe "validations" do
subject { FactoryGirl.build(: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_uniqueness_of :title, on: :create
end
# RSpec
describe Post 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_uniqueness_of :title, message: 'Please choose another title'
end
# RSpec
describe Post 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_uniqueness_of :slug, scope: :journal_id
end
# RSpec
describe Post 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_uniqueness_of :key, case_sensitive: false
end
# RSpec
describe Post 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_uniqueness_of :email
def email=(value)
super(value.downcase)
end
end
# RSpec
describe Post 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_uniqueness_of :author_id, allow_nil: true
end
# RSpec
describe Post 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_uniqueness_of :author_id, allow_blank: true
end
# RSpec
describe Post 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 |