Module Remarkable::ActiveRecord::Matchers
In: lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb
lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb
lib/remarkable_activerecord/matchers/have_default_scope_matcher.rb
lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb
lib/remarkable_activerecord/matchers/accept_nested_attributes_for_matcher.rb
lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb
lib/remarkable_activerecord/matchers/validate_associated_matcher.rb
lib/remarkable_activerecord/matchers/have_column_matcher.rb
lib/remarkable_activerecord/matchers/association_matcher.rb
lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb
lib/remarkable_activerecord/matchers/have_scope_matcher.rb
lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb
lib/remarkable_activerecord/matchers/have_index_matcher.rb
lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb
lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb
lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb
lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb
lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb

Holds ActiveRecord matchers.

Validations matchers

Remarkable supports all ActiveRecord validations, and the only options not supported in those matchers is the :on options. So whenever you have to test that a validation runs on update, you have to do reproduce the state in your tests:

  describe Project do
    describe 'validations on create' do
      should_validate_presence_of :title
    end

    describe 'validations on update' do
      subject { Post.create!(@valid_attributes) }
      should_validate_presence_of :updated_at
    end
  end

Another behavior in validations is the :message option. Whenever you change the message in your model, it must be given in your tests too:

  class Post < ActiveRecord::Base
    validates_presence_of :title, :message => 'must be filled'
  end

  describe Post do
    should_validate_presence_of :title #=> fails
    should_validate_presence_of :title, :message => 'must be filled'
  end

However, if you change the title using the I18n API, you don‘t need to specify the message in your tests, because it‘s retrieved properly.

Methods

Public Instance methods

Ensures that the model accepts nested attributes for the given associations.

Options

  • allow_destroy - When true allows the association to be destroyed
  • accept - attributes that should be accepted by the :reject_if proc
  • reject - attributes that should be rejected by the :reject_if proc

Examples

  should_accept_nested_attributes_for :tasks
  should_accept_nested_attributes_for :tasks, :allow_destroy => true

:accept and :reject takes objects that are verified against the proc. So having a model:

  class Projects < ActiveRecord::Base
    has_many :tasks
    accepts_nested_attributes_for :tasks, :reject_if => proc { |a| a[:title].blank? }
  end

You can have the following specs:

  should_accept_nested_attributes_for :tasks, :reject => { :title => '' }        # Passes
  should_accept_nested_attributes_for :tasks, :accept => { :title => 'My task' } # Passes

  should_accept_nested_attributes_for :tasks, :accept => { :title => 'My task' },
                                              :reject => { :title => '' }        # Passes

  should_accept_nested_attributes_for :tasks, :accept => { :title => '' }        # Fail
  should_accept_nested_attributes_for :tasks, :reject => { :title => 'My task' } # Fail

You can also give arrays to :accept and :reject to verify multiple attributes. In such cases the block syntax is more recommended for readability:

  should_accept_nested_attributes_for :tasks do
    m.allow_destroy(false)
    m.accept :title => 'My task'
    m.accept :title => 'Another task'
    m.reject :title => nil
    m.reject :title => ''
  end

[Source]

     # File lib/remarkable_activerecord/matchers/accept_nested_attributes_for_matcher.rb, line 125
125:       def accept_nested_attributes_for(*args, &block)
126:         AcceptNestedAttributesForMatcher.new(*args, &block).spec(self)
127:       end

Ensures that the attribute can be set on mass update.

Examples

  should_allow_mass_assignment_of :email, :name
  it { should allow_mass_assignment_of(:email, :name) }

[Source]

    # File lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb, line 61
61:       def allow_mass_assignment_of(*attributes, &block)
62:         AllowMassAssignmentOfMatcher.new(*attributes, &block).spec(self)
63:       end

Ensures that the attribute can be set to the given values.

Options

  • :allow_nil - when supplied, validates if it allows nil or not.
  • :allow_blank - when supplied, validates if it allows blank or not.
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.invalid’)

