module Shoulda::Matchers::ActiveModel
Public Instance Methods
The `allow_mass_assignment_of` matcher tests usage of Rails 3's `attr_accessible` and `attr_protected` macros, asserting that an attribute in your model is contained in either the whitelist or blacklist and thus can or cannot be set via mass assignment.
class Post include ActiveModel::Model attr_accessible :title end class User include ActiveModel::Model attr_protected :encrypted_password end # RSpec describe Post do it { should allow_mass_assignment_of(:title) } end describe User do it { should_not allow_mass_assignment_of(:encrypted_password) } end # Test::Unit class PostTest < ActiveSupport::TestCase should allow_mass_assignment_of(:title) end class UserTest < ActiveSupport::TestCase should_not allow_mass_assignment_of(:encrypted_password) end
#### Qualifiers
##### as
Use `as` if your mass-assignment rules apply only under a certain role (Rails >= 3.1 only).
class Post include ActiveModel::Model attr_accessible :title, as: :admin end # RSpec describe Post do it { should allow_mass_assignment_of(:title).as(:admin) } end # Test::Unit class PostTest < ActiveSupport::TestCase should allow_mass_assignment_of(:title).as(:admin) end
@return [AllowMassAssignmentOfMatcher]
# File lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb, line 64 def allow_mass_assignment_of(value) AllowMassAssignmentOfMatcher.new(value) end
The `allow_value` matcher is used to test that an attribute of a model can or cannot be set to a particular value or values. It is most commonly used in conjunction with the `validates_format_of` validation.
#### should
In the positive form, `allow_value` asserts that an attribute can be set to one or more values, succeeding if none of the values cause the record to be invalid:
class UserProfile include ActiveModel::Model validates_format_of :website_url, with: URI.regexp end # RSpec describe UserProfile do it { should allow_value('http://foo.com', 'http://bar.com/baz').for(:website_url) } end # Test::Unit class UserProfileTest < ActiveSupport::TestCase should allow_value('http://foo.com', 'http://bar.com/baz').for(:website_url) end
#### should_not
In the negative form, `allow_value` asserts that an attribute cannot be set to one or more values, succeeding if the first value causes the record to be invalid.
**This can be surprising** so in this case if you need to check that all of the values are invalid, use separate assertions:
class UserProfile include ActiveModel::Model validates_format_of :website_url, with: URI.regexp end describe UserProfile do # One assertion: 'buz' and 'bar' will not be tested it { should_not allow_value('fiz', 'buz', 'bar').for(:website_url) } # Three assertions, all tested separately it { should_not allow_value('fiz').for(:website_url) } it { should_not allow_value('buz').for(:website_url) } it { should_not allow_value('bar').for(:website_url) } end
#### Qualifiers
##### on
Use `on` if your validation applies only under a certain context.
class UserProfile include ActiveModel::Model validates_format_of :birthday_as_string, with: /^(\d+)-(\d+)-(\d+)$/, on: :create end # RSpec describe UserProfile do it do should allow_value('2013-01-01'). for(:birthday_as_string). on(:create) end end # Test::Unit class UserProfileTest < ActiveSupport::TestCase should allow_value('2013-01-01'). for(:birthday_as_string). on(:create) end
##### with_message
Use `with_message` if you are using a custom validation message.
class UserProfile include ActiveModel::Model validates_format_of :state, with: /^(open|closed)$/, message: 'State must be open or closed' end # RSpec describe UserProfile do it do should allow_value('open', 'closed'). for(:state). with_message('State must be open or closed') end end # Test::Unit class UserProfileTest < ActiveSupport::TestCase should allow_value('open', 'closed'). for(:state). with_message('State must be open or closed') end
Use `with_message` with the `:against` option if the attribute the validation message is stored under is different from the attribute being validated.
class UserProfile include ActiveModel::Model validate :sports_team_must_be_valid private def sports_team_must_be_valid if sports_team !~ /^(Broncos|Titans)$/i self.errors.add :chosen_sports_team, 'Must be either a Broncos fan or a Titans fan' end end end # RSpec describe UserProfile do it do should allow_value('Broncos', 'Titans'). for(:sports_team). with_message('Must be either a Broncos or Titans fan', against: :chosen_sports_team ) end end # Test::Unit class UserProfileTest < ActiveSupport::TestCase should allow_value('Broncos', 'Titans'). for(:sports_team). with_message('Must be either a Broncos or Titans fan', against: :chosen_sports_team ) end
@return [AllowValueMatcher]
# File lib/shoulda/matchers/active_model/allow_value_matcher.rb, line 153 def allow_value(*values) if values.empty? raise ArgumentError, 'need at least one argument' else AllowValueMatcher.new(*values) end end
The `ensure_exclusion_of` matcher tests usage of the `validates_exclusion_of` validation, asserting that an attribute cannot take a blacklist of values, and inversely, can take values outside of this list.
#### Qualifiers
`in_array` or `in_range` are used to test usage of the `:in` option, and so one must be used.
##### in_array
Use `in_array` if your blacklist is an array of values.
class Game include ActiveModel::Model validates_exclusion_of :supported_os, in: ['Mac', 'Linux'] end # RSpec describe Game do it { should ensure_exclusion_of(:supported_os).in_array(['Mac', 'Linux']) } end # Test::Unit class GameTest < ActiveSupport::TestCase should ensure_exclusion_of(:supported_os).in_array(['Mac', 'Linux']) end
##### in_range
Use `in_range` if your blacklist is a range of values.
class Game include ActiveModel::Model validates_exclusion_of :supported_os, in: ['Mac', 'Linux'] end # RSpec describe Game do it { should ensure_exclusion_of(:floors_with_enemies).in_range(5..8) } end # Test::Unit class GameTest < ActiveSupport::TestCase should ensure_exclusion_of(:floors_with_enemies).in_range(5..8) end
##### with_message
Use `with_message` if you are using a custom validation message.
class Game validates_exclusion_of :weapon, in: ['pistol', 'paintball gun', 'stick'], message: 'You chose a puny weapon' end # RSpec describe Game do it do should ensure_exclusion_of(:weapon). in_array(['pistol', 'paintball gun', 'stick']). with_message('You chose a puny weapon') end end # Test::Unit class GameTest < ActiveSupport::TestCase should ensure_exclusion_of(:weapon). in_array(['pistol', 'paintball gun', 'stick']). with_message('You chose a puny weapon') end
@return [EnsureExclusionOfMatcher]
# File lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb, line 82 def ensure_exclusion_of(attr) EnsureExclusionOfMatcher.new(attr) end
The `ensure_inclusion_of` matcher tests usage of the `validates_inclusion_of` validation, asserting that an attribute can take a whitelist of values and cannot take values outside of this list.
#### Qualifiers
`in_array` or `in_range` are used to test usage of the `:in` option, and so one must be used.
##### in_array
Use `in_array` if your whitelist is an array of values.
class Issue include ActiveModel::Model validates_inclusion_of :state, in: %w(open resolved unresolved) end # RSpec describe Issue do it { should ensure_inclusion_of(:state).in_array(%w(open resolved unresolved)) } end # Test::Unit class IssueTest < ActiveSupport::TestCase should ensure_inclusion_of(:state).in_array(%w(open resolved unresolved)) end
##### in_range
Use `in_range` if your whitelist is a range of values.
class Issue include ActiveModel::Model validates_inclusion_of :priority, in: 1..5 end # RSpec describe Issue do it { should ensure_inclusion_of(:state).in_range(1..5) } end # Test::Unit class IssueTest < ActiveSupport::TestCase should ensure_inclusion_of(:state).in_range(1..5) end
##### with_message
Use `with_message` if you are using a custom validation message.
class Issue include ActiveModel::Model validates_inclusion_of :severity, in: %w(low medium high), message: 'Severity must be low, medium, or high' end # RSpec describe Issue do it do should ensure_inclusion_of(:severity). in_array(%w(low medium high)). with_message('Severity must be low, medium, or high') end end # Test::Unit class IssueTest < ActiveSupport::TestCase should ensure_inclusion_of(:severity). in_array(%w(low medium high)). with_message('Severity must be low, medium, or high') end
##### with_low_message
Use `with_low_message` if you have a custom validation message for when a given value is too low.
class Person include ActiveModel::Model validate :age_must_be_valid private def age_must_be_valid if age < 65 self.errors.add :age, 'You do not receive any benefits' end end end # RSpec describe Person do it do should ensure_inclusion_of(:age). in_range(0..65). with_low_message('You do not receive any benefits') end end # Test::Unit class PersonTest < ActiveSupport::TestCase should ensure_inclusion_of(:age). in_range(0..65). with_low_message('You do not receive any benefits') end
##### with_high_message
Use `with_high_message` if you have a custom validation message for when a given value is too high.
class Person include ActiveModel::Model validate :age_must_be_valid private def age_must_be_valid if age > 21 self.errors.add :age, "You're too old for this stuff" end end end # RSpec describe Person do it do should ensure_inclusion_of(:age). in_range(0..21). with_high_message("You're too old for this stuff") end end # Test::Unit class PersonTest < ActiveSupport::TestCase should ensure_inclusion_of(:age). in_range(0..21). with_high_message("You're too old for this stuff") end
##### allow_nil
Use `allow_nil` to assert that the attribute allows nil.
class Issue include ActiveModel::Model validates_presence_of :state validates_inclusion_of :state, in: %w(open resolved unresolved), allow_nil: true end # RSpec describe Issue do it do should ensure_inclusion_of(:state). in_array(%w(open resolved unresolved)). allow_nil end end # Test::Unit class IssueTest < ActiveSupport::TestCase should ensure_inclusion_of(:state). in_array(%w(open resolved unresolved)). allow_nil end
##### allow_blank
Use `allow_blank` to assert that the attribute allows blank.
class Issue include ActiveModel::Model validates_presence_of :state validates_inclusion_of :state, in: %w(open resolved unresolved), allow_blank: true end # RSpec describe Issue do it do should ensure_inclusion_of(:state). in_array(%w(open resolved unresolved)). allow_blank end end # Test::Unit class IssueTest < ActiveSupport::TestCase should ensure_inclusion_of(:state). in_array(%w(open resolved unresolved)). allow_blank end
@return [EnsureInclusionOfMatcher]
# File lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb, line 211 def ensure_inclusion_of(attr) EnsureInclusionOfMatcher.new(attr) end
The `ensure_length_of` matcher tests usage of the `validates_length_of` matcher. Note that this matcher is intended to be used against string columns and not integer columns.
#### Qualifiers
One of `is_equal_to`, `is_at_least`, or `is_at_most` must be used.
##### is_at_least
Use `is_at_least` to test usage of the `:minimum` option. This asserts that the attribute can take a string which is equal to or longer than the given length and cannot take a string which is shorter.
class User include ActiveModel::Model validates_length_of :bio, minimum: 15 end # RSpec describe User do it { should ensure_length_of(:bio).is_at_least(15) } end # Test::Unit class UserTest < ActiveSupport::TestCase should ensure_length_of(:bio).is_at_least(15) end
##### is_at_most
Use `is_at_most` to test usage of the `:maximum` option. This asserts that the attribute can take a string which is equal to or shorter than the given length and cannot take a string which is longer.
class User include ActiveModel::Model validates_length_of :status_update, maximum: 140 end # RSpec describe User do it { should ensure_length_of(:status_update).is_at_most(140) } end # Test::Unit class UserTest < ActiveSupport::TestCase should ensure_length_of(:status_update).is_at_most(140) end
##### is_equal_to
Use `is_at_equal` to test usage of the `:is` option. This asserts that the attribute can take a string which is exactly equal to the given length and cannot take a string which is shorter or longer.
class User include ActiveModel::Model validates_length_of :favorite_superhero, is: 6 end # RSpec describe User do it { should ensure_length_of(:favorite_superhero).is_equal_to(6) } end # Test::Unit class UserTest < ActiveSupport::TestCase should ensure_length_of(:favorite_superhero).is_equal_to(6) end
##### is_at_least + is_at_most
Use `is_at_least` and `is_at_most` to test usage of the `:in` option.
class User include ActiveModel::Model validates_length_of :password, in: 5..30 end # RSpec describe User do it { should ensure_length_of(:password).is_at_least(5).is_at_most(30) } end # Test::Unit class UserTest < ActiveSupport::TestCase should ensure_length_of(:password).is_at_least(5).is_at_most(30) end
##### with_message
Use `with_message` if you are using a custom validation message.
class User include ActiveModel::Model validates_length_of :api_token, minimum: 10, message: "Password isn't long enough" end # RSpec describe User do it do should ensure_length_of(:password). is_at_least(10). with_message("Password isn't long enough") end end # Test::Unit class UserTest < ActiveSupport::TestCase should ensure_length_of(:password). is_at_least(10). with_message("Password isn't long enough") end
##### with_short_message
Use `with_short_message` if you are using a custom “too short” message.
class User include ActiveModel::Model validates_length_of :secret_key, in: 15..100, too_short: 'Secret key must be more than 15 characters' end # RSpec describe User do it do should ensure_length_of(:secret_key). is_at_least(15). with_short_message('Secret key must be more than 15 characters') end end # Test::Unit class UserTest < ActiveSupport::TestCase should ensure_length_of(:secret_key). is_at_least(15). with_short_message('Secret key must be more than 15 characters') end
##### with_long_message
Use `with_long_message` if you are using a custom “too long” message.
class User include ActiveModel::Model validates_length_of :secret_key, in: 15..100, too_long: 'Secret key must be less than 100 characters' end # RSpec describe User do it do should ensure_length_of(:secret_key). is_at_most(100). with_long_message('Secret key must be less than 100 characters') end end # Test::Unit class UserTest < ActiveSupport::TestCase should ensure_length_of(:secret_key). is_at_most(100). with_long_message('Secret key must be less than 100 characters') end
@return [EnsureLengthOfMatcher]
# File lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb, line 186 def ensure_length_of(attr) EnsureLengthOfMatcher.new(attr) end
The `have_secure_password` matcher tests usage of the `has_secure_password` macro.
#### Example
class User include ActiveModel::Model has_secure_password end # RSpec describe User do it { should have_secure_password } end # Test::Unit class UserTest < ActiveSupport::TestCase should have_secure_password end
@return [HaveSecurePasswordMatcher]
# File lib/shoulda/matchers/active_model/have_secure_password_matcher.rb, line 27 def have_secure_password HaveSecurePasswordMatcher.new end
The `validate_absence_of` matcher tests the usage of the `validates_absence_of` validation.
class Artillery include ActiveModel::Model validates_absence_of :arms end # RSpec describe Artillery do it { should validate_absence_of(:arms) } end # Test::Unit class ArtilleryTest < ActiveSupport::TestCase should validate_absence_of(:arms) end
#### Qualifiers
##### with_message
Use `with_message` if you are using a custom validation message.
class Artillery include ActiveModel::Model validates_absence_of :arms, message: "We're fresh outta arms here, soldier!" end # RSpec describe Artillery do it do should validate_absence_of(:arms). with_message("We're fresh outta arms here, soldier!") end end # Test::Unit class ArtilleryTest < ActiveSupport::TestCase should validate_absence_of(:arms). with_message("We're fresh outta arms here, soldier!") end
@return [ValidateAbsenceOfMatcher}
# File lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb, line 51 def validate_absence_of(attr) ValidateAbsenceOfMatcher.new(attr) end
The `validate_acceptance_of` matcher tests usage of the `validates_acceptance_of` validation.
class Registration include ActiveModel::Model validates_acceptance_of :eula end # RSpec describe Registration do it { should validate_acceptance_of(:eula) } end # Test::Unit class RegistrationTest < ActiveSupport::TestCase should validate_acceptance_of(:eula) end
#### Qualifiers
##### with_message
Use `with_message` if you are using a custom validation message.
class Registration include ActiveModel::Model validates_acceptance_of :terms_of_service, message: 'You must accept the terms of service' end # RSpec describe Registration do it do should validate_acceptance_of(:terms_of_service). with_message('You must accept the terms of service') end end # Test::Unit class RegistrationTest < ActiveSupport::TestCase should validate_acceptance_of(:terms_of_service). with_message('You must accept the terms of service') end
@return [ValidateAcceptanceOfMatcher]
# File lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb, line 52 def validate_acceptance_of(attr) ValidateAcceptanceOfMatcher.new(attr) end
The `validate_confirmation_of` matcher tests usage of the `validates_confirmation_of` validation.
class User include ActiveModel::Model validates_confirmation_of :email end # RSpec describe User do it { should validate_confirmation_of(:email) } end # Test::Unit class UserTest < ActiveSupport::TestCase should validate_confirmation_of(:email) end
#### Qualifiers
##### with_message
Use `with_message` if you are using a custom validation message.
class User include ActiveModel::Model validates_confirmation_of :password, message: 'Please re-enter your password' end # RSpec describe User do it do should validate_confirmation_of(:password). with_message('Please re-enter your password') end end # Test::Unit class UserTest < ActiveSupport::TestCase should validate_confirmation_of(:password). with_message('Please re-enter your password') end
@return [ValidateConfirmationOfMatcher]
# File lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb, line 52 def validate_confirmation_of(attr) ValidateConfirmationOfMatcher.new(attr) end
The `validate_numericality_of` matcher tests usage of the `validates_numericality_of` validation.
class Person < ActiveRecord::Base validates_numericality_of :gpa end # RSpec describe Person do it { should validate_numericality_of(:gpa) } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:gpa) end
#### Qualifiers
##### only_integer
Use `only_integer` to test usage of the `:only_integer` option. This asserts that your attribute only allows integer numbers and disallows non-integer ones.
class Person include ActiveModel::Model validates_numericality_of :age, only_integer: true end # RSpec describe Person do it { should validate_numericality_of(:age).only_integer } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:age).only_integer end
##### is_less_than
Use `is_less_than` to test usage of the the `:less_than` option. This asserts that the attribute can take a number which is less than the given value and cannot take a number which is greater than or equal to it.
class Person include ActiveModel::Model validates_numericality_of :number_of_cars, less_than: 2 end # RSpec describe Person do it { should validate_numericality_of(:number_of_cars).is_less_than(2) } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:number_of_cars).is_less_than(2) end
##### is_less_than_or_equal_to
Use `is_less_than_or_equal_to` to test usage of the `:less_than_or_equal_to` option. This asserts that the attribute can take a number which is less than or equal to the given value and cannot take a number which is greater than it.
class Person include ActiveModel::Model validates_numericality_of :birth_year, less_than_or_equal_to: 1987 end # RSpec describe Person do it { should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987) } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987) end
##### is_equal_to
Use `is_equal_to` to test usage of the `:equal_to` option. This asserts that the attribute can take a number which is equal to the given value and cannot take a number which is not equal.
class Person include ActiveModel::Model validates_numericality_of :weight, equal_to: 150 end # RSpec describe Person do it { should validate_numericality_of(:weight).is_equal_to(150) } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:weight).is_equal_to(150) end
##### is_greater_than_or_equal_to
Use `is_greater_than_or_equal_to` to test usage of the `:greater_than_or_equal_to` option. This asserts that the attribute can take a number which is greater than or equal to the given value and cannot take a number which is less than it.
class Person include ActiveModel::Model validates_numericality_of :height, greater_than_or_equal_to: 55 end # RSpec describe Person do it { should validate_numericality_of(:height).is_greater_than_or_equal_to(55) } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:height).is_greater_than_or_equal_to(55) end
##### is_greater_than
Use `is_greater_than` to test usage of tthe `:greater_than` option. This asserts that the attribute can take a number which is greater than the given value and cannot take a number less than or equal to it.
class Person include ActiveModel::Model validates_numericality_of :legal_age, greater_than: 21 end # RSpec describe Person do it { should validate_numericality_of(:legal_age).is_greater_than(21) } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:legal_age).is_greater_than(21) end
##### even
Use `even` to test usage of the `:even` option. This asserts that the attribute can take odd numbers and cannot take even ones.
class Person include ActiveModel::Model validates_numericality_of :birth_month, even: true end # RSpec describe Person do it { should validate_numericality_of(:birth_month).even } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:birth_month).even end
##### odd
Use `odd` to test usage of the `:odd` option. This asserts that the attribute can take a number which is odd and cannot take a number which is even.
class Person include ActiveModel::Model validates_numericality_of :birth_day, odd: true end # RSpec describe Person do it { should validate_numericality_of(:birth_day).odd } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:birth_day).odd end
##### allow_nil
Use `allow_nil` to assert that the attribute allows nil.
class Person include ActiveModel::Model validate_numericality_of :rank, allow_nil: true end # RSpec describe Person do it { should validate_numericality_of(:rank).allow_nil } end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_uniqueness_of(:rank).allow_nil end
##### with_message
Use `with_message` if you are using a custom validation message.
class Person include ActiveModel::Model validates_numericality_of :number_of_dependents, message: 'Number of dependents must be a number' end # RSpec describe Person do it do should validate_numericality_of(:number_of_dependents). with_message('Number of dependents must be a number') end end # Test::Unit class PersonTest < ActiveSupport::TestCase should validate_numericality_of(:number_of_dependents). with_message('Number of dependents must be a number') end
@return [ValidateNumericalityOfMatcher]
# File lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb, line 248 def validate_numericality_of(attr) ValidateNumericalityOfMatcher.new(attr) end
The `validate_presence_of` matcher tests usage of the `validates_presence_of` validation.
class Robot < ActiveRecord::Base validates_presence_of :arms end # RSpec describe Robot do it { should validate_presence_of(:arms) } end # Test::Unit class RobotTest < ActiveSupport::TestCase should validate_presence_of(:arms) end
#### Qualifiers
##### with_message
Use `with_message` if you are using a custom validation message.
class Robot < ActiveRecord::Base validates_presence_of :legs, message: 'Robot has no legs' end # RSpec describe Robot do it { should validate_presence_of(:legs).with_message('Robot has no legs') } end # Test::Unit class RobotTest < ActiveSupport::TestCase should validate_presence_of(:legs).with_message('Robot has no legs') end
@return [ValidatePresenceOfMatcher]
# File lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb, line 43 def validate_presence_of(attr) ValidatePresenceOfMatcher.new(attr) end
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 record 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 **create a record manually** 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 (?)
To fix this, you'll need to write this instead:
describe Post do it do Post.create!(content: 'Here is the content') should validate_uniqueness_of(:title) end end
Or, if you're using [FactoryGirl](github.com/thoughtbot/factory_girl) and you have a `post` factory defined which automatically sets `content`, you can say:
describe Post do it do FactoryGirl.create(:post) 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
@return [ValidateUniquenessOfMatcher]
# File lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb, line 170 def validate_uniqueness_of(attr) ValidateUniquenessOfMatcher.new(attr) end