Module Shoulda::ActiveRecord::Macros
In: lib/shoulda/active_record/macros.rb
ValidationMatcher ValidatePresenceOfMatcher ValidateAcceptanceOfMatcher EnsureLengthOfMatcher ValidateFormatOfMatcher EnsureInclusionOfMatcher ValidateUniquenessOfMatcher ValidateNumericalityOfMatcher Context SetSessionMatcher RespondWithContentTypeMatcher SetTheFlashMatcher RenderWithLayout RespondWithMatcher AssignToMatcher FilterParamMatcher RouteMatcher HaveNamedScopeMatcher HaveDbIndexMatcher HaveDbColumnMatcher AllowMassAssignmentOfMatcher AllowValueMatcher AssociationMatcher HaveReadonlyAttributeMatcher lib/shoulda/context.rb lib/shoulda/action_controller/matchers/set_session_matcher.rb lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb lib/shoulda/action_controller/matchers/respond_with_matcher.rb lib/shoulda/action_controller/matchers/assign_to_matcher.rb lib/shoulda/action_controller/matchers/filter_param_matcher.rb lib/shoulda/action_controller/matchers/route_matcher.rb Matchers Macros ActionController lib/shoulda/active_record/matchers/validation_matcher.rb lib/shoulda/active_record/matchers/have_named_scope_matcher.rb lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb lib/shoulda/active_record/matchers/have_db_index_matcher.rb lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb lib/shoulda/active_record/matchers/validate_format_of_matcher.rb lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb lib/shoulda/active_record/matchers/have_db_column_matcher.rb lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb lib/shoulda/active_record/matchers/allow_value_matcher.rb lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb lib/shoulda/active_record/matchers/association_matcher.rb lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb Matchers Helpers Assertions Macros ActiveRecord ClassMethods Macros ActionView Private Helpers Assertions ActionMailer InstanceMethods Assertions Macros Shoulda dot/m_47_0.png

Macro test helpers for your active record models

These helpers will test most of the validations and associations for your ActiveRecord models.

  class UserTest < Test::Unit::TestCase
    should_validate_presence_of :name, :phone_number
    should_not_allow_values_for :phone_number, "abcd", "1234"
    should_allow_values_for :phone_number, "(123) 456-7890"

    should_not_allow_mass_assignment_of :password

    should_have_one :profile
    should_have_many :dogs
    should_have_many :messes, :through => :dogs
    should_belong_to :lover
  end

For all of these helpers, the last parameter may be a hash of options.

Methods

Included Modules

Helpers Matchers

Public Instance methods

Ensures that the attribute can be set on mass update.

  should_allow_mass_assignment_of :first_name, :last_name

[Source]

    # File lib/shoulda/active_record/macros.rb, line 83
83:       def should_allow_mass_assignment_of(*attributes)
84:         get_options!(attributes)
85: 
86:         attributes.each do |attribute|
87:           matcher = allow_mass_assignment_of(attribute)
88:           should matcher.description do
89:             assert_accepts matcher, subject
90:           end
91:         end
92:       end

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

Example:

  should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"

[Source]

     # File lib/shoulda/active_record/macros.rb, line 149
149:       def should_allow_values_for(attribute, *good_values)
150:         get_options!(good_values)
151:         good_values.each do |value|
152:           matcher = allow_value(value).for(attribute)
153:           should matcher.description do
154:             assert_accepts matcher, subject
155:           end
156:         end
157:       end

Ensure that the belongs_to relationship exists.

  should_belong_to :parent

[Source]

     # File lib/shoulda/active_record/macros.rb, line 335
335:       def should_belong_to(*associations)
336:         dependent = get_options!(associations, :dependent)
337:         associations.each do |association|
338:           matcher = belong_to(association).dependent(dependent)
339:           should matcher.description do
340:             assert_accepts(matcher, subject)
341:           end
342:         end
343:       end

Ensures that the length of the attribute is at least a certain length

Options:

  • :short_message - value the test expects to find in errors.on(:attribute). Regexp or string. Default = I18n.translate(‘activerecord.errors.messages.too_short’) % min_length

Example:

  should_ensure_length_at_least :name, 3

[Source]

     # File lib/shoulda/active_record/macros.rb, line 194
194:       def should_ensure_length_at_least(attribute, min_length, opts = {})
195:         short_message = get_options!([opts], :short_message)
196: 
197:         matcher = ensure_length_of(attribute).
198:           is_at_least(min_length).
199:           with_short_message(short_message)
200: 
201:         should matcher.description do
202:           assert_accepts matcher, subject
203:         end
204:       end

