Module: Shoulda::Matchers::ActiveRecord

Defined in:
lib/shoulda/matchers/active_record.rb,
lib/shoulda/matchers/active_record/uniqueness/model.rb,
lib/shoulda/matchers/active_record/serialize_matcher.rb,
lib/shoulda/matchers/active_record/association_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers.rb,
lib/shoulda/matchers/active_record/uniqueness/namespace.rb,
lib/shoulda/matchers/active_record/have_db_index_matcher.rb,
lib/shoulda/matchers/active_record/uniqueness/test_models.rb,
lib/shoulda/matchers/active_record/have_db_column_matcher.rb,
lib/shoulda/matchers/active_record/define_enum_for_matcher.rb,
lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb,
lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb,
lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb,
lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb,
lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb,
lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb,
lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb

Defined Under Namespace

Modules: Uniqueness

Instance Method Summary collapse

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
describe Car do
  it { should accept_nested_attributes_for(:doors) }
end

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

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

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

# Test::Unit
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
describe Person do
  it { should belong_to(:organization) }
end

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

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

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

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

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

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

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

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should belong_to(:world).dependent(:destroy)
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

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

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

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

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should belong_to(:organization).inverse_of(:employees)
end


240
241
242
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 240

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
describe Process do
  it { should define_enum_for(:status) }
  end
end

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

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

#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
describe Person do
  it { should have_and_belong_to_many(:awards) }
end

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

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

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

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:places_visited).
    class_name('City')
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

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

# Test::Unit
class AccountTest < ActiveSupport::TestCase
  should have_and_belong_to_many(:advertisers).autosave(true)
end


801
802
803
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 801

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
describe Phone do
  it { should have_db_column(:supported_ios_version) }
end

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

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

# Test::Unit
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
describe Blog do
  it { should have_db_index(:user_id) }
end

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

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

# Test::Unit
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
describe Person do
  it { should have_many(:friends) }
end

# Test::Unit
class PersonTest < ActiveSupport::TestCase
  should have_many(:friends)
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

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

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

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

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

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

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

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

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

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

# Test::Unit
class PlayerTest < ActiveSupport::TestCase
  should have_many(:games).autosave(true)
end


456
457
458
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 456

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
describe Person do
  it { should have_one(:partner) }
end

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

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

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

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

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

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

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

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

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

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

# Test::Unit
class AccountTest < ActiveSupport::TestCase
  should have_one(:bank).autosave(true)
end


666
667
668
# File 'lib/shoulda/matchers/active_record/association_matcher.rb', line 666

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
describe User do
  it { should have_readonly_attribute(:password) }
end

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

#serialize(name) ⇒ SerializeMatcher

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

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

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

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

# RSpec
describe Post do
  it { should validate_uniqueness_of(:permalink) }
end

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

Failures:

  1) Post should require case sensitive unique value for title
     Failure/Error: it { should validate_uniqueness_of(:title) }
     ActiveRecord::StatementInvalid:
       SQLite3::ConstraintException: posts.content may not be NULL: INSERT INTO "posts" ("title") VALUES (?)

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

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

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

# RSpec
describe Post do
  it { should validate_uniqueness_of(:slug).scoped_to(:journal_id) }
end

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

# Test::Unit
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:key).case_insensitive
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

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

# Test::Unit
class PostTest < ActiveSupport::TestCase
  should validate_uniqueness_of(:author_id).allow_blank
end


194
195
196
# File 'lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb', line 194

def validate_uniqueness_of(attr)
  ValidateUniquenessOfMatcher.new(attr)
end