Module: Shoulda::ActiveRecord::Macros
- Included in:
- Test::Unit::TestCase
- Defined in:
- lib/shoulda/active_record/macros.rb
Overview
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.
Instance Method Summary collapse
-
#should_allow_mass_assignment_of(*attributes) ⇒ Object
Ensures that the attribute can be set on mass update.
-
#should_allow_values_for(attribute, *good_values) ⇒ Object
Ensures that the attribute can be set to the given values.
-
#should_belong_to(*associations) ⇒ Object
Ensure that the belongs_to relationship exists.
-
#should_ensure_length_at_least(attribute, min_length, opts = {}) ⇒ Object
Ensures that the length of the attribute is at least a certain length.
-
#should_ensure_length_in_range(attribute, range, opts = {}) ⇒ Object
Ensures that the length of the attribute is in the given range.
-
#should_ensure_length_is(attribute, length, opts = {}) ⇒ Object
Ensures that the length of the attribute is exactly a certain length.
-
#should_ensure_value_in_range(attribute, range, opts = {}) ⇒ Object
Ensure that the attribute is in the range specified.
-
#should_have_and_belong_to_many(*associations) ⇒ Object
Ensures that the has_and_belongs_to_many relationship exists, and that the join table is in place.
-
#should_have_class_methods(*methods) ⇒ Object
Ensure that the given class methods are defined on the model.
-
#should_have_db_columns(*columns) ⇒ Object
(also: #should_have_db_column)
Ensure that the given columns are defined on the models backing SQL table.
-
#should_have_db_indices(*columns) ⇒ Object
(also: #should_have_db_index)
Ensures that there are DB indices on the given columns or tuples of columns.
-
#should_have_index(*args) ⇒ Object
Deprecated.
-
#should_have_indices(*args) ⇒ Object
Deprecated.
-
#should_have_instance_methods(*methods) ⇒ Object
Ensure that the given instance methods are defined on the model.
-
#should_have_many(*associations) ⇒ Object
Ensures that the has_many relationship exists.
-
#should_have_named_scope(scope_call, find_options = nil) ⇒ Object
Deprecated.
-
#should_have_one(*associations) ⇒ Object
Ensure that the has_one relationship exists.
-
#should_have_readonly_attributes(*attributes) ⇒ Object
Ensures that the attribute cannot be changed once the record has been created.
-
#should_not_allow_mass_assignment_of(*attributes) ⇒ Object
Ensures that the attribute cannot be set on mass update.
-
#should_not_allow_values_for(attribute, *bad_values) ⇒ Object
Ensures that the attribute cannot be set to the given values.
-
#should_validate_acceptance_of(*attributes) ⇒ Object
Ensures that the model cannot be saved if one of the attributes listed is not accepted.
-
#should_validate_numericality_of(*attributes) ⇒ Object
Ensure that the attribute is numeric.
-
#should_validate_presence_of(*attributes) ⇒ Object
Ensures that the model cannot be saved if one of the attributes listed is not present.
-
#should_validate_uniqueness_of(*attributes) ⇒ Object
-
:message
- value the test expects to find inerrors.on(:attribute)
.
-
Methods included from Matchers
#allow_mass_assignment_of, #allow_value, #belong_to, #ensure_inclusion_of, #ensure_length_of, #have_and_belong_to_many, #have_db_column, #have_db_index, #have_many, #have_named_scope, #have_one, #have_readonly_attribute, #validate_acceptance_of, #validate_format_of, #validate_numericality_of, #validate_presence_of, #validate_uniqueness_of
Methods included from Helpers
Instance Method Details
#should_allow_mass_assignment_of(*attributes) ⇒ Object
Ensures that the attribute can be set on mass update.
should_allow_mass_assignment_of :first_name, :last_name
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/shoulda/active_record/macros.rb', line 83 def should_allow_mass_assignment_of(*attributes) (attributes) attributes.each do |attribute| matcher = allow_mass_assignment_of(attribute) should matcher.description do assert_accepts matcher, subject end end end |
#should_allow_values_for(attribute, *good_values) ⇒ Object
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"
149 150 151 152 153 154 155 156 157 |
# File 'lib/shoulda/active_record/macros.rb', line 149 def should_allow_values_for(attribute, *good_values) (good_values) good_values.each do |value| matcher = allow_value(value).for(attribute) should matcher.description do assert_accepts matcher, subject end end end |
#should_belong_to(*associations) ⇒ Object
Ensure that the belongs_to relationship exists.
should_belong_to :parent
335 336 337 338 339 340 341 342 343 |
# File 'lib/shoulda/active_record/macros.rb', line 335 def should_belong_to(*associations) dependent = (associations, :dependent) associations.each do |association| matcher = belong_to(association).dependent(dependent) should matcher.description do assert_accepts(matcher, subject) end end end |
#should_ensure_length_at_least(attribute, min_length, opts = {}) ⇒ Object
Ensures that the length of the attribute is at least a certain length
Options:
-
:short_message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.too_short') % min_length
Example:
should_ensure_length_at_least :name, 3
194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/shoulda/active_record/macros.rb', line 194 def should_ensure_length_at_least(attribute, min_length, opts = {}) = ([opts], :short_message) matcher = ensure_length_of(attribute). is_at_least(min_length). () should matcher.description do assert_accepts matcher, subject end end |
#should_ensure_length_in_range(attribute, range, opts = {}) ⇒ Object
Ensures that the length of the attribute is in the given range
Options:
-
:short_message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.too_short') % range.first
-
:long_message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.too_long') % range.last
Example:
should_ensure_length_in_range :password, (6..20)
170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/shoulda/active_record/macros.rb', line 170 def should_ensure_length_in_range(attribute, range, opts = {}) , = ([opts], :short_message, :long_message) matcher = ensure_length_of(attribute). is_at_least(range.first). (). is_at_most(range.last). () should matcher.description do assert_accepts matcher, subject end end |
#should_ensure_length_is(attribute, length, opts = {}) ⇒ Object
Ensures that the length of the attribute is exactly a certain length
Options:
-
:message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.wrong_length') % length
Example:
should_ensure_length_is :ssn, 9
215 216 217 218 219 220 221 222 223 224 |
# File 'lib/shoulda/active_record/macros.rb', line 215 def should_ensure_length_is(attribute, length, opts = {}) = ([opts], :message) matcher = ensure_length_of(attribute). is_equal_to(length). () should matcher.description do assert_accepts matcher, subject end end |
#should_ensure_value_in_range(attribute, range, opts = {}) ⇒ Object
Ensure that the attribute is in the range specified
Options:
-
:low_message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.inclusion')
-
:high_message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.inclusion')
Example:
should_ensure_value_in_range :age, (0..100)
237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/shoulda/active_record/macros.rb', line 237 def should_ensure_value_in_range(attribute, range, opts = {}) , , = ([opts], :message, :low_message, :high_message) matcher = ensure_inclusion_of(attribute). in_range(range). (). (). () should matcher.description do assert_accepts matcher, subject end end |
#should_have_and_belong_to_many(*associations) ⇒ Object
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
320 321 322 323 324 325 326 327 328 329 |
# File 'lib/shoulda/active_record/macros.rb', line 320 def should_have_and_belong_to_many(*associations) (associations) associations.each do |association| matcher = have_and_belong_to_many(association) should matcher.description do assert_accepts(matcher, subject) end end end |
#should_have_class_methods(*methods) ⇒ Object
Ensure that the given class methods are defined on the model.
should_have_class_methods :find, :destroy
349 350 351 352 353 354 355 356 357 |
# File 'lib/shoulda/active_record/macros.rb', line 349 def should_have_class_methods(*methods) (methods) klass = described_type methods.each do |method| should "respond to class method ##{method}" do assert_respond_to klass, method, "#{klass.name} does not have class method #{method}" end end end |
#should_have_db_columns(*columns) ⇒ Object Also known as: should_have_db_column
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
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
# File 'lib/shoulda/active_record/macros.rb', line 386 def should_have_db_columns(*columns) column_type, precision, limit, default, null, scale, sql_type = (columns, :type, :precision, :limit, :default, :null, :scale, :sql_type) columns.each do |name| matcher = have_db_column(name). of_type(column_type). (:precision => precision, :limit => limit, :default => default, :null => null, :scale => scale, :sql_type => sql_type) should matcher.description do assert_accepts(matcher, subject) end end end |
#should_have_db_indices(*columns) ⇒ Object Also known as: should_have_db_index
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. Usetrue
to explicitly test for a unique constraint. Usefalse
to explicitly test for a non-unique constraint. Usenil
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
420 421 422 423 424 425 426 427 428 429 |
# File 'lib/shoulda/active_record/macros.rb', line 420 def should_have_db_indices(*columns) unique = (columns, :unique) columns.each do |column| matcher = have_db_index(column).unique(unique) should matcher.description do assert_accepts(matcher, subject) end end end |
#should_have_index(*args) ⇒ Object
Deprecated. See should_have_db_index
434 435 436 437 438 |
# File 'lib/shoulda/active_record/macros.rb', line 434 def should_have_index(*args) warn "[DEPRECATION] should_have_index is deprecated. " << "Use should_have_db_index instead." should_have_db_index(*args) end |
#should_have_indices(*args) ⇒ Object
Deprecated. See should_have_db_indices
441 442 443 444 445 |
# File 'lib/shoulda/active_record/macros.rb', line 441 def should_have_indices(*args) warn "[DEPRECATION] should_have_indices is deprecated. " << "Use should_have_db_indices instead." should_have_db_indices(*args) end |
#should_have_instance_methods(*methods) ⇒ Object
Ensure that the given instance methods are defined on the model.
should_have_instance_methods :email, :name, :name=
363 364 365 366 367 368 369 370 371 |
# File 'lib/shoulda/active_record/macros.rb', line 363 def should_have_instance_methods(*methods) (methods) klass = described_type methods.each do |method| should "respond to instance method ##{method}" do assert_respond_to klass.new, method, "#{klass.name} does not have instance method #{method}" end end end |
#should_have_many(*associations) ⇒ Object
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 forhas_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
285 286 287 288 289 290 291 292 293 |
# File 'lib/shoulda/active_record/macros.rb', line 285 def should_have_many(*associations) through, dependent = (associations, :through, :dependent) associations.each do |association| matcher = have_many(association).through(through).dependent(dependent) should matcher.description do assert_accepts(matcher, subject) end end end |
#should_have_named_scope(scope_call, find_options = nil) ⇒ Object
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
504 505 506 507 508 509 |
# File 'lib/shoulda/active_record/macros.rb', line 504 def should_have_named_scope(scope_call, = nil) matcher = have_named_scope(scope_call).finding() should matcher.description do assert_accepts matcher.in_context(self), subject end end |
#should_have_one(*associations) ⇒ Object
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
305 306 307 308 309 310 311 312 313 |
# File 'lib/shoulda/active_record/macros.rb', line 305 def should_have_one(*associations) dependent, through = (associations, :dependent, :through) associations.each do |association| matcher = have_one(association).dependent(dependent).through(through) should matcher.description do assert_accepts(matcher, subject) end end end |
#should_have_readonly_attributes(*attributes) ⇒ Object
Ensures that the attribute cannot be changed once the record has been created.
should_have_readonly_attributes :password, :admin_flag
113 114 115 116 117 118 119 120 121 122 |
# File 'lib/shoulda/active_record/macros.rb', line 113 def should_have_readonly_attributes(*attributes) (attributes) attributes.each do |attribute| matcher = have_readonly_attribute(attribute) should matcher.description do assert_accepts matcher, subject end end end |
#should_not_allow_mass_assignment_of(*attributes) ⇒ Object
Ensures that the attribute cannot be set on mass update.
should_not_allow_mass_assignment_of :password, :admin_flag
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/shoulda/active_record/macros.rb', line 98 def should_not_allow_mass_assignment_of(*attributes) (attributes) attributes.each do |attribute| matcher = allow_mass_assignment_of(attribute) should "not #{matcher.description}" do assert_rejects matcher, subject end end end |
#should_not_allow_values_for(attribute, *bad_values) ⇒ Object
Ensures that the attribute cannot be set to the given values
Options:
-
:message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. If omitted, the test will pass if there is ANY error inerrors.on(:attribute)
.
Example:
should_not_allow_values_for :isbn, "bad 1", "bad 2"
134 135 136 137 138 139 140 141 142 |
# File 'lib/shoulda/active_record/macros.rb', line 134 def should_not_allow_values_for(attribute, *bad_values) = (bad_values, :message) bad_values.each do |value| matcher = allow_value(value).for(attribute).() should "not #{matcher.description}" do assert_rejects matcher, subject end end end |
#should_validate_acceptance_of(*attributes) ⇒ Object
Ensures that the model cannot be saved if one of the attributes listed is not accepted.
Options:
-
:message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.accepted')
Example:
should_validate_acceptance_of :eula
456 457 458 459 460 461 462 463 464 465 |
# File 'lib/shoulda/active_record/macros.rb', line 456 def should_validate_acceptance_of(*attributes) = (attributes, :message) attributes.each do |attribute| matcher = validate_acceptance_of(attribute).() should matcher.description do assert_accepts matcher, subject end end end |
#should_validate_numericality_of(*attributes) ⇒ Object
Ensure that the attribute is numeric
Options:
-
:message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.not_a_number')
Example:
should_validate_numericality_of :age
261 262 263 264 265 266 267 268 269 270 |
# File 'lib/shoulda/active_record/macros.rb', line 261 def should_validate_numericality_of(*attributes) = (attributes, :message) attributes.each do |attribute| matcher = validate_numericality_of(attribute). () should matcher.description do assert_accepts matcher, subject end end end |
#should_validate_presence_of(*attributes) ⇒ Object
Ensures that the model cannot be saved if one of the attributes listed is not present.
Options:
-
:message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.blank')
Example:
should_validate_presence_of :name, :phone_number
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/shoulda/active_record/macros.rb', line 35 def should_validate_presence_of(*attributes) = (attributes, :message) attributes.each do |attribute| matcher = validate_presence_of(attribute).() should matcher.description do assert_accepts(matcher, subject) end end end |
#should_validate_uniqueness_of(*attributes) ⇒ Object
-
:message
- value the test expects to find inerrors.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
64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/shoulda/active_record/macros.rb', line 64 def should_validate_uniqueness_of(*attributes) , scope, case_sensitive = (attributes, :message, :scoped_to, :case_sensitive) scope = [*scope].compact case_sensitive = true if case_sensitive.nil? attributes.each do |attribute| matcher = validate_uniqueness_of(attribute). ().scoped_to(scope) matcher = matcher.case_insensitive unless case_sensitive should matcher.description do assert_accepts(matcher, subject) end end end |