Examples

  should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
  it { should allow_values_for(:isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0") }

[Source]

    # File lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb, line 79
79:       def allow_values_for(attribute, *args, &block)
80:         options = args.extract_options!
81:         AllowValuesForMatcher.new(attribute, options.merge!(:in => args), &block).spec(self)
82:       end

Ensure that the belongs_to relationship exists. Will also test that the subject table has the association_id column.

Options

  • :class_name - the expected associted class name.
  • :foreign_key - the expected foreign key in the subject table.
  • :dependent - the expected dependent value for the association.
  • :readonly - checks wether readonly is true or false.
  • :validate - checks wether validate is true or false.
  • :autosave - checks wether autosave is true or false.
  • :counter_cache - the expected dependent value for the association. It also checks if the column actually exists in the table.
  • :polymorphic - if the association should be polymorphic or not. When true it also checks for the association_type column in the subject table.

Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.

Examples

  should_belong_to :parent, :polymorphic => true
  it { should belong_to(:parent) }

[Source]

     # File lib/remarkable_activerecord/matchers/association_matcher.rb, line 187
187:       def belong_to(*associations, &block)
188:         AssociationMatcher.new(:belongs_to, *associations, &block).spec(self)
189:       end

Ensures that the has_and_belongs_to_many relationship exists, if the join table is in place and if the foreign_key column exists.

Options

  • :class_name - the expected associted class name.
  • :join_table - the expected join table name.
  • :foreign_key - the expected foreign key in the association table.
  • :uniq - checks wether uniq is true or false.
  • :readonly - checks wether readonly is true or false.
  • :validate - checks wether validate is true or false.
  • :autosave - checks wether autosave is true or false.

Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.

Examples

 should_have_and_belong_to_many :posts, :cars
 it{ should have_and_belong_to_many :posts, :cars }

[Source]

     # File lib/remarkable_activerecord/matchers/association_matcher.rb, line 212
212:       def have_and_belong_to_many(*associations, &block)
213:         AssociationMatcher.new(:has_and_belongs_to_many, *associations, &block).spec(self)
214:       end

Ensures that a column of the database actually exists.

Options

  • All options available in migrations are available:

    :type, :default, :precision, :limit, :scale, :sql_type, :primary, :null

Examples

  should_have_column :name, :type => :string, :default => ''

  it { should have_column(:name, :type => :string) }
  it { should have_column(:name).type(:string) }

[Source]

    # File lib/remarkable_activerecord/matchers/have_column_matcher.rb, line 59
59:       def have_column(*args, &block)
60:         HaveColumnMatcher.new(*args, &block).spec(self)
61:       end
have_columns(*args, &block)

Alias for have_column

have_db_column(*args, &block)

Alias for have_column

have_db_columns(*args, &block)

Alias for have_column

have_db_index(*args, &block)

Alias for have_index

have_db_indices(*args, &block)

Alias for have_index

Ensures that the model has a default scope with the given options.

Options

All options that the default scope would pass on to find: :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :having, :from, :lock.

Examples

  it { should have_default_scope(:conditions => {:visible => true}) }
  it { should have_default_scope.conditions(:visible => true) }

Passes for:

  default_scope :conditions => { :visible => true }

If you set two different default scopes, you have to spec them separatedly. Given the scopes:

  default_scope :conditions => { :visible => true }
  default_scope :conditions => { :published => true }

Then we have the matchers:

  should_have_default_scope :conditions => { :visible => true }   # Passes
  should_have_default_scope :conditions => { :published => true } # Passes

  should_have_default_scope :conditions => { :published => true,
                                              :visible => true }  # Fails

[Source]

    # File lib/remarkable_activerecord/matchers/have_default_scope_matcher.rb, line 63
63:       def have_default_scope(*args, &block)
64:         HaveDefaultScopeMatcher.new(*args, &block).spec(self)
65:       end

Ensures the database column has specified index.

Options

  • unique - when supplied, tests if the index is unique or not
  • table_name - when supplied, tests if the index is defined for the given table

Examples

  it { should have_index(:ssn).unique(true) }
  it { should have_index([:name, :email]).unique(true) }

  should_have_index :ssn, :unique => true, :limit => 9, :null => false

  should_have_index :ssn do |m|
    m.unique
    m.limit = 9
    m.null = false
  end

[Source]

    # File lib/remarkable_activerecord/matchers/have_index_matcher.rb, line 64
64:       def have_index(*args, &block)
65:         HaveIndexMatcher.new(*args, &block).spec(self)
66:       end
have_indices(*args, &block)

Alias for have_index

Ensures that the has_many relationship exists. Will also test that the associated table has the required columns. It works by default with polymorphic association (:as does not have to be supplied).

Options

  • :class_name - the expected associted class name.
  • :through - the expected join model which to perform the query. It also checks if the through table exists.
  • :source - the source of the through association.
  • :source_type - the source type of the through association.
  • :foreign_key - the expected foreign key in the associated table. When used with :through, it will check for the foreign key in the join table.
  • :dependent - the expected dependent value for the association.
  • :uniq - checks wether uniq is true or false.
  • :readonly - checks wether readonly is true or false.
  • :validate - checks wether validate is true or false.
  • :autosave - checks wether autosave is true or false.

Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.

Examples

  should_have_many :friends
  should_have_many :enemies, :through => :friends
  should_have_many :enemies, :dependent => :destroy

  it{ should have_many(:friends) }
  it{ should have_many(:enemies, :through => :friends) }
  it{ should have_many(:enemies, :dependent => :destroy) }

[Source]

     # File lib/remarkable_activerecord/matchers/association_matcher.rb, line 248
248:       def have_many(*associations, &block)
249:         AssociationMatcher.new(:has_many, *associations, &block).spec(self)
250:       end
have_named_scope(*args, &block)

Alias for have_scope

Ensures that the has_many relationship exists. Will also test that the associated table has the required columns. It works by default with polymorphic association (:as does not have to be supplied).

Options

  • :class_name - the expected associted class name.
  • :through - the expected join model which to perform the query. It also checks if the through table exists.
  • :source - the source of the through association.
  • :source_type - the source type of the through association.
  • :foreign_key - the expected foreign key in the associated table. When used with :through, it will check for the foreign key in the join table.
  • :dependent - the expected dependent value for the association.
  • :validate - checks wether validate is true or false.
  • :autosave - checks wether autosave is true or false.

Plus all supported sql conditions options: :select, :conditions, :order, :limit, :offset, :include, :group, :having.

Examples

 should_have_one :universe
 it{ should have_one(:universe) }

[Source]

     # File lib/remarkable_activerecord/matchers/association_matcher.rb, line 277
277:       def have_one(*associations, &block)
278:         AssociationMatcher.new(:has_one, *associations, &block).spec(self)
279:       end
have_readonly_attribute(*attributes, &block)

Ensures that the attribute cannot be changed once the record has been created.

Examples

  it { should have_readonly_attributes(:password, :admin_flag) }

[Source]

    # File lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb, line 23
23:       def have_readonly_attributes(*attributes, &block)
24:         HaveReadonlyAttributesMatcher.new(*attributes, &block).spec(self)
25:       end

Ensures that the model has a method named scope that returns a NamedScope object with the supplied proxy options.

Options

  • with - Options to be sent to the named scope

All options that the named scope would pass on to find: :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :having, :from, :lock.

Examples

  it { should have_scope(:visible, :conditions => {:visible => true}) }
  it { should have_scope(:visible).conditions(:visible => true) }

Passes for

  named_scope :visible, :conditions => {:visible => true}

Or for

  def self.visible
    scoped(:conditions => {:visible => true})
  end

You can test lambdas or methods that return ActiveRecord#scoped calls:

  it { should have_scope(:recent, :with => 5) }
  it { should have_scope(:recent, :with => 1) }

Passes for

  named_scope :recent, lambda {|c| {:limit => c}}

Or for

  def self.recent(c)
    scoped(:limit => c)
  end

[Source]

    # File lib/remarkable_activerecord/matchers/have_scope_matcher.rb, line 78
78:       def have_scope(*args, &block)
79:         HaveScopeMatcher.new(*args, &block).spec(self)
80:       end

Ensures that the model cannot be saved if one of the attributes listed is not accepted.

Options

  • :accept - the expected value to be accepted.
  • :allow_nil - when supplied, validates if it allows nil or not.
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.accepted’)

Examples

  should_validate_acceptance_of :eula, :terms
  should_validate_acceptance_of :eula, :terms, :accept => true

  it { should validate_acceptance_of(:eula, :terms) }
  it { should validate_acceptance_of(:eula, :terms, :accept => true) }

[Source]

    # File lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb, line 44
44:       def validate_acceptance_of(*attributes, &block)
45:         ValidateAcceptanceOfMatcher.new(*attributes, &block).spec(self)
46:       end

Ensures that the model is invalid if one of the associations given is invalid. It tries to build the association automatically. In has_one and belongs_to cases, it will build it like this:

  @model.build_association
  @project.build_manager

In has_many and has_and_belongs_to_many to cases it will build it like this:

  @model.association.build
  @project.tasks.build

The object returned MUST be invalid and it‘s likely the case, since the associated object is empty when calling build. However, if the associated object has to be manipulated to be invalid, you will have to give :builder as option or a block to manipulate it:

  should_validate_associated(:tasks) do |project|
    project.tasks.build(:captcha => 'i_am_a_bot')
  end

In the case above, the associated object task is only invalid when the captcha attribute is set. So we give a block to the matcher that tell exactly how to build an invalid object.

The example above can also be written as:

  should_validate_associated :tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_bot') }

Options

  • :builder - a proc to build the association
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.invalid’)