Ensures that the length of the attribute is in the given range

Options:

  • :short_message - value the test expects to find in errors.on(:attribute). Regexp or string. Default = I18n.translate(‘activerecord.errors.messages.too_short’) % range.first
  • :long_message - value the test expects to find in errors.on(:attribute). Regexp or string. Default = I18n.translate(‘activerecord.errors.messages.too_long’) % range.last

Example:

  should_ensure_length_in_range :password, (6..20)

[Source]

     # File lib/shoulda/active_record/macros.rb, line 170
170:       def should_ensure_length_in_range(attribute, range, opts = {})
171:         short_message, long_message = get_options!([opts], 
172:                                                    :short_message,
173:                                                    :long_message)
174:         matcher = ensure_length_of(attribute).
175:           is_at_least(range.first).
176:           with_short_message(short_message).
177:           is_at_most(range.last).
178:           with_long_message(long_message)
179: 
180:         should matcher.description do
181:           assert_accepts matcher, subject
182:         end
183:       end

Ensures that the length of the attribute is exactly a certain length

Options:

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

Example:

  should_ensure_length_is :ssn, 9

[Source]

     # File lib/shoulda/active_record/macros.rb, line 215
215:       def should_ensure_length_is(attribute, length, opts = {})
216:         message = get_options!([opts], :message)
217:         matcher = ensure_length_of(attribute).
218:           is_equal_to(length).
219:           with_message(message)
220: 
221:         should matcher.description do
222:           assert_accepts matcher, subject
223:         end
224:       end

Ensure that the attribute is in the range specified

Options:

  • :low_message - value the test expects to find in errors.on(:attribute). Regexp or string. Default = I18n.translate(‘activerecord.errors.messages.inclusion’)
  • :high_message - value the test expects to find in errors.on(:attribute). Regexp or string. Default = I18n.translate(‘activerecord.errors.messages.inclusion’)

Example:

  should_ensure_value_in_range :age, (0..100)

[Source]

     # File lib/shoulda/active_record/macros.rb, line 237
237:       def should_ensure_value_in_range(attribute, range, opts = {})
238:         message, low_message, high_message = get_options!([opts],
239:                                                           :message,
240:                                                           :low_message,
241:                                                           :high_message)
242:         matcher = ensure_inclusion_of(attribute).
243:           in_range(range).
244:           with_message(message).
245:           with_low_message(low_message).
246:           with_high_message(high_message)
247:         should matcher.description do
248:           assert_accepts matcher, subject
249:         end
250:       end

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

  should_have_and_belong_to_many :posts, :cars

[Source]

     # File lib/shoulda/active_record/macros.rb, line 320
320:       def should_have_and_belong_to_many(*associations)
321:         get_options!(associations)
322: 
323:         associations.each do |association|
324:           matcher = have_and_belong_to_many(association)
325:           should matcher.description do
326:             assert_accepts(matcher, subject)
327:           end
328:         end
329:       end

Ensure that the given class methods are defined on the model.

  should_have_class_methods :find, :destroy

[Source]

     # File lib/shoulda/active_record/macros.rb, line 349
349:       def should_have_class_methods(*methods)
350:         get_options!(methods)
351:         klass = described_type
352:         methods.each do |method|
353:           should "respond to class method ##{method}" do
354:             assert_respond_to klass, method, "#{klass.name} does not have class method #{method}"
355:           end
356:         end
357:       end
should_have_db_column(*columns)

Ensure that the given columns are defined on the models backing SQL table. Also aliased to should_have_db_column for readability. Takes the same options available in migrations: :type, :precision, :limit, :default, :null, and :scale

Examples:

  should_have_db_columns :id, :email, :name, :created_at

  should_have_db_column :email,  :type => "string", :limit => 255
  should_have_db_column :salary, :decimal, :precision => 15, :scale => 2
  should_have_db_column :admin,  :default => false, :null => false

[Source]

     # File lib/shoulda/active_record/macros.rb, line 386
386:       def should_have_db_columns(*columns)
387:         column_type, precision, limit, default, null, scale, sql_type = 
388:           get_options!(columns, :type, :precision, :limit,
389:                                 :default, :null, :scale, :sql_type)
390:         columns.each do |name|
391:           matcher = have_db_column(name).
392:                       of_type(column_type).
393:                       with_options(:precision => precision, :limit    => limit,
394:                                    :default   => default,   :null     => null,
395:                                    :scale     => scale,     :sql_type => sql_type)
396:           should matcher.description do
397:             assert_accepts(matcher, subject)
398:           end
399:         end
400:       end
should_have_db_index(*columns)

