ultra-fast-box 0.0.1

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.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/shoulda-matchers-8.0.1/LICENSE +22 -0
  3. data/shoulda-matchers-8.0.1/README.md +567 -0
  4. data/shoulda-matchers-8.0.1/docs/errors/NonCaseSwappableValueError.md +111 -0
  5. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/callback_matcher.rb +121 -0
  6. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +70 -0
  7. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/flash_store.rb +86 -0
  8. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/permit_matcher.rb +445 -0
  9. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +96 -0
  10. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_template_matcher.rb +84 -0
  11. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +145 -0
  12. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +115 -0
  13. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +148 -0
  14. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_matcher.rb +207 -0
  15. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_params.rb +62 -0
  16. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
  17. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +228 -0
  18. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_matcher.rb +163 -0
  19. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +107 -0
  20. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller.rb +24 -0
  21. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
  22. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
  23. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +232 -0
  24. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
  25. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
  26. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
  27. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
  28. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
  29. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher.rb +695 -0
  30. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
  31. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +78 -0
  32. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/errors.rb +52 -0
  33. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +125 -0
  34. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/helpers.rb +37 -0
  35. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +45 -0
  36. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +67 -0
  37. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +45 -0
  38. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +44 -0
  39. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
  40. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +53 -0
  41. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
  42. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
  43. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
  44. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
  45. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
  46. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers.rb +14 -0
  47. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +180 -0
  48. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +128 -0
  49. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +567 -0
  50. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +185 -0
  51. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +272 -0
  52. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +664 -0
  53. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +575 -0
  54. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +711 -0
  55. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +428 -0
  56. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +62 -0
  57. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher.rb +195 -0
  58. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_message_finder.rb +63 -0
  59. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validator.rb +127 -0
  60. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model.rb +96 -0
  61. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +217 -0
  62. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matcher.rb +2134 -0
  63. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +74 -0
  64. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +62 -0
  65. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +41 -0
  66. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +105 -0
  67. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +101 -0
  68. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +89 -0
  69. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +142 -0
  70. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +71 -0
  71. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
  72. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +76 -0
  73. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +42 -0
  74. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +65 -0
  75. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
  76. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +784 -0
  77. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
  78. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_attached_matcher.rb +343 -0
  79. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +366 -0
  80. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +287 -0
  81. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +104 -0
  82. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +95 -0
  83. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
  84. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
  85. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
  86. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/serialize_matcher.rb +203 -0
  87. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/model.rb +58 -0
  88. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +39 -0
  89. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +49 -0
  90. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +55 -0
  91. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
  92. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1197 -0
  93. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record.rb +37 -0
  94. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/configuration.rb +31 -0
  95. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double.rb +103 -0
  96. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_collection.rb +60 -0
  97. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +31 -0
  98. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/method_call.rb +44 -0
  99. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/object_double.rb +43 -0
  100. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +32 -0
  101. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/stub_implementation.rb +31 -0
  102. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/world.rb +63 -0
  103. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak.rb +38 -0
  104. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/error.rb +29 -0
  105. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
  106. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher.rb +540 -0
  107. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent.rb +11 -0
  108. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration.rb +70 -0
  109. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
  110. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
  111. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/action_controller.rb +33 -0
  112. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
  113. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
  114. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
  115. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/rails.rb +31 -0
  116. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/routing.rb +29 -0
  117. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries.rb +16 -0
  118. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/rails.rb +12 -0
  119. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/registry.rb +28 -0
  120. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
  121. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
  122. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
  123. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
  124. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
  125. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
  126. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
  127. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations.rb +43 -0
  128. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_collection.rb +99 -0
  129. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_context.rb +36 -0
  130. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/rails_shim.rb +190 -0
  131. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/routing.rb +10 -0
  132. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util/word_wrap.rb +211 -0
  133. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util.rb +110 -0
  134. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/version.rb +6 -0
  135. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/warn.rb +28 -0
  136. data/shoulda-matchers-8.0.1/lib/shoulda/matchers.rb +25 -0
  137. data/shoulda-matchers-8.0.1/lib/shoulda-matchers.rb +1 -0
  138. data/shoulda-matchers-8.0.1/shoulda-matchers.gemspec +43 -0
  139. data/ultra-fast-box.gemspec +12 -0
  140. metadata +179 -0