Examples

  should_validate_associated :tasks
  should_validate_associated :tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_bot') }

  should_validate_associated :tasks do |m|
    m.builder { |p| p.tasks.build(:captcha => 'i_am_a_bot') }
  end

  it { should validate_associated(:tasks) }
  it { should validate_associated(:tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_bot') }) }

[Source]

     # File lib/remarkable_activerecord/matchers/validate_associated_matcher.rb, line 98
 98:       def validate_associated(*args, &block)
 99:         ValidateAssociatedMatcher.new(*args, &block).spec(self)
100:       end

Ensures that the model cannot be saved if one of the attributes is not confirmed.

Options

  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.confirmation’)

Examples

  should_validate_confirmation_of :email, :password

  it { should validate_confirmation_of(:email, :password) }

[Source]

    # File lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb, line 38
38:       def validate_confirmation_of(*attributes, &block)
39:         ValidateConfirmationOfMatcher.new(*attributes, &block).spec(self)
40:       end

Ensures that given values are not valid for the attribute. If a range is given, ensures that the attribute is not valid in the given range.

If you give that :username does not accept ["admin", "user"], it will test that "uses" (the next of the array max value) is allowed.

Options

  • :in - values to test exclusion.
  • :allow_nil - when supplied, validates if it allows nil or not.
  • :allow_blank - when supplied, validates if it allows blank or not.
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.exclusion’)