Ensures that there are DB indices on the given columns or tuples of columns. Also aliased to should_have_db_index for readability

Options:

  • :unique - whether or not the index has a unique constraint. Use true to explicitly test for a unique constraint. Use false to explicitly test for a non-unique constraint. Use nil if you don‘t care whether the index is unique or not. Default = nil

Examples:

  should_have_db_indices :email, :name, [:commentable_type, :commentable_id]
  should_have_db_index :age
  should_have_db_index :ssn, :unique => true

[Source]

     # File lib/shoulda/active_record/macros.rb, line 420
420:       def should_have_db_indices(*columns)
421:         unique = get_options!(columns, :unique)
422:         
423:         columns.each do |column|
424:           matcher = have_db_index(column).unique(unique)
425:           should matcher.description do
426:             assert_accepts(matcher, subject)
427:           end
428:         end
429:       end

Deprecated. See should_have_db_index

[Source]

     # File lib/shoulda/active_record/macros.rb, line 434
434:       def should_have_index(*args)
435:         warn "[DEPRECATION] should_have_index is deprecated. " <<
436:              "Use should_have_db_index instead."
437:         should_have_db_index(*args)
438:       end

Deprecated. See should_have_db_indices

[Source]

     # File lib/shoulda/active_record/macros.rb, line 441
441:       def should_have_indices(*args)
442:         warn "[DEPRECATION] should_have_indices is deprecated. " <<
443:              "Use should_have_db_indices instead."
444:         should_have_db_indices(*args)
445:       end

Ensure that the given instance methods are defined on the model.

  should_have_instance_methods :email, :name, :name=

[Source]

     # File lib/shoulda/active_record/macros.rb, line 363
363:       def should_have_instance_methods(*methods)
364:         get_options!(methods)
365:         klass = described_type
366:         methods.each do |method|
367:           should "respond to instance method ##{method}" do
368:             assert_respond_to klass.new, method, "#{klass.name} does not have instance method #{method}"
369:           end
370:         end
371:       end

Ensures that the has_many relationship exists. Will also test that the associated table has the required columns. Works with polymorphic associations.

Options:

  • :through - association name for has_many :through
  • :dependent - tests that the association makes use of the dependent option.

Example:

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

[Source]

     # File lib/shoulda/active_record/macros.rb, line 285
285:       def should_have_many(*associations)
286:         through, dependent = get_options!(associations, :through, :dependent)
287:         associations.each do |association|
288:           matcher = have_many(association).through(through).dependent(dependent)
289:           should matcher.description do
290:             assert_accepts(matcher, subject)
291:           end
292:         end
293:       end

Deprecated.

Ensures that the model has a method named scope_name that returns a NamedScope object with the proxy options set to the options you supply. scope_name can be either a symbol, or a method call which will be evaled against the model. The eval‘d method call has access to all the same instance variables that a should statement would.

Options: Any of the options that the named scope would pass on to find.

Example:

  should_have_named_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:

  should_have_named_scope 'recent(5)', :limit => 5
  should_have_named_scope 'recent(1)', :limit => 1

Passes for

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

Or for

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

[Source]

     # File lib/shoulda/active_record/macros.rb, line 504
504:       def should_have_named_scope(scope_call, find_options = nil)
505:         matcher = have_named_scope(scope_call).finding(find_options)
506:         should matcher.description do
507:           assert_accepts matcher.in_context(self), subject
508:         end
509:       end

Ensure that the has_one relationship exists. Will also test that the associated table has the required columns. Works with polymorphic associations.

Options:

  • :dependent - tests that the association makes use of the dependent option.

Example:

  should_have_one :god # unless hindu

[Source]

     # File lib/shoulda/active_record/macros.rb, line 305
305:       def should_have_one(*associations)
306:         dependent, through = get_options!(associations, :dependent, :through)
307:         associations.each do |association|
308:           matcher = have_one(association).dependent(dependent).through(through)
309:           should matcher.description do
310:             assert_accepts(matcher, subject)
311:           end
312:         end
313:       end

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

  should_have_readonly_attributes :password, :admin_flag

[Source]

     # File lib/shoulda/active_record/macros.rb, line 113
