mcmire-shoulda-matchers 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +32 -0
- data/.yardopts +7 -0
- data/Appraisals +45 -0
- data/CONTRIBUTING.md +41 -0
- data/Gemfile +31 -0
- data/Gemfile.lock +166 -0
- data/MIT-LICENSE +22 -0
- data/NEWS.md +299 -0
- data/README.md +163 -0
- data/Rakefile +116 -0
- data/doc_config/gh-pages/index.html.erb +9 -0
- data/doc_config/yard/setup.rb +22 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +300 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
- data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
- data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
- data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
- data/doc_config/yard/templates/default/layout/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
- data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
- data/features/rails_integration.feature +113 -0
- data/features/step_definitions/rails_steps.rb +162 -0
- data/features/support/env.rb +5 -0
- data/gemfiles/3.0.gemfile +24 -0
- data/gemfiles/3.0.gemfile.lock +150 -0
- data/gemfiles/3.1.gemfile +27 -0
- data/gemfiles/3.1.gemfile.lock +173 -0
- data/gemfiles/3.2.gemfile +27 -0
- data/gemfiles/3.2.gemfile.lock +171 -0
- data/gemfiles/4.0.0.gemfile +28 -0
- data/gemfiles/4.0.0.gemfile.lock +172 -0
- data/gemfiles/4.0.1.gemfile +28 -0
- data/gemfiles/4.0.1.gemfile.lock +172 -0
- data/lib/shoulda-matchers.rb +1 -0
- data/lib/shoulda/matchers.rb +11 -0
- data/lib/shoulda/matchers/action_controller.rb +17 -0
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +64 -0
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +97 -0
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +81 -0
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +117 -0
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +114 -0
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +154 -0
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +116 -0
- data/lib/shoulda/matchers/action_controller/route_params.rb +48 -0
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +164 -0
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +296 -0
- data/lib/shoulda/matchers/active_model.rb +30 -0
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +167 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +314 -0
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +46 -0
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +160 -0
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +417 -0
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +337 -0
- data/lib/shoulda/matchers/active_model/errors.rb +10 -0
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +58 -0
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +92 -0
- data/lib/shoulda/matchers/active_model/helpers.rb +46 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +75 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +26 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +112 -0
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +77 -0
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +121 -0
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +380 -0
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +89 -0
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +372 -0
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +97 -0
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +69 -0
- data/lib/shoulda/matchers/active_record.rb +22 -0
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +204 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +901 -0
- data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +81 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +65 -0
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +94 -0
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +41 -0
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +63 -0
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +261 -0
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +149 -0
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +72 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +181 -0
- data/lib/shoulda/matchers/assertion_error.rb +19 -0
- data/lib/shoulda/matchers/error.rb +6 -0
- data/lib/shoulda/matchers/integrations/rspec.rb +20 -0
- data/lib/shoulda/matchers/integrations/test_unit.rb +30 -0
- data/lib/shoulda/matchers/rails_shim.rb +50 -0
- data/lib/shoulda/matchers/version.rb +6 -0
- data/lib/shoulda/matchers/warn.rb +8 -0
- data/shoulda-matchers.gemspec +23 -0
- data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +22 -0
- data/spec/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +42 -0
- data/spec/shoulda/matchers/action_controller/render_template_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +31 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +70 -0
- data/spec/shoulda/matchers/action_controller/route_params_spec.rb +30 -0
- data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +51 -0
- data/spec/shoulda/matchers/action_controller/set_the_flash_matcher_spec.rb +153 -0
- data/spec/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +170 -0
- data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +81 -0
- data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +95 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +320 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +166 -0
- data/spec/shoulda/matchers/active_model/exception_message_finder_spec.rb +111 -0
- data/spec/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +20 -0
- data/spec/shoulda/matchers/active_model/helpers_spec.rb +158 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +169 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +59 -0
- data/spec/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +57 -0
- data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +139 -0
- data/spec/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +47 -0
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +331 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +180 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +398 -0
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +127 -0
- data/spec/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +107 -0
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +860 -0
- data/spec/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +247 -0
- data/spec/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +111 -0
- data/spec/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +78 -0
- data/spec/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +41 -0
- data/spec/shoulda/matchers/active_record/serialize_matcher_spec.rb +86 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/active_model_versions.rb +13 -0
- data/spec/support/active_resource_builder.rb +29 -0
- data/spec/support/activemodel_helpers.rb +19 -0
- data/spec/support/capture_helpers.rb +19 -0
- data/spec/support/class_builder.rb +42 -0
- data/spec/support/controller_builder.rb +74 -0
- data/spec/support/fail_with_message_including_matcher.rb +33 -0
- data/spec/support/fail_with_message_matcher.rb +32 -0
- data/spec/support/i18n_faker.rb +10 -0
- data/spec/support/mailer_builder.rb +10 -0
- data/spec/support/model_builder.rb +81 -0
- data/spec/support/rails_versions.rb +18 -0
- data/spec/support/shared_examples/numerical_submatcher.rb +19 -0
- data/spec/support/shared_examples/numerical_type_submatcher.rb +17 -0
- data/spec/support/test_application.rb +120 -0
- data/yard.watchr +5 -0
- metadata +281 -0
@@ -0,0 +1,121 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
# The `validate_confirmation_of` matcher tests usage of the
|
5
|
+
# `validates_confirmation_of` validation.
|
6
|
+
#
|
7
|
+
# class User
|
8
|
+
# include ActiveModel::Model
|
9
|
+
#
|
10
|
+
# validates_confirmation_of :email
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# # RSpec
|
14
|
+
# describe User do
|
15
|
+
# it { should validate_confirmation_of(:email) }
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # Test::Unit
|
19
|
+
# class UserTest < ActiveSupport::TestCase
|
20
|
+
# should validate_confirmation_of(:email)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# #### Qualifiers
|
24
|
+
#
|
25
|
+
# ##### with_message
|
26
|
+
#
|
27
|
+
# Use `with_message` if you are using a custom validation message.
|
28
|
+
#
|
29
|
+
# class User
|
30
|
+
# include ActiveModel::Model
|
31
|
+
#
|
32
|
+
# validates_confirmation_of :password,
|
33
|
+
# message: 'Please re-enter your password'
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # RSpec
|
37
|
+
# describe User do
|
38
|
+
# it do
|
39
|
+
# should validate_confirmation_of(:password).
|
40
|
+
# with_message('Please re-enter your password')
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # Test::Unit
|
45
|
+
# class UserTest < ActiveSupport::TestCase
|
46
|
+
# should validate_confirmation_of(:password).
|
47
|
+
# with_message('Please re-enter your password')
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# @return [ValidateConfirmationOfMatcher]
|
51
|
+
#
|
52
|
+
def validate_confirmation_of(attr)
|
53
|
+
ValidateConfirmationOfMatcher.new(attr)
|
54
|
+
end
|
55
|
+
|
56
|
+
# @private
|
57
|
+
class ValidateConfirmationOfMatcher < ValidationMatcher
|
58
|
+
include Helpers
|
59
|
+
|
60
|
+
attr_reader :attribute, :confirmation_attribute
|
61
|
+
|
62
|
+
def initialize(attribute)
|
63
|
+
@attribute = attribute
|
64
|
+
@confirmation_attribute = "#{attribute}_confirmation"
|
65
|
+
end
|
66
|
+
|
67
|
+
def with_message(message)
|
68
|
+
@message = message if message
|
69
|
+
self
|
70
|
+
end
|
71
|
+
|
72
|
+
def description
|
73
|
+
"require #{@confirmation_attribute} to match #{@attribute}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def matches?(subject)
|
77
|
+
super(subject)
|
78
|
+
@message ||= :confirmation
|
79
|
+
|
80
|
+
disallows_different_value &&
|
81
|
+
allows_same_value &&
|
82
|
+
allows_missing_confirmation
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def disallows_different_value
|
88
|
+
set_confirmation('some value')
|
89
|
+
disallows_value_of('different value') do |matcher|
|
90
|
+
matcher.with_message(@message, against: error_attribute)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def allows_same_value
|
95
|
+
set_confirmation('same value')
|
96
|
+
allows_value_of('same value') do |matcher|
|
97
|
+
matcher.with_message(@message, against: error_attribute)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def allows_missing_confirmation
|
102
|
+
set_confirmation(nil)
|
103
|
+
allows_value_of('any value') do |matcher|
|
104
|
+
matcher.with_message(@message, against: error_attribute)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def set_confirmation(val)
|
109
|
+
setter = :"#{@confirmation_attribute}="
|
110
|
+
if @subject.respond_to?(setter)
|
111
|
+
@subject.__send__(setter, val)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def error_attribute
|
116
|
+
RailsShim.validates_confirmation_of_error_attribute(self)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,380 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveModel
|
4
|
+
# The `validate_numericality_of` matcher tests usage of the
|
5
|
+
# `validates_numericality_of` validation.
|
6
|
+
#
|
7
|
+
# class Person < ActiveRecord::Base
|
8
|
+
# validates_numericality_of :gpa
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# # RSpec
|
12
|
+
# describe Person do
|
13
|
+
# it { should validate_numericality_of(:gpa) }
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# # Test::Unit
|
17
|
+
# class PersonTest < ActiveSupport::TestCase
|
18
|
+
# should validate_numericality_of(:gpa)
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# #### Qualifiers
|
22
|
+
#
|
23
|
+
# ##### only_integer
|
24
|
+
#
|
25
|
+
# Use `only_integer` to test usage of the `:only_integer` option. This
|
26
|
+
# asserts that your attribute only allows integer numbers and disallows
|
27
|
+
# non-integer ones.
|
28
|
+
#
|
29
|
+
# class Person
|
30
|
+
# include ActiveModel::Model
|
31
|
+
#
|
32
|
+
# validates_numericality_of :age, only_integer: true
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # RSpec
|
36
|
+
# describe Person do
|
37
|
+
# it { should validate_numericality_of(:age).only_integer }
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# # Test::Unit
|
41
|
+
# class PersonTest < ActiveSupport::TestCase
|
42
|
+
# should validate_numericality_of(:age).only_integer
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# ##### is_less_than
|
46
|
+
#
|
47
|
+
# Use `is_less_than` to test usage of the the `:less_than` option. This
|
48
|
+
# asserts that the attribute can take a number which is less than the
|
49
|
+
# given value and cannot take a number which is greater than or equal to
|
50
|
+
# it.
|
51
|
+
#
|
52
|
+
# class Person
|
53
|
+
# include ActiveModel::Model
|
54
|
+
#
|
55
|
+
# validates_numericality_of :number_of_cars, less_than: 2
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# # RSpec
|
59
|
+
# describe Person do
|
60
|
+
# it { should validate_numericality_of(:number_of_cars).is_less_than(2) }
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# # Test::Unit
|
64
|
+
# class PersonTest < ActiveSupport::TestCase
|
65
|
+
# should validate_numericality_of(:number_of_cars).is_less_than(2)
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# ##### is_less_than_or_equal_to
|
69
|
+
#
|
70
|
+
# Use `is_less_than_or_equal_to` to test usage of the
|
71
|
+
# `:less_than_or_equal_to` option. This asserts that the attribute can
|
72
|
+
# take a number which is less than or equal to the given value and cannot
|
73
|
+
# take a number which is greater than it.
|
74
|
+
#
|
75
|
+
# class Person
|
76
|
+
# include ActiveModel::Model
|
77
|
+
#
|
78
|
+
# validates_numericality_of :birth_year, less_than_or_equal_to: 1987
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# # RSpec
|
82
|
+
# describe Person do
|
83
|
+
# it { should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987) }
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# # Test::Unit
|
87
|
+
# class PersonTest < ActiveSupport::TestCase
|
88
|
+
# should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987)
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
# ##### is_equal_to
|
92
|
+
#
|
93
|
+
# Use `is_equal_to` to test usage of the `:equal_to` option. This asserts
|
94
|
+
# that the attribute can take a number which is equal to the given value
|
95
|
+
# and cannot take a number which is not equal.
|
96
|
+
#
|
97
|
+
# class Person
|
98
|
+
# include ActiveModel::Model
|
99
|
+
#
|
100
|
+
# validates_numericality_of :weight, equal_to: 150
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# # RSpec
|
104
|
+
# describe Person do
|
105
|
+
# it { should validate_numericality_of(:weight).is_equal_to(150) }
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# # Test::Unit
|
109
|
+
# class PersonTest < ActiveSupport::TestCase
|
110
|
+
# should validate_numericality_of(:weight).is_equal_to(150)
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# ##### is_greater_than_or_equal_to
|
114
|
+
#
|
115
|
+
# Use `is_greater_than_or_equal_to` to test usage of the
|
116
|
+
# `:greater_than_or_equal_to` option. This asserts that the attribute can
|
117
|
+
# take a number which is greater than or equal to the given value and
|
118
|
+
# cannot take a number which is less than it.
|
119
|
+
#
|
120
|
+
# class Person
|
121
|
+
# include ActiveModel::Model
|
122
|
+
#
|
123
|
+
# validates_numericality_of :height, greater_than_or_equal_to: 55
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# # RSpec
|
127
|
+
# describe Person do
|
128
|
+
# it { should validate_numericality_of(:height).is_greater_than_or_equal_to(55) }
|
129
|
+
# end
|
130
|
+
#
|
131
|
+
# # Test::Unit
|
132
|
+
# class PersonTest < ActiveSupport::TestCase
|
133
|
+
# should validate_numericality_of(:height).is_greater_than_or_equal_to(55)
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# ##### is_greater_than
|
137
|
+
#
|
138
|
+
# Use `is_greater_than` to test usage of tthe `:greater_than` option.
|
139
|
+
# This asserts that the attribute can take a number which is greater than
|
140
|
+
# the given value and cannot take a number less than or equal to it.
|
141
|
+
#
|
142
|
+
# class Person
|
143
|
+
# include ActiveModel::Model
|
144
|
+
#
|
145
|
+
# validates_numericality_of :legal_age, greater_than: 21
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# # RSpec
|
149
|
+
# describe Person do
|
150
|
+
# it { should validate_numericality_of(:legal_age).is_greater_than(21) }
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
# # Test::Unit
|
154
|
+
# class PersonTest < ActiveSupport::TestCase
|
155
|
+
# should validate_numericality_of(:legal_age).is_greater_than(21)
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# ##### even
|
159
|
+
#
|
160
|
+
# Use `even` to test usage of the `:even` option. This asserts that the
|
161
|
+
# attribute can take odd numbers and cannot take even ones.
|
162
|
+
#
|
163
|
+
# class Person
|
164
|
+
# include ActiveModel::Model
|
165
|
+
#
|
166
|
+
# validates_numericality_of :birth_month, even: true
|
167
|
+
# end
|
168
|
+
#
|
169
|
+
# # RSpec
|
170
|
+
# describe Person do
|
171
|
+
# it { should validate_numericality_of(:birth_month).even }
|
172
|
+
# end
|
173
|
+
#
|
174
|
+
# # Test::Unit
|
175
|
+
# class PersonTest < ActiveSupport::TestCase
|
176
|
+
# should validate_numericality_of(:birth_month).even
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
# ##### odd
|
180
|
+
#
|
181
|
+
# Use `odd` to test usage of the `:odd` option. This asserts that the
|
182
|
+
# attribute can take a number which is odd and cannot take a number which
|
183
|
+
# is even.
|
184
|
+
#
|
185
|
+
# class Person
|
186
|
+
# include ActiveModel::Model
|
187
|
+
#
|
188
|
+
# validates_numericality_of :birth_day, odd: true
|
189
|
+
# end
|
190
|
+
#
|
191
|
+
# # RSpec
|
192
|
+
# describe Person do
|
193
|
+
# it { should validate_numericality_of(:birth_day).odd }
|
194
|
+
# end
|
195
|
+
#
|
196
|
+
# # Test::Unit
|
197
|
+
# class PersonTest < ActiveSupport::TestCase
|
198
|
+
# should validate_numericality_of(:birth_day).odd
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# ##### allow_nil
|
202
|
+
#
|
203
|
+
# Use `allow_nil` to assert that the attribute allows nil.
|
204
|
+
#
|
205
|
+
# class Person
|
206
|
+
# include ActiveModel::Model
|
207
|
+
#
|
208
|
+
# validate_numericality_of :rank, allow_nil: true
|
209
|
+
# end
|
210
|
+
#
|
211
|
+
# # RSpec
|
212
|
+
# describe Person do
|
213
|
+
# it { should validate_numericality_of(:rank).allow_nil }
|
214
|
+
# end
|
215
|
+
#
|
216
|
+
# # Test::Unit
|
217
|
+
# class PersonTest < ActiveSupport::TestCase
|
218
|
+
# should validate_uniqueness_of(:rank).allow_nil
|
219
|
+
# end
|
220
|
+
#
|
221
|
+
# ##### with_message
|
222
|
+
#
|
223
|
+
# Use `with_message` if you are using a custom validation message.
|
224
|
+
#
|
225
|
+
# class Person
|
226
|
+
# include ActiveModel::Model
|
227
|
+
#
|
228
|
+
# validates_numericality_of :number_of_dependents,
|
229
|
+
# message: 'Number of dependents must be a number'
|
230
|
+
# end
|
231
|
+
#
|
232
|
+
# # RSpec
|
233
|
+
# describe Person do
|
234
|
+
# it do
|
235
|
+
# should validate_numericality_of(:number_of_dependents).
|
236
|
+
# with_message('Number of dependents must be a number')
|
237
|
+
# end
|
238
|
+
# end
|
239
|
+
#
|
240
|
+
# # Test::Unit
|
241
|
+
# class PersonTest < ActiveSupport::TestCase
|
242
|
+
# should validate_numericality_of(:number_of_dependents).
|
243
|
+
# with_message('Number of dependents must be a number')
|
244
|
+
# end
|
245
|
+
#
|
246
|
+
# @return [ValidateNumericalityOfMatcher]
|
247
|
+
#
|
248
|
+
def validate_numericality_of(attr)
|
249
|
+
ValidateNumericalityOfMatcher.new(attr)
|
250
|
+
end
|
251
|
+
|
252
|
+
# @private
|
253
|
+
class ValidateNumericalityOfMatcher
|
254
|
+
NUMERIC_NAME = 'numbers'
|
255
|
+
NON_NUMERIC_VALUE = 'abcd'
|
256
|
+
|
257
|
+
def initialize(attribute)
|
258
|
+
@attribute = attribute
|
259
|
+
@submatchers = []
|
260
|
+
|
261
|
+
add_disallow_value_matcher
|
262
|
+
end
|
263
|
+
|
264
|
+
def only_integer
|
265
|
+
add_submatcher(NumericalityMatchers::OnlyIntegerMatcher.new(@attribute))
|
266
|
+
self
|
267
|
+
end
|
268
|
+
|
269
|
+
def is_greater_than(value)
|
270
|
+
add_submatcher(NumericalityMatchers::ComparisonMatcher.new(value, :>).for(@attribute))
|
271
|
+
self
|
272
|
+
end
|
273
|
+
|
274
|
+
def is_greater_than_or_equal_to(value)
|
275
|
+
add_submatcher(NumericalityMatchers::ComparisonMatcher.new(value, :>=).for(@attribute))
|
276
|
+
self
|
277
|
+
end
|
278
|
+
|
279
|
+
def is_equal_to(value)
|
280
|
+
add_submatcher(NumericalityMatchers::ComparisonMatcher.new(value, :==).for(@attribute))
|
281
|
+
self
|
282
|
+
end
|
283
|
+
|
284
|
+
def is_less_than(value)
|
285
|
+
add_submatcher(NumericalityMatchers::ComparisonMatcher.new(value, :<).for(@attribute))
|
286
|
+
self
|
287
|
+
end
|
288
|
+
|
289
|
+
def is_less_than_or_equal_to(value)
|
290
|
+
add_submatcher(NumericalityMatchers::ComparisonMatcher.new(value, :<=).for(@attribute))
|
291
|
+
self
|
292
|
+
end
|
293
|
+
|
294
|
+
def odd
|
295
|
+
odd_number_matcher = NumericalityMatchers::OddNumberMatcher.new(@attribute)
|
296
|
+
add_submatcher(odd_number_matcher)
|
297
|
+
self
|
298
|
+
end
|
299
|
+
|
300
|
+
def even
|
301
|
+
even_number_matcher = NumericalityMatchers::EvenNumberMatcher.new(@attribute)
|
302
|
+
add_submatcher(even_number_matcher)
|
303
|
+
self
|
304
|
+
end
|
305
|
+
|
306
|
+
def with_message(message)
|
307
|
+
@submatchers.each { |matcher| matcher.with_message(message) }
|
308
|
+
self
|
309
|
+
end
|
310
|
+
|
311
|
+
def matches?(subject)
|
312
|
+
@subject = subject
|
313
|
+
submatchers_match?
|
314
|
+
end
|
315
|
+
|
316
|
+
def description
|
317
|
+
"only allow #{allowed_types} for #{@attribute}#{comparison_descriptions}"
|
318
|
+
end
|
319
|
+
|
320
|
+
def failure_message
|
321
|
+
submatcher_failure_messages_for_should.last
|
322
|
+
end
|
323
|
+
alias failure_message_for_should failure_message
|
324
|
+
|
325
|
+
def failure_message_when_negated
|
326
|
+
submatcher_failure_messages_for_should_not.last
|
327
|
+
end
|
328
|
+
alias failure_message_for_should_not failure_message_when_negated
|
329
|
+
|
330
|
+
private
|
331
|
+
|
332
|
+
def add_disallow_value_matcher
|
333
|
+
disallow_value_matcher = DisallowValueMatcher.new(NON_NUMERIC_VALUE).
|
334
|
+
for(@attribute).
|
335
|
+
with_message(:not_a_number)
|
336
|
+
|
337
|
+
add_submatcher(disallow_value_matcher)
|
338
|
+
end
|
339
|
+
|
340
|
+
def add_submatcher(submatcher)
|
341
|
+
@submatchers << submatcher
|
342
|
+
end
|
343
|
+
|
344
|
+
def submatchers_match?
|
345
|
+
failing_submatchers.empty?
|
346
|
+
end
|
347
|
+
|
348
|
+
def submatcher_failure_messages_for_should
|
349
|
+
failing_submatchers.map(&:failure_message)
|
350
|
+
end
|
351
|
+
|
352
|
+
def submatcher_failure_messages_for_should_not
|
353
|
+
failing_submatchers.map(&:failure_message_when_negated)
|
354
|
+
end
|
355
|
+
|
356
|
+
def failing_submatchers
|
357
|
+
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject) }
|
358
|
+
end
|
359
|
+
|
360
|
+
def allowed_types
|
361
|
+
allowed_array = submatcher_allowed_types
|
362
|
+
allowed_array.empty? ? NUMERIC_NAME : allowed_array.join(', ')
|
363
|
+
end
|
364
|
+
|
365
|
+
def submatcher_allowed_types
|
366
|
+
@submatchers.inject([]){|m, s| m << s.allowed_type if s.respond_to?(:allowed_type); m }
|
367
|
+
end
|
368
|
+
|
369
|
+
def comparison_descriptions
|
370
|
+
description_array = submatcher_comparison_descriptions
|
371
|
+
description_array.empty? ? '' : ' which are ' + submatcher_comparison_descriptions.join(' and ')
|
372
|
+
end
|
373
|
+
|
374
|
+
def submatcher_comparison_descriptions
|
375
|
+
@submatchers.inject([]){|m, s| m << s.comparison_description if s.respond_to?(:comparison_description); m }
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|