@@ -0,0 +1,711 @@
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
8
+ # include ActiveModel::Model
9
+ # attr_accessor :gpa
10
+ #
11
+ # validates_numericality_of :gpa
12
+ # end
13
+ #
14
+ # # RSpec
15
+ # RSpec.describe Person, type: :model do
16
+ # it { should validate_numericality_of(:gpa) }
17
+ # end
18
+ #
19
+ # # Minitest (Shoulda)
20
+ # class PersonTest < ActiveSupport::TestCase
21
+ # should validate_numericality_of(:gpa)
22
+ # end
23
+ #
24
+ # #### Qualifiers
25
+ #
26
+ # ##### on
27
+ #
28
+ # Use `on` if your validation applies only under a certain context.
29
+ #
30
+ # class Person
31
+ # include ActiveModel::Model
32
+ # attr_accessor :number_of_dependents
33
+ #
34
+ # validates_numericality_of :number_of_dependents, on: :create
35
+ # end
36
+ #
37
+ # # RSpec
38
+ # RSpec.describe Person, type: :model do
39
+ # it do
40
+ # should validate_numericality_of(:number_of_dependents).
41
+ # on(:create)
42
+ # end
43
+ # end
44
+ #
45
+ # # Minitest (Shoulda)
46
+ # class PersonTest < ActiveSupport::TestCase
47
+ # should validate_numericality_of(:number_of_dependents).on(:create)
48
+ # end
49
+ #
50
+ # ##### only_integer
51
+ #
52
+ # Use `only_integer` to test usage of the `:only_integer` option. This
53
+ # asserts that your attribute only allows integer numbers and disallows
54
+ # non-integer ones.
55
+ #
56
+ # class Person
57
+ # include ActiveModel::Model
58
+ # attr_accessor :age
59
+ #
60
+ # validates_numericality_of :age, only_integer: true
61
+ # end
62
+ #
63
+ # # RSpec
64
+ # RSpec.describe Person, type: :model do
65
+ # it { should validate_numericality_of(:age).only_integer }
66
+ # end
67
+ #
68
+ # # Minitest (Shoulda)
69
+ # class PersonTest < ActiveSupport::TestCase
70
+ # should validate_numericality_of(:age).only_integer
71
+ # end
72
+ #
73
+ # ##### is_less_than
74
+ #
75
+ # Use `is_less_than` to test usage of the the `:less_than` option. This
76
+ # asserts that the attribute can take a number which is less than the
77
+ # given value and cannot take a number which is greater than or equal to
78
+ # it.
79
+ #
80
+ # class Person
81
+ # include ActiveModel::Model
82
+ # attr_accessor :number_of_cars
83
+ #
84
+ # validates_numericality_of :number_of_cars, less_than: 2
85
+ # end
86
+ #
87
+ # # RSpec
88
+ # RSpec.describe Person, type: :model do
89
+ # it do
90
+ # should validate_numericality_of(:number_of_cars).
91
+ # is_less_than(2)
92
+ # end
93
+ # end
94
+ #
95
+ # # Minitest (Shoulda)
96
+ # class PersonTest < ActiveSupport::TestCase
97
+ # should validate_numericality_of(:number_of_cars).
98
+ # is_less_than(2)
99
+ # end
100
+ #
101
+ # ##### is_less_than_or_equal_to
102
+ #
103
+ # Use `is_less_than_or_equal_to` to test usage of the
104
+ # `:less_than_or_equal_to` option. This asserts that the attribute can
105
+ # take a number which is less than or equal to the given value and cannot
106
+ # take a number which is greater than it.
107
+ #
108
+ # class Person
109
+ # include ActiveModel::Model
110
+ # attr_accessor :birth_year
111
+ #
112
+ # validates_numericality_of :birth_year, less_than_or_equal_to: 1987
113
+ # end
114
+ #
115
+ # # RSpec
116
+ # RSpec.describe Person, type: :model do
117
+ # it do
118
+ # should validate_numericality_of(:birth_year).
119
+ # is_less_than_or_equal_to(1987)
120
+ # end
121
+ # end
122
+ #
123
+ # # Minitest (Shoulda)
124
+ # class PersonTest < ActiveSupport::TestCase
125
+ # should validate_numericality_of(:birth_year).
126
+ # is_less_than_or_equal_to(1987)
127
+ # end
128
+ #
129
+ # ##### is_equal_to
130
+ #
131
+ # Use `is_equal_to` to test usage of the `:equal_to` option. This asserts
132
+ # that the attribute can take a number which is equal to the given value
133
+ # and cannot take a number which is not equal.
134
+ #
135
+ # class Person
136
+ # include ActiveModel::Model
137
+ # attr_accessor :weight
138
+ #
139
+ # validates_numericality_of :weight, equal_to: 150
140
+ # end
141
+ #
142
+ # # RSpec
143
+ # RSpec.describe Person, type: :model do
144
+ # it { should validate_numericality_of(:weight).is_equal_to(150) }
145
+ # end
146
+ #
147
+ # # Minitest (Shoulda)
148
+ # class PersonTest < ActiveSupport::TestCase
149
+ # should validate_numericality_of(:weight).is_equal_to(150)
150
+ # end
151
+ #
152
+ # ##### is_greater_than_or_equal_to
153
+ #
154
+ # Use `is_greater_than_or_equal_to` to test usage of the
155
+ # `:greater_than_or_equal_to` option. This asserts that the attribute can
156
+ # take a number which is greater than or equal to the given value and
157
+ # cannot take a number which is less than it.
158
+ #
159
+ # class Person
160
+ # include ActiveModel::Model
161
+ # attr_accessor :height
162
+ #
163
+ # validates_numericality_of :height, greater_than_or_equal_to: 55
164
+ # end
165
+ #
166
+ # # RSpec
167
+ # RSpec.describe Person, type: :model do
168
+ # it do
169
+ # should validate_numericality_of(:height).
170
+ # is_greater_than_or_equal_to(55)
171
+ # end
172
+ # end
173
+ #
174
+ # # Minitest (Shoulda)
175
+ # class PersonTest < ActiveSupport::TestCase
176
+ # should validate_numericality_of(:height).
177
+ # is_greater_than_or_equal_to(55)
178
+ # end
179
+ #
180
+ # ##### is_greater_than
181
+ #
182
+ # Use `is_greater_than` to test usage of the `:greater_than` option.
183
+ # This asserts that the attribute can take a number which is greater than
184
+ # the given value and cannot take a number less than or equal to it.
185
+ #
186
+ # class Person
187
+ # include ActiveModel::Model
188
+ # attr_accessor :legal_age
189
+ #
190
+ # validates_numericality_of :legal_age, greater_than: 21
191
+ # end
192
+ #
193
+ # # RSpec
194
+ # RSpec.describe Person, type: :model do
195
+ # it do
196
+ # should validate_numericality_of(:legal_age).
197
+ # is_greater_than(21)
198
+ # end
199
+ # end
200
+ #
201
+ # # Minitest (Shoulda)
202
+ # class PersonTest < ActiveSupport::TestCase
203
+ # should validate_numericality_of(:legal_age).
204
+ # is_greater_than(21)
205
+ # end
206
+ #
207
+ # ##### is_other_than
208
+ #
209
+ # Use `is_other_than` to test usage of the `:other_than` option.
210
+ # This asserts that the attribute can take a number which is not equal to
211
+ # the given value.
212
+ #
213
+ # class Person
214
+ # include ActiveModel::Model
215
+ # attr_accessor :legal_age
216
+ #
217
+ # validates_numericality_of :legal_age, other_than: 21
218
+ # end
219
+ #
220
+ # # RSpec
221
+ # RSpec.describe Person, type: :model do
222
+ # it do
223
+ # should validate_numericality_of(:legal_age).
224
+ # is_other_than(21)
225
+ # end
226
+ # end
227
+ #
228
+ # # Minitest (Shoulda)
229
+ # class PersonTest < ActiveSupport::TestCase
230
+ # should validate_numericality_of(:legal_age).
231
+ # is_other_than(21)
232
+ # end
233
+ #
234
+ # ##### even
235
+ #
236
+ # Use `even` to test usage of the `:even` option. This asserts that the
237
+ # attribute can take odd numbers and cannot take even ones.
238
+ #
239
+ # class Person
240
+ # include ActiveModel::Model
241
+ # attr_accessor :birth_month
242
+ #
243
+ # validates_numericality_of :birth_month, even: true
244
+ # end
245
+ #
246
+ # # RSpec
247
+ # RSpec.describe Person, type: :model do
248
+ # it { should validate_numericality_of(:birth_month).even }
249
+ # end
250
+ #
251
+ # # Minitest (Shoulda)
252
+ # class PersonTest < ActiveSupport::TestCase
253
+ # should validate_numericality_of(:birth_month).even
254
+ # end
255
+ #
256
+ # ##### odd
257
+ #
258
+ # Use `odd` to test usage of the `:odd` option. This asserts that the
259
+ # attribute can take a number which is odd and cannot take a number which
260
+ # is even.
261
+ #
262
+ # class Person
263
+ # include ActiveModel::Model
264
+ # attr_accessor :birth_day
265
+ #
266
+ # validates_numericality_of :birth_day, odd: true
267
+ # end
268
+ #
269
+ # # RSpec
270
+ # RSpec.describe Person, type: :model do
271
+ # it { should validate_numericality_of(:birth_day).odd }
272
+ # end
273
+ #
274
+ # # Minitest (Shoulda)
275
+ # class PersonTest < ActiveSupport::TestCase
276
+ # should validate_numericality_of(:birth_day).odd
277
+ # end
278
+ #
279
+ # ##### is_in
280
+ #
281
+ # Use `is_in` to test usage of the `:in` option.
282
+ # This asserts that the attribute can take a number which is contained
283
+ # in the given range.
284
+ #
285
+ # class Person
286
+ # include ActiveModel::Model
287
+ # attr_accessor :legal_age
288
+ #
289
+ # validates_numericality_of :birth_month, in: 1..12
290
+ # end
291
+ #
292
+ # # RSpec
293
+ # RSpec.describe Person, type: :model do
294
+ # it do
295
+ # should validate_numericality_of(:birth_month).
296
+ # is_in(1..12)
297
+ # end
298
+ # end
299
+ #
300
+ # # Minitest (Shoulda)
301
+ # class PersonTest < ActiveSupport::TestCase
302
+ # should validate_numericality_of(:birth_month).
303
+ # is_in(1..12)
304
+ # end
305
+ #
306
+ # ##### with_message
307
+ #
308
+ # Use `with_message` if you are using a custom validation message.
309
+ #
310
+ # class Person
311
+ # include ActiveModel::Model
312
+ # attr_accessor :number_of_dependents
313
+ #
314
+ # validates_numericality_of :number_of_dependents,
315
+ # message: 'Number of dependents must be a number'
316
+ # end
317
+ #
318
+ # # RSpec
319
+ # RSpec.describe Person, type: :model do
320
+ # it do
321
+ # should validate_numericality_of(:number_of_dependents).
322
+ # with_message('Number of dependents must be a number')
323
+ # end
324
+ # end
325
+ #
326
+ # # Minitest (Shoulda)
327
+ # class PersonTest < ActiveSupport::TestCase
328
+ # should validate_numericality_of(:number_of_dependents).
329
+ # with_message('Number of dependents must be a number')
330
+ # end
331
+ #
332
+ # ##### allow_nil
333
+ #
334
+ # Use `allow_nil` to assert that the attribute allows nil.
335
+ #
336
+ # class Post
337
+ # include ActiveModel::Model
338
+ # attr_accessor :age
339
+ #
340
+ # validates_numericality_of :age, allow_nil: true
341
+ # end
342
+ #
343
+ # # RSpec
344
+ # RSpec.describe Post, type: :model do
345
+ # it { should validate_numericality_of(:age).allow_nil }
346
+ # end
347
+ #
348
+ # # Minitest (Shoulda)
349
+ # class PostTest < ActiveSupport::TestCase
350
+ # should validate_numericality_of(:age).allow_nil
351
+ # end
352
+ #
353
+ # #### Multiple attributes
354
+ #
355
+ # You can pass multiple attributes to assert that each one has the
356
+ # validation. Any qualifier chained on the matcher is applied to
357
+ # every attribute uniformly.
358
+ #
359
+ # class Item
360
+ # include ActiveModel::Model
361
+ # attr_accessor :price, :quantity
362
+ #
363
+ # validates_numericality_of :price, :quantity
364
+ # end
365
+ #
366
+ # # RSpec
367
+ # RSpec.describe Item, type: :model do
368
+ # it { should validate_numericality_of(:price, :quantity) }
369
+ # end
370
+ #
371
+ # # Minitest (Shoulda)
372
+ # class ItemTest < ActiveSupport::TestCase
373
+ # should validate_numericality_of(:price, :quantity)
374
+ # end
375
+ #
376
+ # @return [ValidateNumericalityOfMatcher]
377
+ #
378
+ def validate_numericality_of(*attrs)
379
+ MatcherCollection.build(attrs) { |attr| ValidateNumericalityOfMatcher.new(attr) }
380
+ end
381
+
382
+ # @private
383
+ class ValidateNumericalityOfMatcher < ValidationMatcher
384
+ NUMERIC_NAME = 'number'.freeze
385
+ DEFAULT_DIFF_TO_COMPARE = 1
386
+
387
+ attr_reader :diff_to_compare
388
+
389
+ def initialize(attribute)
390
+ super
391
+ @submatchers = []
392
+ @diff_to_compare = DEFAULT_DIFF_TO_COMPARE
393
+ @expects_to_allow_nil = false
394
+ @allowed_type_adjective = nil
395
+ @allowed_type_name = 'number'
396
+
397
+ add_disallow_non_numeric_value_matcher
398
+ end
399
+
400
+ def only_integer
401
+ prepare_submatcher(
402
+ NumericalityMatchers::OnlyIntegerMatcher.new(self, attribute),
403
+ )
404
+ self
405
+ end
406
+
407
+ def allow_nil
408
+ @expects_to_allow_nil = true
409
+ prepare_submatcher(allow_value_matcher(nil, :not_a_number))
410
+ self
411
+ end
412
+
413
+ def expects_to_allow_nil?
414
+ @expects_to_allow_nil
415
+ end
416
+
417
+ def odd
418
+ prepare_submatcher(
419
+ NumericalityMatchers::OddNumberMatcher.new(self, attribute),
420
+ )
421
+ self
422
+ end
423
+
424
+ def even
425
+ prepare_submatcher(
426
+ NumericalityMatchers::EvenNumberMatcher.new(self, attribute),
427
+ )
428
+ self
429
+ end
430
+
431
+ def is_greater_than(value)
432
+ prepare_submatcher(comparison_matcher_for(value, :>).for(attribute))
433
+ self
434
+ end
435
+
436
+ def is_greater_than_or_equal_to(value)
437
+ prepare_submatcher(comparison_matcher_for(value, :>=).for(attribute))
438
+ self
439
+ end
440
+
441
+ def is_equal_to(value)
442
+ prepare_submatcher(comparison_matcher_for(value, :==).for(attribute))
443
+ self
444
+ end
445
+
446
+ def is_less_than(value)
447
+ prepare_submatcher(comparison_matcher_for(value, :<).for(attribute))
448
+ self
449
+ end
450
+
451
+ def is_less_than_or_equal_to(value)
452
+ prepare_submatcher(comparison_matcher_for(value, :<=).for(attribute))
453
+ self
454
+ end
455
+
456
+ def is_other_than(value)
457
+ prepare_submatcher(comparison_matcher_for(value, :!=).for(attribute))
458
+ self
459
+ end
460
+
461
+ def is_in(range)
462
+ prepare_submatcher(
463
+ NumericalityMatchers::RangeMatcher.new(self, attribute, range),
464
+ )
465
+ self
466
+ end
467
+
468
+ def matches?(subject)
469
+ matches_or_does_not_match?(subject)
470
+ first_submatcher_that_fails_to_match.nil?
471
+ end
472
+
473
+ def does_not_match?(subject)
474
+ matches_or_does_not_match?(subject)
475
+ first_submatcher_that_fails_to_not_match.nil?
476
+ end
477
+
478
+ def simple_description
479
+ String.new.tap do |description|
480
+ description << "validate that :#{attribute} looks like "
481
+ description << Shoulda::Matchers::Util.a_or_an(full_allowed_type)
482
+
483
+ if range_description.present?
484
+ description << " #{range_description}"
485
+ end
486
+
487
+ if comparison_descriptions.present?
488
+ description << " #{comparison_descriptions}"
489
+ end
490
+ end
491
+ end
492
+
493
+ def failure_message
494
+ overall_failure_message.dup.tap do |message|
495
+ message << "\n"
496
+ message << failure_message_for_first_submatcher_that_fails_to_match
497
+ end
498
+ end
499
+
500
+ def failure_message_when_negated
501
+ overall_failure_message_when_negated.dup.tap do |message|
502
+ message << "\n"
503
+ message <<
504
+ failure_message_for_first_submatcher_that_fails_to_not_match
505
+ end
506
+ end
507
+
508
+ def failure_reason
509
+ raw_submatcher_failure_reason_for(
510
+ first_submatcher_that_fails_to_match,
511
+ :failure_message,
512
+ )
513
+ end
514
+
515
+ def given_numeric_column?
516
+ attribute_is_active_record_column? &&
517
+ [:integer, :float, :decimal].include?(column_type)
518
+ end
519
+
520
+ private
521
+
522
+ def matches_or_does_not_match?(subject)
523
+ @subject = subject
524
+ @number_of_submatchers = @submatchers.size
525
+
526
+ qualify_submatchers
527
+ end
528
+
529
+ def attribute_is_active_record_column?
530
+ columns_hash.key?(attribute.to_s)
531
+ end
532
+
533
+ def column_type
534
+ columns_hash[attribute.to_s].type
535
+ end
536
+
537
+ def columns_hash
538
+ if subject.class.respond_to?(:columns_hash)
539
+ subject.class.columns_hash
540
+ else
541
+ {}
542
+ end
543
+ end
544
+
545
+ def add_disallow_non_numeric_value_matcher
546
+ disallow_value_matcher = DisallowValueMatcher.
547
+ new(non_numeric_value).
548
+ for(attribute).
549
+ with_message(:not_a_number)
550
+
551
+ add_submatcher(disallow_value_matcher)
552
+ end
553
+
554
+ def prepare_submatcher(submatcher)
555
+ add_submatcher(submatcher)
556
+ submatcher
557
+ end
558
+
559
+ def comparison_matcher_for(value, operator)
560
+ ComparisonMatcher.
561
+ new(self, value, operator).
562
+ for(attribute)
563
+ end
564
+
565
+ def add_submatcher(submatcher)
566
+ if submatcher.respond_to?(:allowed_type_name)
567
+ @allowed_type_name = submatcher.allowed_type_name
568
+ end
569
+
570
+ if submatcher.respond_to?(:allowed_type_adjective)
571
+ @allowed_type_adjective = submatcher.allowed_type_adjective
572
+ end
573
+
574
+ if submatcher.respond_to?(:diff_to_compare)
575
+ @diff_to_compare = [
576
+ @diff_to_compare,
577
+ submatcher.diff_to_compare,
578
+ ].max
579
+ end
580
+
581
+ @submatchers << submatcher
582
+ end
583
+
584
+ def qualify_submatchers
585
+ @submatchers.each do |submatcher|
586
+ if @expects_strict
587
+ submatcher.strict(@expects_strict)
588
+ end
589
+
590
+ if @expected_message.present?
591
+ submatcher.with_message(@expected_message)
592
+ end
593
+
594
+ if context
595
+ submatcher.on(context)
596
+ end
597
+
598
+ submatcher.ignoring_interference_by_writer(
599
+ ignore_interference_by_writer,
600
+ )
601
+ end
602
+ end
603
+
604
+ def number_of_submatchers_for_failure_message
605
+ if has_been_qualified?
606
+ @submatchers.size - 1
607
+ else
608
+ @submatchers.size
609
+ end
610
+ end
611
+
612
+ def has_been_qualified?
613
+ @submatchers.any? { |submatcher| submatcher_qualified?(submatcher) }
614
+ end
615
+
616
+ def submatcher_qualified?(submatcher)
617
+ Shoulda::Matchers::RailsShim.parent_of(submatcher.class) ==
618
+ NumericalityMatchers || submatcher.instance_of?(ComparisonMatcher)
619
+ end
620
+
621
+ def first_submatcher_that_fails_to_match
622
+ @_first_submatcher_that_fails_to_match ||=
623
+ @submatchers.detect do |submatcher|
624
+ !submatcher.matches?(subject)
625
+ end
626
+ end
627
+
628
+ def first_submatcher_that_fails_to_not_match
629
+ @_first_submatcher_that_fails_to_not_match ||=
630
+ @submatchers.detect do |submatcher|
631
+ !submatcher.does_not_match?(subject)
632
+ end
633
+ end
634
+
635
+ def failure_message_for_first_submatcher_that_fails_to_match
636
+ build_submatcher_failure_message_for(
637
+ first_submatcher_that_fails_to_match,
638
+ :failure_message,
639
+ )
640
+ end
641
+
642
+ def failure_message_for_first_submatcher_that_fails_to_not_match
643
+ build_submatcher_failure_message_for(
644
+ first_submatcher_that_fails_to_not_match,
645
+ :failure_message_when_negated,
646
+ )
647
+ end
648
+
649
+ def build_submatcher_failure_message_for(
650
+ submatcher,
651
+ failure_message_method
652
+ )
653
+ Shoulda::Matchers.word_wrap(
654
+ raw_submatcher_failure_reason_for(submatcher, failure_message_method),
655
+ indent: 2,
656
+ )
657
+ end
658
+
659
+ def raw_submatcher_failure_reason_for(submatcher, failure_message_method)
660
+ failure_message = submatcher.public_send(failure_message_method)
661
+ submatcher_description = submatcher.simple_description.
662
+ sub(/\bvalidate that\b/, 'validates').
663
+ sub(/\bdisallow\b/, 'disallows').
664
+ sub(/\ballow\b/, 'allows')
665
+
666
+ if number_of_submatchers_for_failure_message > 1
667
+ "In checking that #{model.name} #{submatcher_description}, " +
668
+ failure_message[0].downcase +
669
+ failure_message[1..]
670
+ else
671
+ failure_message
672
+ end
673
+ end
674
+
675
+ def full_allowed_type
676
+ "#{@allowed_type_adjective} #{@allowed_type_name}".strip
677
+ end
678
+
679
+ def comparison_descriptions
680
+ description_array = submatcher_comparison_descriptions
681
+ if description_array.empty?
682
+ ''
683
+ else
684
+ submatcher_comparison_descriptions.join(' and ')
685
+ end
686
+ end
687
+
688
+ def submatcher_comparison_descriptions
689
+ @submatchers.inject([]) do |arr, submatcher|
690
+ if submatcher.respond_to? :comparison_description
691
+ arr << submatcher.comparison_description
692
+ end
693
+ arr
694
+ end
695
+ end
696
+
697
+ def range_description
698
+ range_submatcher = @submatchers.detect do |submatcher|
699
+ submatcher.respond_to? :range_description
700
+ end
701
+
702
+ range_submatcher&.range_description
703
+ end
704
+
705
+ def non_numeric_value
706
+ 'abcd'
707
+ end
708
+ end
709
+ end
710
+ end
711
+ end