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
-
#load_all_fixtures ⇒ Object
DEPRECATED: Use
fixtures :all
instead. -
#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_indices(*columns) ⇒ Object
(also: #should_have_index)
Ensures that there are DB indices on the given columns or tuples of columns.
-
#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
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.
-
#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_only_allow_numeric_values_for(*attributes) ⇒ Object
Deprecated.
-
#should_protect_attributes(*attributes) ⇒ Object
Deprecated.
-
#should_require_acceptance_of(*attributes) ⇒ Object
Deprecated.
-
#should_require_attributes(*attributes) ⇒ Object
Deprecated.
-
#should_require_unique_attributes(*attributes) ⇒ Object
Deprecated.
-
#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_index, #have_many, #have_named_scope, #have_one, #have_readonly_attribute, #validate_acceptance_of, #validate_numericality_of, #validate_presence_of, #validate_uniqueness_of
Methods included from Helpers
Instance Method Details
#load_all_fixtures ⇒ Object
DEPRECATED: Use fixtures :all
instead
Loads all fixture files (test/fixtures/*.yml
)
29 30 31 32 |
# File 'lib/shoulda/active_record/macros.rb', line 29 def load_all_fixtures warn "[DEPRECATION] load_all_fixtures is deprecated. Use `fixtures :all` instead." fixtures :all end |
#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
112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/shoulda/active_record/macros.rb', line 112 def should_allow_mass_assignment_of(*attributes) (attributes) klass = model_class attributes.each do |attribute| matcher = allow_mass_assignment_of(attribute) should matcher.description do assert_accepts matcher, klass.new end end end |
#should_allow_values_for(attribute, *good_values) ⇒ Object
Ensures that the attribute can be set to the given values.
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
Example:
should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/shoulda/active_record/macros.rb', line 196 def should_allow_values_for(attribute, *good_values) (good_values) klass = model_class klass = model_class good_values.each do |value| matcher = allow_value(value).for(attribute) should matcher.description do assert_accepts matcher, get_instance_of(klass) end end end |
#should_belong_to(*associations) ⇒ Object
Ensure that the belongs_to relationship exists.
should_belong_to :parent
417 418 419 420 421 422 423 424 425 426 |
# File 'lib/shoulda/active_record/macros.rb', line 417 def should_belong_to(*associations) dependent = (associations, :dependent) klass = model_class associations.each do |association| matcher = belong_to(association).dependent(dependent) should matcher.description do assert_accepts(matcher, klass.new) 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
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
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
253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/shoulda/active_record/macros.rb', line 253 def should_ensure_length_at_least(attribute, min_length, opts = {}) = ([opts], :short_message) klass = model_class matcher = ensure_length_of(attribute). is_at_least(min_length). () should matcher.description do assert_accepts matcher, get_instance_of(klass) end end |
#should_ensure_length_in_range(attribute, range, opts = {}) ⇒ Object
Ensures that the length of the attribute is in the given range
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
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)
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/shoulda/active_record/macros.rb', line 223 def should_ensure_length_in_range(attribute, range, opts = {}) , = ([opts], :short_message, :long_message) klass = model_class matcher = ensure_length_of(attribute). is_at_least(range.first). (). is_at_most(range.last). () should matcher.description do assert_accepts matcher, get_instance_of(klass) end end |
#should_ensure_length_is(attribute, length, opts = {}) ⇒ Object
Ensures that the length of the attribute is exactly a certain length
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
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
279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/shoulda/active_record/macros.rb', line 279 def should_ensure_length_is(attribute, length, opts = {}) = ([opts], :message) klass = model_class matcher = ensure_length_of(attribute). is_equal_to(length). () should matcher.description do assert_accepts matcher, get_instance_of(klass) end end |
#should_ensure_value_in_range(attribute, range, opts = {}) ⇒ Object
Ensure that the attribute is in the range specified
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
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)
306 307 308 309 310 311 312 313 314 315 316 317 |
# File 'lib/shoulda/active_record/macros.rb', line 306 def should_ensure_value_in_range(attribute, range, opts = {}) = ([opts], :message) ||= (:inclusion) klass = model_class matcher = ensure_inclusion_of(attribute). in_range(range). () should matcher.description do assert_accepts matcher, get_instance_of(klass) 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
401 402 403 404 405 406 407 408 409 410 411 |
# File 'lib/shoulda/active_record/macros.rb', line 401 def should_have_and_belong_to_many(*associations) (associations) klass = model_class associations.each do |association| matcher = have_and_belong_to_many(association) should matcher.description do assert_accepts(matcher, klass.new) 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
432 433 434 435 436 437 438 439 440 |
# File 'lib/shoulda/active_record/macros.rb', line 432 def should_have_class_methods(*methods) (methods) klass = model_class 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_index 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
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 |
# File 'lib/shoulda/active_record/macros.rb', line 469 def should_have_db_columns(*columns) column_type, precision, limit, default, null, scale, sql_type = (columns, :type, :precision, :limit, :default, :null, :scale, :sql_type) klass = model_class 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, klass.new) end end end |
#should_have_indices(*columns) ⇒ Object Also known as: should_have_index
Ensures that there are DB indices on the given columns or tuples of columns. Also aliased to should_have_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_indices :email, :name, [:commentable_type, :commentable_id]
should_have_index :age
should_have_index :ssn, :unique => true
504 505 506 507 508 509 510 511 512 513 514 |
# File 'lib/shoulda/active_record/macros.rb', line 504 def should_have_indices(*columns) unique = (columns, :unique) klass = model_class columns.each do |column| matcher = have_index(column).unique(unique) should matcher.description do assert_accepts(matcher, klass.new) end end 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=
446 447 448 449 450 451 452 453 454 |
# File 'lib/shoulda/active_record/macros.rb', line 446 def should_have_instance_methods(*methods) (methods) klass = model_class 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
364 365 366 367 368 369 370 371 372 373 |
# File 'lib/shoulda/active_record/macros.rb', line 364 def should_have_many(*associations) through, dependent = (associations, :through, :dependent) klass = model_class associations.each do |association| matcher = have_many(association).through(through).dependent(dependent) should matcher.description do assert_accepts(matcher, klass.new) end end end |
#should_have_named_scope(scope_call, find_options = nil) ⇒ Object
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
585 586 587 588 589 590 591 |
# File 'lib/shoulda/active_record/macros.rb', line 585 def should_have_named_scope(scope_call, = nil) klass = model_class matcher = have_named_scope(scope_call).finding() should matcher.description do assert_accepts matcher.in_context(self), klass.new 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
385 386 387 388 389 390 391 392 393 394 |
# File 'lib/shoulda/active_record/macros.rb', line 385 def should_have_one(*associations) dependent = (associations, :dependent) klass = model_class associations.each do |association| matcher = have_one(association).dependent(dependent) should matcher.description do assert_accepts(matcher, klass.new) 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
151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/shoulda/active_record/macros.rb', line 151 def should_have_readonly_attributes(*attributes) (attributes) klass = model_class attributes.each do |attribute| matcher = have_readonly_attribute(attribute) should matcher.description do assert_accepts matcher, klass.new 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
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/shoulda/active_record/macros.rb', line 128 def should_not_allow_mass_assignment_of(*attributes) (attributes) klass = model_class attributes.each do |attribute| matcher = allow_mass_assignment_of(attribute) should "not #{matcher.description}" do assert_rejects matcher, klass.new end end end |
#should_not_allow_values_for(attribute, *bad_values) ⇒ Object
Ensures that the attribute cannot be set to the given values
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
Options:
-
:message
- value the test expects to find inerrors.on(:attribute)
. Regexp or string. Default =I18n.translate('activerecord.errors.messages.invalid')
Example:
should_not_allow_values_for :isbn, "bad 1", "bad 2"
176 177 178 179 180 181 182 183 184 185 |
# File 'lib/shoulda/active_record/macros.rb', line 176 def should_not_allow_values_for(attribute, *bad_values) = (bad_values, :message) klass = model_class bad_values.each do |value| matcher = allow_value(value).for(attribute).() should "not #{matcher.description}" do assert_rejects matcher, get_instance_of(klass) end end end |
#should_only_allow_numeric_values_for(*attributes) ⇒ Object
Deprecated. See should_validate_uniqueness_of
345 346 347 348 349 |
# File 'lib/shoulda/active_record/macros.rb', line 345 def should_only_allow_numeric_values_for(*attributes) warn "[DEPRECATION] should_only_allow_numeric_values_for is " << "deprecated. Use should_validate_numericality_of instead." should_validate_numericality_of(*attributes) end |
#should_protect_attributes(*attributes) ⇒ Object
Deprecated. See should_not_allow_mass_assignment_of
141 142 143 144 145 |
# File 'lib/shoulda/active_record/macros.rb', line 141 def should_protect_attributes(*attributes) warn "[DEPRECATION] should_protect_attributes is deprecated. " << "Use should_not_allow_mass_assignment_of instead." should_not_allow_mass_assignment_of(*attributes) end |
#should_require_acceptance_of(*attributes) ⇒ Object
Deprecated. See should_validate_uniqueness_of
544 545 546 547 548 |
# File 'lib/shoulda/active_record/macros.rb', line 544 def should_require_acceptance_of(*attributes) warn "[DEPRECATION] should_require_acceptance_of is deprecated. " << "Use should_validate_acceptance_of instead." should_validate_acceptance_of(*attributes) end |
#should_require_attributes(*attributes) ⇒ Object
Deprecated. See should_validate_presence_of
60 61 62 63 64 |
# File 'lib/shoulda/active_record/macros.rb', line 60 def should_require_attributes(*attributes) warn "[DEPRECATION] should_require_attributes is deprecated. " << "Use should_validate_presence_of instead." should_validate_presence_of(*attributes) end |
#should_require_unique_attributes(*attributes) ⇒ Object
Deprecated. See should_validate_uniqueness_of
102 103 104 105 106 |
# File 'lib/shoulda/active_record/macros.rb', line 102 def should_require_unique_attributes(*attributes) warn "[DEPRECATION] should_require_unique_attributes is deprecated. " << "Use should_validate_uniqueness_of instead." should_validate_uniqueness_of(*attributes) end |
#should_validate_acceptance_of(*attributes) ⇒ Object
Ensures that the model cannot be saved if one of the attributes listed is not accepted.
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
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
531 532 533 534 535 536 537 538 539 540 541 |
# File 'lib/shoulda/active_record/macros.rb', line 531 def should_validate_acceptance_of(*attributes) = (attributes, :message) klass = model_class attributes.each do |attribute| matcher = validate_acceptance_of(attribute).() should matcher.description do assert_accepts matcher, get_instance_of(klass) end end end |
#should_validate_numericality_of(*attributes) ⇒ Object
Ensure that the attribute is numeric
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
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
332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/shoulda/active_record/macros.rb', line 332 def should_validate_numericality_of(*attributes) = (attributes, :message) klass = model_class attributes.each do |attribute| matcher = validate_numericality_of(attribute). () should matcher.description do assert_accepts matcher, get_instance_of(klass) 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.
If an instance variable has been created in the setup named after the model being tested, then this method will use that. Otherwise, it will create a new instance to test against.
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
47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/shoulda/active_record/macros.rb', line 47 def should_validate_presence_of(*attributes) = (attributes, :message) klass = model_class attributes.each do |attribute| matcher = validate_presence_of(attribute).() should matcher.description do assert_accepts(matcher, get_instance_of(klass)) 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
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/shoulda/active_record/macros.rb', line 84 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? klass = model_class 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, get_instance_of(klass)) end end end |