113:       def should_have_readonly_attributes(*attributes)
114:         get_options!(attributes)
115: 
116:         attributes.each do |attribute|
117:           matcher = have_readonly_attribute(attribute)
118:           should matcher.description do
119:             assert_accepts matcher, subject
120:           end
121:         end
122:       end

Ensures that the attribute cannot be set on mass update.

  should_not_allow_mass_assignment_of :password, :admin_flag

[Source]

     # File lib/shoulda/active_record/macros.rb, line 98
 98:       def should_not_allow_mass_assignment_of(*attributes)
 99:         get_options!(attributes)
100: 
101:         attributes.each do |attribute|
102:           matcher = allow_mass_assignment_of(attribute)
103:           should "not #{matcher.description}" do
104:             assert_rejects matcher, subject
105:           end
106:         end
107:       end

Ensures that the attribute cannot be set to the given values

Options:

  • :message - value the test expects to find in errors.on(:attribute). Regexp or string. If omitted, the test will pass if there is ANY error in errors.on(:attribute).

Example:

  should_not_allow_values_for :isbn, "bad 1", "bad 2"

[Source]

     # File lib/shoulda/active_record/macros.rb, line 134
134:       def should_not_allow_values_for(attribute, *bad_values)
135:         message = get_options!(bad_values, :message)
136:         bad_values.each do |value|
137:           matcher = allow_value(value).for(attribute).with_message(message)
138:           should "not #{matcher.description}" do
139:             assert_rejects matcher, subject
140:           end
141:         end
142:       end

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

Options:

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

Example:

  should_validate_acceptance_of :eula

[Source]

     # File lib/shoulda/active_record/macros.rb, line 456
456:       def should_validate_acceptance_of(*attributes)
457:         message = get_options!(attributes, :message)
458: 
459:         attributes.each do |attribute|
460:           matcher = validate_acceptance_of(attribute).with_message(message)
461:           should matcher.description do
462:             assert_accepts matcher, subject
463:           end
464:         end
465:       end

Ensure that the attribute is numeric

Options:

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

Example:

  should_validate_numericality_of :age

[Source]

     # File lib/shoulda/active_record/macros.rb, line 261
261:       def should_validate_numericality_of(*attributes)
262:         message = get_options!(attributes, :message)
263:         attributes.each do |attribute|
264:           matcher = validate_numericality_of(attribute).
265:             with_message(message)
266:           should matcher.description do
267:             assert_accepts matcher, subject
268:           end
269:         end
270:       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 or string. Default = I18n.translate(‘activerecord.errors.messages.blank’)

Example:

  should_validate_presence_of :name, :phone_number

[Source]

    # File lib/shoulda/active_record/macros.rb, line 35
35:       def should_validate_presence_of(*attributes)
36:         message = get_options!(attributes, :message)
37: 
38:         attributes.each do |attribute|
39:           matcher = validate_presence_of(attribute).with_message(message)
40:           should matcher.description do
41:             assert_accepts(matcher, subject)
42:           end
43:         end
44:       end
  • :message - value the test expects to find in errors.on(:attribute). Regexp or string. Default = I18n.translate(‘activerecord.errors.messages.taken’)
  • :scoped_to - field(s) to scope the uniqueness to.
  • :case_sensitive - whether or not uniqueness is defined by an exact match. Ignored by non-text attributes. Default = true

Examples:

  should_validate_uniqueness_of :keyword, :username
  should_validate_uniqueness_of :name, :message => "O NOES! SOMEONE STOELED YER NAME!"
  should_validate_uniqueness_of :email, :scoped_to => :name
  should_validate_uniqueness_of :address, :scoped_to => [:first_name, :last_name]
  should_validate_uniqueness_of :email, :case_sensitive => false

[Source]

    # File lib/shoulda/active_record/macros.rb, line 64
64:       def should_validate_uniqueness_of(*attributes)
65:         message, scope, case_sensitive = get_options!(attributes, :message, :scoped_to, :case_sensitive)
66:         scope = [*scope].compact
67:         case_sensitive = true if case_sensitive.nil?
68: 
69:         attributes.each do |attribute|
70:           matcher = validate_uniqueness_of(attribute).
71:             with_message(message).scoped_to(scope)
72:           matcher = matcher.case_insensitive unless case_sensitive
73:           should matcher.description do
74:             assert_accepts(matcher, subject)
75:           end
76:         end
77:       end

[Validate]