Examples

  it { should validate_exclusion_of(:username, :in => ["admin", "user"]) }
  it { should validate_exclusion_of(:age, :in => 30..60) }

  should_validate_exclusion_of :username, :in => ["admin", "user"]
  should_validate_exclusion_of :age, :in => 30..60

[Source]

    # File lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb, line 51
51:       def validate_exclusion_of(*args, &block)
52:         ValidateExclusionOfMatcher.new(*args, &block).spec(self)
53:       end

Deprecated. Use allow_values_for instead.

[Source]

    # File lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb, line 86
86:       def validate_format_of(*args)
87:         if caller[0] =~ /\macros.rb/
88:           warn "[DEPRECATION] should_validate_format_of is deprecated, use should_allow_values_for instead."
89:         else
90:           warn "[DEPRECATION] validate_format_of is deprecated, use allow_values_for instead. Called from #{caller[0]}."
91:         end
92:         allow_values_for(*args)
93:       end

Ensures that given values are valid for the attribute. If a range is given, ensures that the attribute is valid in the given range.

If you give that :size accepts ["S", "M", "L"], it will test that "T" (the next of the array max value) is not allowed.

Options

  • :in - values to test inclusion.
  • :allow_nil - when supplied, validates if it allows nil or not.
  • :allow_blank - when supplied, validates if it allows blank or not.
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.inclusion’)

Examples

  should_validate_inclusion_of :size, :in => ["S", "M", "L", "XL"]
  should_validate_inclusion_of :age, :in => 18..100

  it { should validate_inclusion_of(:size, :in => ["S", "M", "L", "XL"]) }
  it { should validate_inclusion_of(:age, :in => 18..100) }

[Source]

    # File lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb, line 51
51:       def validate_inclusion_of(*args, &block)
52:         ValidateInclusionOfMatcher.new(*args, &block).spec(self)
53:       end

Validates the length of the given attributes. You have also to supply one of the following options: minimum, maximum, is or within.

Note: this method is also aliased as validate_size_of.

Options

  • :minimum - The minimum size of the attribute.
  • :maximum - The maximum size of the attribute.
  • :is - The exact size of the attribute.
  • :within - A range specifying the minimum and maximum size of the attribute.
  • :in - A synonym(or alias) for :within.
  • :allow_nil - when supplied, validates if it allows nil or not.
  • :allow_blank - when supplied, validates if it allows blank or not.
  • :too_short - value the test expects to find in errors.on(:attribute) when attribute is too short. Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.too_short’) % range.first
  • :too_long - value the test expects to find in errors.on(:attribute) when attribute is too long. Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.too_long’) % range.last
  • :wrong_length - value the test expects to find in errors.on(:attribute) when attribute is the wrong length. Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.wrong_length’) % range.last
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.wrong_length’) % value

It also accepts an extra option called :with_kind_of. If you are validating the size of an association array, you have to specify the kind of the array being validated. For example, if your post accepts maximum 10 comments, you can do:

  should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment

Finally, it also accepts :token and :separator, to specify how the tokenizer should work. For example, if you are splitting the attribute per word:

  validates_length_of :essay, :minimum => 100, :tokenizer => lambda {|str| str.scan(/\w+/) }

You could do this:

  should_validate_length_of :essay, :minimum => 100, :token => "word", :separator => " "

Gotcha

In Rails 2.3.x, when :message is supplied, it overwrites the messages supplied in :wrong_length, :too_short and :too_long. However, in earlier versions, Rails ignores the :message option.

Examples

  it { should validate_length_of(:password).within(6..20) }
  it { should validate_length_of(:password).maximum(20) }
  it { should validate_length_of(:password).minimum(6) }
  it { should validate_length_of(:age).is(18) }

  should_validate_length_of :password, :within => 6..20
  should_validate_length_of :password, :maximum => 20
  should_validate_length_of :password, :minimum => 6
  should_validate_length_of :age, :is => 18

  should_validate_length_of :password do |m|
    m.minimum 6
    m.maximum 20
  end

[Source]

     # File lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb, line 145
145:       def validate_length_of(*attributes, &block)
146:         ValidateLengthOfMatcher.new(*attributes, &block).spec(self)
147:       end

Ensures that the given attributes accepts only numbers.

Options

  • :only_integer - when supplied, checks if it accepts only integers or not
  • :odd - when supplied, checks if it accepts only odd values or not
  • :even - when supplied, checks if it accepts only even values or not
  • :equal_to - when supplied, checks if attributes are only valid when equal to given value
  • :less_than - when supplied, checks if attributes are only valid when less than given value
  • :greater_than - when supplied, checks if attributes are only valid when greater than given value
  • :less_than_or_equal_to - when supplied, checks if attributes are only valid when less than or equal to given value
  • :greater_than_or_equal_to - when supplied, checks if attributes are only valid when greater than or equal to given value
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.not_a_number’)

Examples

  it { should validate_numericality_of(:age).odd }
  it { should validate_numericality_of(:age).even }
  it { should validate_numericality_of(:age).only_integer }
  it { should validate_numericality_of(:age, :odd => true) }
  it { should validate_numericality_of(:age, :even => true) }

  should_validate_numericality_of :age, :price
  should_validate_numericality_of :price, :only_integer => false, :greater_than => 10

  should_validate_numericality_of :price do |m|
    m.only_integer = false
    m.greater_than = 10
  end

[Source]

     # File lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb, line 182
182:       def validate_numericality_of(*attributes, &block)
183:         ValidateNumericalityOfMatcher.new(*attributes, &block).spec(self)
184:       end

Ensures that the model cannot be saved if one of the attributes listed is not present.

Options

  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.blank’)

Examples

  should_validate_presence_of :name, :phone_number
  it { should validate_presence_of(:name, :phone_number) }

[Source]

    # File lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb, line 78
78:       def validate_presence_of(*args, &block)
79:         ValidatePresenceOfMatcher.new(*args, &block).spec(self)
80:       end

Ensures that the model cannot be saved if one of the attributes listed is not unique.

Requires an existing record in the database. If you supply :allow_nil as option, you need to have in the database a record which is not nil in the given attributes. The same is required for allow_blank option.

Notice that the record being validate should not be the same as in the database. In other words, you can‘t do this:

  subject { Post.create!(@valid_attributes) }
  should_validate_uniqueness_of :title

But don‘t worry, if you eventually do that, a helpful error message will be raised.

Options

  • :scope - field(s) to scope the uniqueness to.
  • :case_sensitive - the matcher look for an exact match.
  • :allow_nil - when supplied, validates if it allows nil or not.
  • :allow_blank - when supplied, validates if it allows blank or not.
  • :message - value the test expects to find in errors.on(:attribute). Regexp, string or symbol. Default = I18n.translate(‘activerecord.errors.messages.taken’)

Examples

  it { should validate_uniqueness_of(:keyword, :username) }
  it { should validate_uniqueness_of(:email, :scope => :name, :case_sensitive => false) }
  it { should validate_uniqueness_of(:address, :scope => [:first_name, :last_name]) }

  should_validate_uniqueness_of :keyword, :username
  should_validate_uniqueness_of :email, :scope => :name, :case_sensitive => false
  should_validate_uniqueness_of :address, :scope => [:first_name, :last_name]

  should_validate_uniqueness_of :email do |m|
    m.scope = name
    m.case_sensitive = false
  end

[Source]

     # File lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb, line 228
228:       def validate_uniqueness_of(*attributes, &block)
229:         ValidateUniquenessOfMatcher.new(*attributes, &block).spec(self)
230:       end

[Validate]