shoulda-matchers 4.0.0.rc1 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +72 -40
  4. data/lib/shoulda/matchers/action_controller.rb +2 -0
  5. data/lib/shoulda/matchers/active_model.rb +2 -3
  6. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +1 -0
  7. data/lib/shoulda/matchers/active_record.rb +2 -0
  8. data/lib/shoulda/matchers/active_record/association_matcher.rb +34 -0
  9. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +27 -4
  10. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +27 -4
  11. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1 -1
  12. data/lib/shoulda/matchers/independent.rb +2 -1
  13. data/lib/shoulda/matchers/rails_shim.rb +5 -9
  14. data/lib/shoulda/matchers/version.rb +1 -1
  15. data/lib/shoulda/matchers/warn.rb +1 -0
  16. data/shoulda-matchers.gemspec +11 -3
  17. metadata +13 -340
  18. data/.gitignore +0 -12
  19. data/.hound.yml +0 -3
  20. data/.hound/ruby.yml +0 -1062
  21. data/.python-version +0 -1
  22. data/.rubocop.yml +0 -15
  23. data/.travis.yml +0 -21
  24. data/.yardopts +0 -10
  25. data/Appraisals +0 -105
  26. data/CONTRIBUTING.md +0 -172
  27. data/Gemfile +0 -15
  28. data/Gemfile.lock +0 -59
  29. data/MAINTAINING.md +0 -250
  30. data/NEWS.md +0 -1235
  31. data/Rakefile +0 -46
  32. data/bin/setup +0 -190
  33. data/custom_plan.rb +0 -104
  34. data/doc_config/gh-pages/index.html.erb +0 -9
  35. data/doc_config/yard/setup.rb +0 -22
  36. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -5967
  37. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +0 -12
  38. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +0 -66
  39. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +0 -69
  40. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +0 -312
  41. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -26
  42. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +0 -1
  43. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +0 -8
  44. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -281
  45. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +0 -1
  46. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +0 -289
  47. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +0 -6
  48. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +0 -35
  49. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +0 -14
  50. data/doc_config/yard/templates/default/layout/html/fonts.erb +0 -1
  51. data/doc_config/yard/templates/default/layout/html/footer.erb +0 -6
  52. data/doc_config/yard/templates/default/layout/html/layout.erb +0 -23
  53. data/doc_config/yard/templates/default/layout/html/search.erb +0 -13
  54. data/doc_config/yard/templates/default/layout/html/setup.rb +0 -40
  55. data/doc_config/yard/templates/default/method_details/html/source.erb +0 -10
  56. data/doc_config/yard/templates/default/module/html/box_info.erb +0 -31
  57. data/gemfiles/4.2.gemfile +0 -39
  58. data/gemfiles/4.2.gemfile.lock +0 -246
  59. data/gemfiles/5.0.gemfile +0 -37
  60. data/gemfiles/5.0.gemfile.lock +0 -238
  61. data/gemfiles/5.1.gemfile +0 -38
  62. data/gemfiles/5.1.gemfile.lock +0 -254
  63. data/gemfiles/5.2.gemfile +0 -40
  64. data/gemfiles/5.2.gemfile.lock +0 -273
  65. data/script/install_gems_in_all_appraisals +0 -16
  66. data/script/run_all_tests +0 -16
  67. data/script/supported_ruby_versions +0 -7
  68. data/script/update_gem_in_all_appraisals +0 -17
  69. data/script/update_gems_in_all_appraisals +0 -16
  70. data/spec/acceptance/active_model_integration_spec.rb +0 -23
  71. data/spec/acceptance/independent_matchers_spec.rb +0 -125
  72. data/spec/acceptance/multiple_libraries_integration_spec.rb +0 -55
  73. data/spec/acceptance/rails_integration_spec.rb +0 -156
  74. data/spec/acceptance_spec_helper.rb +0 -23
  75. data/spec/doublespeak_spec_helper.rb +0 -2
  76. data/spec/report_warnings.rb +0 -7
  77. data/spec/spec_helper.rb +0 -20
  78. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +0 -133
  79. data/spec/support/acceptance/helpers.rb +0 -33
  80. data/spec/support/acceptance/helpers/active_model_helpers.rb +0 -11
  81. data/spec/support/acceptance/helpers/array_helpers.rb +0 -13
  82. data/spec/support/acceptance/helpers/base_helpers.rb +0 -19
  83. data/spec/support/acceptance/helpers/command_helpers.rb +0 -68
  84. data/spec/support/acceptance/helpers/file_helpers.rb +0 -19
  85. data/spec/support/acceptance/helpers/gem_helpers.rb +0 -31
  86. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -11
  87. data/spec/support/acceptance/helpers/n_unit_helpers.rb +0 -25
  88. data/spec/support/acceptance/helpers/pluralization_helpers.rb +0 -13
  89. data/spec/support/acceptance/helpers/rails_migration_helpers.rb +0 -21
  90. data/spec/support/acceptance/helpers/rails_version_helpers.rb +0 -11
  91. data/spec/support/acceptance/helpers/rspec_helpers.rb +0 -24
  92. data/spec/support/acceptance/helpers/ruby_version_helpers.rb +0 -9
  93. data/spec/support/acceptance/helpers/step_helpers.rb +0 -127
  94. data/spec/support/acceptance/matchers/have_output.rb +0 -31
  95. data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +0 -55
  96. data/spec/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +0 -103
  97. data/spec/support/tests/bundle.rb +0 -94
  98. data/spec/support/tests/command_runner.rb +0 -230
  99. data/spec/support/tests/current_bundle.rb +0 -55
  100. data/spec/support/tests/database.rb +0 -28
  101. data/spec/support/tests/database_adapters/postgresql.rb +0 -25
  102. data/spec/support/tests/database_adapters/sqlite3.rb +0 -26
  103. data/spec/support/tests/database_configuration.rb +0 -33
  104. data/spec/support/tests/database_configuration_registry.rb +0 -28
  105. data/spec/support/tests/filesystem.rb +0 -100
  106. data/spec/support/tests/version.rb +0 -45
  107. data/spec/support/unit/active_record/create_table.rb +0 -54
  108. data/spec/support/unit/attribute.rb +0 -45
  109. data/spec/support/unit/capture.rb +0 -46
  110. data/spec/support/unit/change_value.rb +0 -111
  111. data/spec/support/unit/create_model_arguments/basic.rb +0 -135
  112. data/spec/support/unit/create_model_arguments/has_many.rb +0 -15
  113. data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +0 -74
  114. data/spec/support/unit/helpers/action_pack_versions.rb +0 -22
  115. data/spec/support/unit/helpers/active_model_helpers.rb +0 -27
  116. data/spec/support/unit/helpers/active_model_versions.rb +0 -32
  117. data/spec/support/unit/helpers/active_record_versions.rb +0 -44
  118. data/spec/support/unit/helpers/active_resource_builder.rb +0 -27
  119. data/spec/support/unit/helpers/allow_value_matcher_helpers.rb +0 -15
  120. data/spec/support/unit/helpers/class_builder.rb +0 -90
  121. data/spec/support/unit/helpers/column_type_helpers.rb +0 -26
  122. data/spec/support/unit/helpers/confirmation_matcher_helpers.rb +0 -17
  123. data/spec/support/unit/helpers/controller_builder.rb +0 -63
  124. data/spec/support/unit/helpers/database_helpers.rb +0 -20
  125. data/spec/support/unit/helpers/i18n_faker.rb +0 -15
  126. data/spec/support/unit/helpers/mailer_builder.rb +0 -12
  127. data/spec/support/unit/helpers/message_helpers.rb +0 -19
  128. data/spec/support/unit/helpers/model_builder.rb +0 -114
  129. data/spec/support/unit/helpers/rails_versions.rb +0 -42
  130. data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +0 -44
  131. data/spec/support/unit/i18n.rb +0 -7
  132. data/spec/support/unit/load_environment.rb +0 -12
  133. data/spec/support/unit/matchers/deprecate.rb +0 -60
  134. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +0 -51
  135. data/spec/support/unit/matchers/fail_with_message_matcher.rb +0 -64
  136. data/spec/support/unit/matchers/print_warning_including.rb +0 -67
  137. data/spec/support/unit/model_creation_strategies/active_model.rb +0 -111
  138. data/spec/support/unit/model_creation_strategies/active_record.rb +0 -77
  139. data/spec/support/unit/model_creators.rb +0 -19
  140. data/spec/support/unit/model_creators/active_model.rb +0 -39
  141. data/spec/support/unit/model_creators/active_record.rb +0 -42
  142. data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +0 -95
  143. data/spec/support/unit/model_creators/active_record/has_many.rb +0 -67
  144. data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +0 -42
  145. data/spec/support/unit/model_creators/basic.rb +0 -102
  146. data/spec/support/unit/rails_application.rb +0 -151
  147. data/spec/support/unit/record_builder_with_i18n_validation_message.rb +0 -69
  148. data/spec/support/unit/record_validating_confirmation_builder.rb +0 -54
  149. data/spec/support/unit/record_with_different_error_attribute_builder.rb +0 -92
  150. data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +0 -79
  151. data/spec/support/unit/shared_examples/numerical_submatcher.rb +0 -17
  152. data/spec/support/unit/shared_examples/set_session_or_flash.rb +0 -360
  153. data/spec/support/unit/validation_matcher_scenario.rb +0 -60
  154. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +0 -82
  155. data/spec/unit/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +0 -28
  156. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +0 -629
  157. data/spec/unit/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +0 -42
  158. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +0 -76
  159. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +0 -62
  160. data/spec/unit/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +0 -90
  161. data/spec/unit/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +0 -31
  162. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +0 -330
  163. data/spec/unit/shoulda/matchers/action_controller/route_params_spec.rb +0 -30
  164. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +0 -67
  165. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +0 -17
  166. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +0 -562
  167. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -117
  168. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +0 -829
  169. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -86
  170. data/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +0 -20
  171. data/spec/unit/shoulda/matchers/active_model/helpers_spec.rb +0 -162
  172. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +0 -290
  173. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +0 -109
  174. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +0 -172
  175. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -264
  176. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -1049
  177. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -335
  178. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +0 -1865
  179. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -406
  180. data/spec/unit/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -107
  181. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +0 -1672
  182. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +0 -251
  183. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +0 -690
  184. data/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +0 -111
  185. data/spec/unit/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +0 -85
  186. data/spec/unit/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +0 -41
  187. data/spec/unit/shoulda/matchers/active_record/have_secure_token_matcher_spec.rb +0 -169
  188. data/spec/unit/shoulda/matchers/active_record/serialize_matcher_spec.rb +0 -86
  189. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +0 -1682
  190. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +0 -190
  191. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +0 -21
  192. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +0 -271
  193. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +0 -77
  194. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +0 -72
  195. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +0 -101
  196. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +0 -78
  197. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +0 -27
  198. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher/stubbed_target_spec.rb +0 -43
  199. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +0 -650
  200. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +0 -406
  201. data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +0 -252
  202. data/spec/unit_spec_helper.rb +0 -54
  203. data/spec/warnings_spy.rb +0 -64
  204. data/spec/warnings_spy/filesystem.rb +0 -45
  205. data/spec/warnings_spy/partitioner.rb +0 -36
  206. data/spec/warnings_spy/reader.rb +0 -53
  207. data/spec/warnings_spy/reporter.rb +0 -88
  208. data/tasks/documentation.rb +0 -199
  209. data/zeus.json +0 -11
@@ -1,1682 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveRecord::ValidateUniquenessOfMatcher, type: :model do
4
- shared_context 'it supports scoped attributes of a certain type' do |options = {}|
5
- column_type = options.fetch(:column_type)
6
- value_type = options.fetch(:value_type, column_type)
7
- array = options.fetch(:array, false)
8
-
9
- context 'when the correct scope is specified' do
10
- context 'when the subject is a new record' do
11
- it 'accepts' do
12
- record = build_record_validating_uniqueness(
13
- scopes: [
14
- build_attribute(name: :scope1),
15
- { name: :scope2 }
16
- ]
17
- )
18
- expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
19
- end
20
-
21
- it 'still accepts if the scope is unset beforehand' do
22
- record = build_record_validating_uniqueness(
23
- scopes: [ build_attribute(name: :scope, value: nil) ]
24
- )
25
-
26
- expect(record).to validate_uniqueness.scoped_to(:scope)
27
- end
28
- end
29
-
30
- context 'when the subject is an existing record' do
31
- it 'accepts' do
32
- record = create_record_validating_uniqueness(
33
- scopes: [
34
- build_attribute(name: :scope1),
35
- { name: :scope2 }
36
- ]
37
- )
38
-
39
- expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
40
- end
41
-
42
- it 'still accepts if the scope is unset beforehand' do
43
- record = create_record_validating_uniqueness(
44
- scopes: [ build_attribute(name: :scope, value: nil) ]
45
- )
46
-
47
- expect(record).to validate_uniqueness.scoped_to(:scope)
48
- end
49
- end
50
- end
51
-
52
- context "when more than one record exists that has the next version of the attribute's value" do
53
- it 'accepts' do
54
- value1 = dummy_value_for(value_type, array: array)
55
- value2 = next_version_of(value1, value_type)
56
- value3 = next_version_of(value2, value_type)
57
- model = define_model_validating_uniqueness(
58
- scopes: [ build_attribute(name: :scope) ]
59
- )
60
- create_record_from(model, scope: value2)
61
- create_record_from(model, scope: value3)
62
- record = build_record_from(model, scope: value1)
63
-
64
- expect(record).to validate_uniqueness.scoped_to(:scope)
65
- end
66
- end
67
-
68
- context 'when too narrow of a scope is specified' do
69
- it 'rejects with an appropriate failure message' do
70
- record = build_record_validating_uniqueness(
71
- scopes: [
72
- build_attribute(name: :scope1),
73
- build_attribute(name: :scope2)
74
- ],
75
- additional_attributes: [:other]
76
- )
77
-
78
- assertion = lambda do
79
- expect(record).
80
- to validate_uniqueness.
81
- scoped_to(:scope1, :scope2, :other)
82
- end
83
-
84
- message = <<-MESSAGE
85
- Expected Example to validate that :attr is case-sensitively unique
86
- within the scope of :scope1, :scope2, and :other, but this could not be
87
- proved.
88
- Expected the validation to be scoped to :scope1, :scope2, and :other,
89
- but it was scoped to :scope1 and :scope2 instead.
90
- MESSAGE
91
-
92
- expect(&assertion).to fail_with_message(message)
93
- end
94
- end
95
-
96
- context 'when too broad of a scope is specified' do
97
- it 'rejects with an appropriate failure message' do
98
- record = build_record_validating_uniqueness(
99
- scopes: [
100
- build_attribute(name: :scope1),
101
- build_attribute(name: :scope2)
102
- ],
103
- )
104
-
105
- assertion = lambda do
106
- expect(record).
107
- to validate_uniqueness.
108
- scoped_to(:scope1)
109
- end
110
-
111
- message = <<-MESSAGE
112
- Expected Example to validate that :attr is case-sensitively unique
113
- within the scope of :scope1, but this could not be proved.
114
- Expected the validation to be scoped to :scope1, but it was scoped to
115
- :scope1 and :scope2 instead.
116
- MESSAGE
117
-
118
- expect(&assertion).to fail_with_message(message)
119
- end
120
- end
121
-
122
- context 'when a different scope is specified' do
123
- it 'rejects with an appropriate failure message' do
124
- record = build_record_validating_uniqueness(
125
- scopes: [ build_attribute(name: :other) ],
126
- additional_attributes: [:scope]
127
- )
128
- assertion = lambda do
129
- expect(record).
130
- to validate_uniqueness.
131
- scoped_to(:scope)
132
- end
133
-
134
- message = <<-MESSAGE
135
- Expected Example to validate that :attr is case-sensitively unique
136
- within the scope of :scope, but this could not be proved.
137
- Expected the validation to be scoped to :scope, but it was scoped to
138
- :other instead.
139
- MESSAGE
140
-
141
- expect(&assertion).to fail_with_message(message)
142
- end
143
- end
144
-
145
- context 'when no scope is specified' do
146
- it 'rejects with an appropriate failure message' do
147
- record = build_record_validating_uniqueness(
148
- scopes: [ build_attribute(name: :scope) ]
149
- )
150
-
151
- assertion = lambda do
152
- expect(record).to validate_uniqueness
153
- end
154
-
155
- message = <<-MESSAGE
156
- Expected Example to validate that :attr is case-sensitively unique, but
157
- this could not be proved.
158
- Expected the validation not to be scoped to anything, but it was
159
- scoped to :scope instead.
160
- MESSAGE
161
-
162
- expect(&assertion).to fail_with_message(message)
163
- end
164
-
165
- context 'if the scope attribute is unset in the record given to the matcher' do
166
- it 'rejects with an appropriate failure message' do
167
- record = build_record_validating_uniqueness(
168
- scopes: [ build_attribute(name: :scope, value: nil) ]
169
- )
170
-
171
- assertion = lambda do
172
- expect(record).to validate_uniqueness
173
- end
174
-
175
- message = <<-MESSAGE
176
- Expected Example to validate that :attr is case-sensitively unique, but
177
- this could not be proved.
178
- Expected the validation not to be scoped to anything, but it was
179
- scoped to :scope instead.
180
- MESSAGE
181
-
182
- expect(&assertion).to fail_with_message(message)
183
- end
184
- end
185
- end
186
-
187
- context 'when a non-existent attribute is specified as a scope' do
188
- context 'when there is more than one scope' do
189
- it 'rejects with an appropriate failure message (and does not raise an error)' do
190
- record = build_record_validating_uniqueness(
191
- scopes: [ build_attribute(name: :scope) ]
192
- )
193
-
194
- assertion = lambda do
195
- expect(record).to validate_uniqueness.scoped_to(:non_existent)
196
- end
197
-
198
- message = <<-MESSAGE.strip
199
- Expected Example to validate that :attr is case-sensitively unique
200
- within the scope of :non_existent, but this could not be proved.
201
- :non_existent does not seem to be an attribute on Example.
202
- MESSAGE
203
-
204
- expect(&assertion).to fail_with_message(message)
205
- end
206
- end
207
-
208
- context 'when there is more than one scope' do
209
- it 'rejects with an appropriate failure message (and does not raise an error)' do
210
- record = build_record_validating_uniqueness(
211
- scopes: [ build_attribute(name: :scope) ]
212
- )
213
-
214
- assertion = lambda do
215
- expect(record).to validate_uniqueness.scoped_to(
216
- :non_existent1,
217
- :non_existent2
218
- )
219
- end
220
-
221
- message = <<-MESSAGE.strip
222
- Expected Example to validate that :attr is case-sensitively unique
223
- within the scope of :non_existent1 and :non_existent2, but this could
224
- not be proved.
225
- :non_existent1 and :non_existent2 do not seem to be attributes on
226
- Example.
227
- MESSAGE
228
-
229
- expect(&assertion).to fail_with_message(message)
230
- end
231
- end
232
- end
233
-
234
- context 'when there is more than one validation on the same attribute with different scopes' do
235
- context 'when a record exists beforehand, where all scopes are set' do
236
- if column_type != :boolean
237
- context 'when each validation has the same (default) message' do
238
- it 'accepts' do
239
- pending 'this needs another qualifier to properly fix'
240
-
241
- model = define_model(
242
- 'Example',
243
- attribute_name => :string,
244
- scope1: column_type,
245
- scope2: column_type
246
- ) do |m|
247
- m.validates_uniqueness_of(attribute_name, scope: [:scope1])
248
- m.validates_uniqueness_of(attribute_name, scope: [:scope2])
249
- end
250
-
251
- model.create!(
252
- attribute_name => dummy_value_for(:string),
253
- scope1: dummy_value_for(column_type),
254
- scope2: dummy_value_for(column_type)
255
- )
256
-
257
- expect(model.new).to validate_uniqueness.scoped_to(:scope1)
258
- expect(model.new).to validate_uniqueness.scoped_to(:scope2)
259
- end
260
- end
261
- end
262
-
263
- context 'when each validation has a different message' do
264
- it 'accepts' do
265
- model = define_model(
266
- 'Example',
267
- attribute_name => :string,
268
- scope1: column_type,
269
- scope2: column_type
270
- ) do |m|
271
- m.validates_uniqueness_of(
272
- attribute_name,
273
- scope: [:scope1],
274
- message: 'first message'
275
- )
276
- m.validates_uniqueness_of(
277
- attribute_name,
278
- scope: [:scope2],
279
- message: 'second message'
280
- )
281
- end
282
-
283
- model.create!(
284
- attribute_name => dummy_value_for(:string),
285
- scope1: dummy_value_for(column_type),
286
- scope2: dummy_value_for(column_type)
287
- )
288
-
289
- expect(model.new).
290
- to validate_uniqueness.
291
- scoped_to(:scope1).
292
- with_message('first message')
293
-
294
- expect(model.new).
295
- to validate_uniqueness.
296
- scoped_to(:scope2).
297
- with_message('second message')
298
- end
299
- end
300
- end
301
-
302
- context 'when no record exists beforehand' do
303
- it 'accepts' do
304
- pending 'this needs another qualifier to properly fix'
305
-
306
- model = define_model(
307
- 'Example',
308
- attribute_name => :string,
309
- scope1: column_type,
310
- scope2: column_type
311
- ) do |m|
312
- m.validates_uniqueness_of(attribute_name, scope: [:scope1])
313
- m.validates_uniqueness_of(attribute_name, scope: [:scope2])
314
- end
315
-
316
- expect(model.new).to validate_uniqueness.scoped_to(:scope1)
317
- expect(model.new).to validate_uniqueness.scoped_to(:scope2)
318
- end
319
- end
320
- end
321
-
322
- define_method(:build_attribute) do |attribute_options|
323
- attribute_options.deep_merge(
324
- column_type: column_type,
325
- value_type: value_type,
326
- options: { array: array }
327
- )
328
- end
329
- end
330
-
331
- context 'when the model does not have a uniqueness validation' do
332
- it 'rejects with an appropriate failure message' do
333
- model = define_model_without_validation
334
- model.create!(attribute_name => 'value')
335
-
336
- assertion = lambda do
337
- expect(model.new).to validate_uniqueness_of(attribute_name)
338
- end
339
-
340
- message = <<-MESSAGE
341
- Expected Example to validate that :attr is case-sensitively unique, but
342
- this could not be proved.
343
- Given an existing Example whose :attr is ‹"value"›, after making a new
344
- Example and setting its :attr to ‹"value"› as well, the matcher
345
- expected the new Example to be invalid, but it was valid instead.
346
- MESSAGE
347
-
348
- expect(&assertion).to fail_with_message(message)
349
- end
350
- end
351
-
352
- context 'when the model has a uniqueness validation' do
353
- context 'when the attribute has a character limit' do
354
- it 'accepts' do
355
- record = build_record_validating_uniqueness(
356
- attribute_type: :string,
357
- attribute_options: { limit: 1 }
358
- )
359
-
360
- expect(record).to validate_uniqueness
361
- end
362
- end
363
-
364
- context 'when the attribute is of integer type' do
365
- it 'accepts' do
366
- record = build_record_validating_uniqueness(
367
- attribute_type: :integer,
368
- attribute_options: { limit: 4 },
369
- )
370
-
371
- expect(record).to validate_uniqueness
372
- end
373
- end
374
-
375
- context 'when the existing record was created beforehand' do
376
- context 'when the subject is a new record' do
377
- it 'accepts' do
378
- create_record_validating_uniqueness
379
- expect(new_record_validating_uniqueness).
380
- to validate_uniqueness
381
- end
382
- end
383
-
384
- context 'when the subject is itself the existing record' do
385
- it 'accepts' do
386
- expect(existing_record_validating_uniqueness).to validate_uniqueness
387
- end
388
- end
389
- end
390
-
391
- context 'when the existing record was not created beforehand' do
392
- context 'and the subject is empty' do
393
- context 'and the attribute being tested is required' do
394
- it 'can save the subject without the attribute being set' do
395
- options = { attribute_name: :attr }
396
- model = define_model_validating_uniqueness(options) do |m|
397
- m.validates_presence_of :attr
398
- end
399
-
400
- record = model.new
401
-
402
- expect(record).to validate_uniqueness
403
- end
404
- end
405
-
406
- context 'and the attribute being tested are required along with other attributes' do
407
- it 'can save the subject without the attributes being set' do
408
- options = {
409
- attribute_name: :attr,
410
- additional_attributes: [:required_attribute]
411
- }
412
- model = define_model_validating_uniqueness(options) do |m|
413
- m.validates_presence_of :attr
414
- m.validates_presence_of :required_attribute
415
- end
416
-
417
- expect(model.new).to validate_uniqueness
418
- end
419
- end
420
-
421
- context 'and the attribute being tested has other validations on it' do
422
- it 'can save the subject without it being completely valid' do
423
- options = { attribute_name: :attr }
424
-
425
- model = define_model_validating_uniqueness(options) do |m|
426
- m.validates_presence_of :attr
427
- m.validates_numericality_of :attr
428
- end
429
-
430
- expect(model.new).to validate_uniqueness
431
- end
432
- end
433
-
434
- context 'and the table has non-nullable columns other than the attribute being validated' do
435
- context 'which are set beforehand' do
436
- it 'can save the subject' do
437
- options = {
438
- additional_attributes: [
439
- { name: :required_attribute, options: { null: false } }
440
- ]
441
- }
442
- model = define_model_validating_uniqueness(options)
443
- record = model.new
444
- record.required_attribute = 'something'
445
-
446
- expect(record).to validate_uniqueness
447
- end
448
- end
449
-
450
- context 'which are not set beforehand' do
451
- it 'raises a useful exception' do
452
- options = {
453
- additional_attributes: [
454
- { name: :required_attribute, options: { null: false } }
455
- ]
456
- }
457
- model = define_model_validating_uniqueness(options)
458
-
459
- assertion = lambda do
460
- expect(model.new).to validate_uniqueness
461
- end
462
-
463
- expect(&assertion).to raise_error(
464
- described_class::ExistingRecordInvalid
465
- )
466
- end
467
- end
468
- end
469
-
470
- context 'and the model has required attributes other than the attribute being validated' do
471
- it 'can save the subject without the attributes being set' do
472
- options = {
473
- additional_attributes: [:required_attribute]
474
- }
475
- model = define_model_validating_uniqueness(options) do |m|
476
- m.validates_presence_of :required_attribute
477
- end
478
-
479
- expect(model.new).to validate_uniqueness
480
- end
481
- end
482
- end
483
-
484
- context 'and the subject is not empty' do
485
- it 'creates the record automatically from the subject' do
486
- model = define_model_validating_uniqueness
487
- assertion = -> {
488
- record = build_record_from(model)
489
- expect(record).to validate_uniqueness
490
- }
491
- expect(&assertion).to change(model, :count).from(0).to(1)
492
- end
493
-
494
- context 'and the table has required attributes other than the attribute being validated, set beforehand' do
495
- it 'can save the subject' do
496
- options = {
497
- additional_attributes: [
498
- { name: :required_attribute, options: { null: false } }
499
- ]
500
- }
501
- model = define_model_validating_uniqueness(options)
502
-
503
- record = build_record_from(model, required_attribute: 'something')
504
- expect(record).to validate_uniqueness
505
- end
506
- end
507
-
508
- context 'and the model has required attributes other than the attribute being validated, set beforehand' do
509
- it 'can save the subject' do
510
- options = {
511
- additional_attributes: [:required_attribute]
512
- }
513
- model = define_model_validating_uniqueness(options) do |m|
514
- m.validates_presence_of :required_attribute
515
- end
516
-
517
- record = build_record_from(model, required_attribute: 'something')
518
- expect(record).to validate_uniqueness
519
- end
520
- end
521
- end
522
- end
523
-
524
- context 'when the validation has no scope and a scope is specified' do
525
- it 'rejects with an appropriate failure message' do
526
- model = define_model_validating_uniqueness(
527
- additional_attributes: [:other]
528
- )
529
- create_record_from(model)
530
- record = build_record_from(model)
531
-
532
- assertion = lambda do
533
- expect(record).to validate_uniqueness.scoped_to(:other)
534
- end
535
-
536
- message = <<-MESSAGE
537
- Expected Example to validate that :attr is case-sensitively unique
538
- within the scope of :other, but this could not be proved.
539
- Expected the validation to be scoped to :other, but it was not scoped
540
- to anything.
541
- MESSAGE
542
-
543
- expect(&assertion).to fail_with_message(message)
544
- end
545
- end
546
-
547
- context 'and the validation has a custom message' do
548
- context 'when no message is specified' do
549
- it 'rejects with an appropriate failure message' do
550
- record = build_record_validating_uniqueness(
551
- attribute_value: 'some value',
552
- validation_options: { message: 'bad value' }
553
- )
554
-
555
- assertion = lambda do
556
- expect(record).to validate_uniqueness
557
- end
558
-
559
- message = <<-MESSAGE
560
- Expected Example to validate that :attr is case-sensitively unique, but
561
- this could not be proved.
562
- After taking the given Example, whose :attr is ‹"some value"›, and
563
- saving it as the existing record, then making a new Example and
564
- setting its :attr to ‹"some value"› as well, the matcher expected the
565
- new Example to be invalid and to produce the validation error "has
566
- already been taken" on :attr. The record was indeed invalid, but it
567
- produced these validation errors instead:
568
-
569
- * attr: ["bad value"]
570
- MESSAGE
571
-
572
- expect(&assertion).to fail_with_message(message)
573
- end
574
- end
575
-
576
- context 'given a string' do
577
- context 'when the given and actual messages do not match' do
578
- it 'rejects with an appropriate failure message' do
579
- record = build_record_validating_uniqueness(
580
- attribute_value: 'some value',
581
- validation_options: { message: 'something else entirely' }
582
- )
583
-
584
- assertion = lambda do
585
- expect(record).
586
- to validate_uniqueness.
587
- with_message('some message')
588
- end
589
-
590
- message = <<-MESSAGE
591
- Expected Example to validate that :attr is case-sensitively unique,
592
- producing a custom validation error on failure, but this could not be
593
- proved.
594
- After taking the given Example, whose :attr is ‹"some value"›, and
595
- saving it as the existing record, then making a new Example and
596
- setting its :attr to ‹"some value"› as well, the matcher expected the
597
- new Example to be invalid and to produce the validation error "some
598
- message" on :attr. The record was indeed invalid, but it produced
599
- these validation errors instead:
600
-
601
- * attr: ["something else entirely"]
602
- MESSAGE
603
-
604
- expect(&assertion).to fail_with_message(message)
605
- end
606
- end
607
-
608
- context 'when the given and actual messages match' do
609
- it 'accepts' do
610
- record = build_record_validating_uniqueness(
611
- validation_options: { message: 'bad value' }
612
- )
613
- expect(record).
614
- to validate_uniqueness.
615
- with_message('bad value')
616
- end
617
- end
618
- end
619
-
620
- context 'given a regex' do
621
- context 'when the given and actual messages do not match' do
622
- it 'rejects with an appropriate failure message' do
623
- record = build_record_validating_uniqueness(
624
- attribute_value: 'some value',
625
- validation_options: { message: 'something else entirely' }
626
- )
627
-
628
- assertion = lambda do
629
- expect(record).
630
- to validate_uniqueness.
631
- with_message(/some message/)
632
- end
633
-
634
- message = <<-MESSAGE
635
- Expected Example to validate that :attr is case-sensitively unique,
636
- producing a custom validation error on failure, but this could not be
637
- proved.
638
- After taking the given Example, whose :attr is ‹"some value"›, and
639
- saving it as the existing record, then making a new Example and
640
- setting its :attr to ‹"some value"› as well, the matcher expected the
641
- new Example to be invalid and to produce a validation error matching
642
- ‹/some message/› on :attr. The record was indeed invalid, but it
643
- produced these validation errors instead:
644
-
645
- * attr: ["something else entirely"]
646
- MESSAGE
647
-
648
- expect(&assertion).to fail_with_message(message)
649
- end
650
- end
651
-
652
- context 'when the given and actual messages match' do
653
- it 'accepts' do
654
- record = build_record_validating_uniqueness(
655
- validation_options: { message: 'bad value' }
656
- )
657
- expect(record).
658
- to validate_uniqueness.
659
- with_message(/bad/)
660
- end
661
- end
662
- end
663
- end
664
-
665
- it_supports(
666
- 'ignoring_interference_by_writer',
667
- tests: {
668
- reject_if_qualified_but_changing_value_interferes: {
669
- model_name: 'Example',
670
- attribute_name: :attr,
671
- default_value: 'some value',
672
- changing_values_with: :next_value,
673
- expected_message: <<-MESSAGE.strip
674
- Expected Example to validate that :attr is case-sensitively unique, but
675
- this could not be proved.
676
- After taking the given Example, whose :attr is ‹"some valuf"›, and
677
- saving it as the existing record, then making a new Example and
678
- setting its :attr to ‹"some valuf"› (read back as ‹"some valug"›) as
679
- well, the matcher expected the new Example to be invalid, but it was
680
- valid instead.
681
-
682
- As indicated in the message above, :attr seems to be changing certain
683
- values as they are set, and this could have something to do with why
684
- this test is failing. If you or something else has overridden the
685
- writer method for this attribute to normalize values by changing their
686
- case in any way (for instance, ensuring that the attribute is always
687
- downcased), then try adding `ignoring_case_sensitivity` onto the end
688
- of the uniqueness matcher. Otherwise, you may need to write the test
689
- yourself, or do something different altogether.
690
-
691
- MESSAGE
692
- }
693
- }
694
- )
695
-
696
- it 'fails when used in the negative' do
697
- assertion = lambda do
698
- record = build_record_validating_uniqueness(
699
- attribute_type: :string,
700
- attribute_options: { limit: 1 }
701
- )
702
-
703
- expect(record).not_to validate_uniqueness
704
- end
705
-
706
- message = <<-MESSAGE
707
- Expected Example not to validate that :attr is case-sensitively unique,
708
- but this could not be proved.
709
- After taking the given Example, setting its :attr to ‹"x"›, and saving
710
- it as the existing record, then making a new Example and setting its
711
- :attr to a different value, ‹"X"›, the matcher expected the new
712
- Example to be invalid, but it was valid instead.
713
- MESSAGE
714
-
715
- expect(&assertion).to fail_with_message(message)
716
- end
717
- end
718
-
719
- context 'when the model has a scoped uniqueness validation' do
720
- context 'when one of the scoped attributes is a string column' do
721
- include_context 'it supports scoped attributes of a certain type',
722
- column_type: :string
723
- end
724
-
725
- context 'when one of the scoped attributes is a boolean column' do
726
- include_context 'it supports scoped attributes of a certain type',
727
- column_type: :boolean
728
- end
729
-
730
- context 'when there is more than one scoped attribute and all are boolean columns' do
731
- it 'accepts when all of the scoped attributes are true' do
732
- record = build_record_validating_uniqueness(
733
- scopes: [
734
- { type: :boolean, name: :scope1, value: true },
735
- { type: :boolean, name: :scope2, value: true }
736
- ]
737
- )
738
- expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
739
- end
740
-
741
- it 'accepts when all the scoped attributes are false' do
742
- record = build_record_validating_uniqueness(
743
- scopes: [
744
- { type: :boolean, name: :scope1, value: false },
745
- { type: :boolean, name: :scope2, value: false }
746
- ]
747
- )
748
- expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
749
- end
750
-
751
- it 'accepts when one of the scoped attributes is true and the other is false' do
752
- record = build_record_validating_uniqueness(
753
- scopes: [
754
- { type: :boolean, name: :scope1, value: true },
755
- { type: :boolean, name: :scope2, value: false }
756
- ]
757
- )
758
- expect(record).to validate_uniqueness.scoped_to(:scope1, :scope2)
759
- end
760
- end
761
-
762
- context 'when one of the scoped attributes is an integer column' do
763
- include_context 'it supports scoped attributes of a certain type',
764
- column_type: :integer
765
-
766
- context 'when one of the scoped attributes is an enum' do
767
- it 'accepts' do
768
- record = build_record_validating_scoped_uniqueness_with_enum(
769
- enum_scope: :scope
770
- )
771
- expect(record).to validate_uniqueness.scoped_to(:scope)
772
- end
773
-
774
- context 'when too narrow of a scope is specified' do
775
- it 'rejects with an appropriate failure message' do
776
- record = build_record_validating_scoped_uniqueness_with_enum(
777
- enum_scope: :scope1,
778
- additional_scopes: [:scope2],
779
- additional_attributes: [:other]
780
- )
781
-
782
- assertion = lambda do
783
- expect(record).
784
- to validate_uniqueness.
785
- scoped_to(:scope1, :scope2, :other)
786
- end
787
-
788
- message = <<-MESSAGE
789
- Expected Example to validate that :attr is case-sensitively unique
790
- within the scope of :scope1, :scope2, and :other, but this could not be
791
- proved.
792
- Expected the validation to be scoped to :scope1, :scope2, and :other,
793
- but it was scoped to :scope1 and :scope2 instead.
794
- MESSAGE
795
-
796
- expect(&assertion).to fail_with_message(message)
797
- end
798
- end
799
-
800
- context 'when too broad of a scope is specified' do
801
- it 'rejects with an appropriate failure message' do
802
- record = build_record_validating_scoped_uniqueness_with_enum(
803
- enum_scope: :scope1,
804
- additional_scopes: [:scope2]
805
- )
806
-
807
- assertion = lambda do
808
- expect(record).to validate_uniqueness.scoped_to(:scope1)
809
- end
810
-
811
- message = <<-MESSAGE
812
- Expected Example to validate that :attr is case-sensitively unique
813
- within the scope of :scope1, but this could not be proved.
814
- Expected the validation to be scoped to :scope1, but it was scoped to
815
- :scope1 and :scope2 instead.
816
- MESSAGE
817
-
818
- expect(&assertion).to fail_with_message(message)
819
- end
820
- end
821
- end
822
- end
823
-
824
- context 'when one of the scoped attributes is a date column' do
825
- include_context 'it supports scoped attributes of a certain type',
826
- column_type: :date
827
- end
828
-
829
- context 'when one of the scoped attributes is a datetime column (using DateTime)' do
830
- include_context 'it supports scoped attributes of a certain type',
831
- column_type: :datetime
832
- end
833
-
834
- context 'when one of the scoped attributes is a datetime column (using Time)' do
835
- include_context 'it supports scoped attributes of a certain type',
836
- column_type: :datetime,
837
- value_type: :time
838
- end
839
-
840
- context 'when one of the scoped attributes is a text column' do
841
- include_context 'it supports scoped attributes of a certain type',
842
- column_type: :text
843
- end
844
-
845
- if database_supports_uuid_columns?
846
- context 'when one of the scoped attributes is a UUID column' do
847
- include_context 'it supports scoped attributes of a certain type',
848
- column_type: :uuid
849
- end
850
- end
851
-
852
- if (
853
- database_supports_array_columns? &&
854
- active_record_supports_array_columns? &&
855
- active_record_uniqueness_supports_array_columns?
856
- )
857
- context 'when one of the scoped attributes is a array-of-string column' do
858
- include_examples 'it supports scoped attributes of a certain type',
859
- column_type: :string,
860
- array: true
861
- end
862
-
863
- context 'when one of the scoped attributes is an array-of-integer column' do
864
- include_examples 'it supports scoped attributes of a certain type',
865
- column_type: :integer,
866
- array: true
867
- end
868
-
869
- context 'when one of the scoped attributes is an array-of-date column' do
870
- include_examples 'it supports scoped attributes of a certain type',
871
- column_type: :date,
872
- array: true
873
- end
874
-
875
- context 'when one of the scoped attributes is an array-of-datetime column (using DateTime)' do
876
- include_examples 'it supports scoped attributes of a certain type',
877
- column_type: :datetime,
878
- array: true
879
- end
880
-
881
- context 'when one of the scoped attributes is an array-of-datetime column (using Time)' do
882
- include_examples 'it supports scoped attributes of a certain type',
883
- column_type: :datetime,
884
- value_type: :time,
885
- array: true
886
- end
887
-
888
- context 'when one of the scoped attributes is an array-of-text column' do
889
- include_examples 'it supports scoped attributes of a certain type',
890
- column_type: :text,
891
- array: true
892
- end
893
- end
894
-
895
- context "when an existing record that is not the first has a nil value for the scoped attribute" do
896
- it 'still works' do
897
- model = define_model_validating_uniqueness(scopes: [:scope])
898
- create_record_from(model, scope: 'some value')
899
- create_record_from(model, scope: nil)
900
- record = build_record_from(model, scope: 'a different value')
901
-
902
- expect(record).to validate_uniqueness.scoped_to(:scope)
903
- end
904
- end
905
- end
906
-
907
- context 'when the model has a case-sensitive validation' do
908
- context 'when the matcher is not qualified with case_insensitive' do
909
- it 'accepts' do
910
- record = build_record_validating_uniqueness(
911
- attribute_type: :string,
912
- validation_options: { case_sensitive: true }
913
- )
914
-
915
- expect(record).to validate_uniqueness
916
- end
917
-
918
- context 'given an existing record where the value of the attribute under test is not case-swappable' do
919
- it 'raises a NonCaseSwappableValueError' do
920
- model = define_model_validating_uniqueness(
921
- attribute_type: :string,
922
- validation_options: { case_sensitive: true },
923
- )
924
- record = create_record_from(model, attribute_name => '123')
925
- running_matcher = -> { validate_uniqueness.matches?(record) }
926
-
927
- expect(&running_matcher).
928
- to raise_error(described_class::NonCaseSwappableValueError)
929
- end
930
- end
931
- end
932
-
933
- context 'when the matcher is qualified with case_insensitive' do
934
- it 'rejects with an appropriate failure message' do
935
- record = build_record_validating_uniqueness(
936
- attribute_type: :string,
937
- attribute_value: 'some value',
938
- validation_options: { case_sensitive: true }
939
- )
940
-
941
- assertion = lambda do
942
- expect(record).to validate_uniqueness.case_insensitive
943
- end
944
-
945
- message = <<-MESSAGE
946
- Expected Example to validate that :attr is case-insensitively unique,
947
- but this could not be proved.
948
- After taking the given Example, whose :attr is ‹"some value"›, and
949
- saving it as the existing record, then making a new Example and
950
- setting its :attr to a different value, ‹"SOME VALUE"›, the matcher
951
- expected the new Example to be invalid, but it was valid instead.
952
- MESSAGE
953
-
954
- expect(&assertion).to fail_with_message(message)
955
- end
956
- end
957
- end
958
-
959
- context 'when the model has a case-insensitive validation' do
960
- context 'when case_insensitive is not specified' do
961
- it 'rejects with an appropriate failure message' do
962
- record = build_record_validating_uniqueness(
963
- attribute_type: :string,
964
- validation_options: { case_sensitive: false }
965
- )
966
-
967
- assertion = lambda do
968
- expect(record).to validate_uniqueness
969
- end
970
-
971
- message = <<-MESSAGE
972
- Expected Example to validate that :attr is case-sensitively unique, but
973
- this could not be proved.
974
- After taking the given Example, setting its :attr to ‹"dummy value"›,
975
- and saving it as the existing record, then making a new Example and
976
- setting its :attr to a different value, ‹"DUMMY VALUE"›, the matcher
977
- expected the new Example to be valid, but it was invalid instead,
978
- producing these validation errors:
979
-
980
- * attr: ["has already been taken"]
981
- MESSAGE
982
-
983
- expect(&assertion).to fail_with_message(message)
984
- end
985
- end
986
-
987
- context 'when case_insensitive is specified' do
988
- it 'accepts' do
989
- record = build_record_validating_uniqueness(
990
- attribute_type: :string,
991
- validation_options: { case_sensitive: false }
992
- )
993
-
994
- expect(record).to validate_uniqueness.case_insensitive
995
- end
996
-
997
- it_supports(
998
- 'ignoring_interference_by_writer',
999
- tests: {
1000
- reject_if_qualified_but_changing_value_interferes: {
1001
- model_name: 'Example',
1002
- attribute_name: :attr,
1003
- default_value: 'some value',
1004
- changing_values_with: :next_value,
1005
- expected_message: <<-MESSAGE.strip
1006
- Expected Example to validate that :attr is case-insensitively unique,
1007
- but this could not be proved.
1008
- After taking the given Example, whose :attr is ‹"some valuf"›, and
1009
- saving it as the existing record, then making a new Example and
1010
- setting its :attr to ‹"some valuf"› (read back as ‹"some valug"›) as
1011
- well, the matcher expected the new Example to be invalid, but it was
1012
- valid instead.
1013
-
1014
- As indicated in the message above, :attr seems to be changing certain
1015
- values as they are set, and this could have something to do with why
1016
- this test is failing. If you or something else has overridden the
1017
- writer method for this attribute to normalize values by changing their
1018
- case in any way (for instance, ensuring that the attribute is always
1019
- downcased), then try adding `ignoring_case_sensitivity` onto the end
1020
- of the uniqueness matcher. Otherwise, you may need to write the test
1021
- yourself, or do something different altogether.
1022
- MESSAGE
1023
- }
1024
- }
1025
- )
1026
-
1027
- def validation_matcher_scenario_args
1028
- super.deep_merge(validation_options: { case_sensitive: false })
1029
- end
1030
-
1031
- def configure_validation_matcher(matcher)
1032
- super(matcher).case_insensitive
1033
- end
1034
- end
1035
- end
1036
-
1037
- context 'when the validation is declared with allow_nil' do
1038
- context 'given a new record whose attribute is nil' do
1039
- it 'accepts' do
1040
- model = define_model_validating_uniqueness(
1041
- validation_options: { allow_nil: true }
1042
- )
1043
- record = build_record_from(model, attribute_name => nil)
1044
- expect(record).to validate_uniqueness.allow_nil
1045
- end
1046
- end
1047
-
1048
- context 'given an existing record whose attribute is nil' do
1049
- it 'accepts' do
1050
- model = define_model_validating_uniqueness(
1051
- validation_options: { allow_nil: true }
1052
- )
1053
- record = create_record_from(model, attribute_name => nil)
1054
- expect(record).to validate_uniqueness.allow_nil
1055
- end
1056
- end
1057
-
1058
- if active_record_supports_has_secure_password?
1059
- context 'when the model is declared with has_secure_password' do
1060
- it 'accepts' do
1061
- model = define_model_validating_uniqueness(
1062
- validation_options: { allow_nil: true },
1063
- additional_attributes: [{ name: :password_digest, type: :string }]
1064
- ) do |m|
1065
- m.has_secure_password
1066
- end
1067
-
1068
- record = build_record_from(model, attribute_name => nil)
1069
-
1070
- expect(record).to validate_uniqueness.allow_nil
1071
- end
1072
- end
1073
- end
1074
- end
1075
-
1076
- context 'when the validation is not declared with allow_nil' do
1077
- context 'given a new record whose attribute is nil' do
1078
- it 'rejects with an appropriate failure message' do
1079
- model = define_model_validating_uniqueness
1080
- record = build_record_from(model, attribute_name => nil)
1081
-
1082
- assertion = lambda do
1083
- expect(record).to validate_uniqueness.allow_nil
1084
- end
1085
-
1086
- message = <<-MESSAGE
1087
- Expected Example to validate that :attr is case-sensitively unique as
1088
- long as it is not nil, but this could not be proved.
1089
- After taking the given Example, setting its :attr to ‹nil›, and saving
1090
- it as the existing record, then making a new Example and setting its
1091
- :attr to ‹nil› as well, the matcher expected the new Example to be
1092
- valid, but it was invalid instead, producing these validation errors:
1093
-
1094
- * attr: ["has already been taken"]
1095
- MESSAGE
1096
-
1097
- expect(&assertion).to fail_with_message(message)
1098
- end
1099
- end
1100
-
1101
- context 'given an existing record whose attribute is nil' do
1102
- it 'rejects with an appropriate failure message' do
1103
- model = define_model_validating_uniqueness
1104
- record = create_record_from(model, attribute_name => nil)
1105
-
1106
- assertion = lambda do
1107
- expect(record).to validate_uniqueness.allow_nil
1108
- end
1109
-
1110
- message = <<-MESSAGE
1111
- Expected Example to validate that :attr is case-sensitively unique as
1112
- long as it is not nil, but this could not be proved.
1113
- Given an existing Example, after setting its :attr to ‹nil›, then
1114
- making a new Example and setting its :attr to ‹nil› as well, the
1115
- matcher expected the new Example to be valid, but it was invalid
1116
- instead, producing these validation errors:
1117
-
1118
- * attr: ["has already been taken"]
1119
- MESSAGE
1120
-
1121
- expect(&assertion).to fail_with_message(message)
1122
- end
1123
- end
1124
- end
1125
-
1126
- context 'when the validation is declared with allow_blank' do
1127
- context 'given a new record whose attribute is nil' do
1128
- it 'accepts' do
1129
- model = define_model_validating_uniqueness(
1130
- validation_options: { allow_blank: true }
1131
- )
1132
- record = build_record_from(model, attribute_name => nil)
1133
- expect(record).to validate_uniqueness.allow_blank
1134
- end
1135
- end
1136
-
1137
- context 'given an existing record whose attribute is nil' do
1138
- it 'accepts' do
1139
- model = define_model_validating_uniqueness(
1140
- validation_options: { allow_blank: true }
1141
- )
1142
- record = create_record_from(model, attribute_name => nil)
1143
- expect(record).to validate_uniqueness.allow_blank
1144
- end
1145
- end
1146
-
1147
- context 'given a new record whose attribute is empty' do
1148
- it 'accepts' do
1149
- model = define_model_validating_uniqueness(
1150
- attribute_type: :string,
1151
- validation_options: { allow_blank: true }
1152
- )
1153
- record = build_record_from(model, attribute_name => '')
1154
- expect(record).to validate_uniqueness.allow_blank
1155
- end
1156
- end
1157
-
1158
- context 'given an existing record whose attribute is empty' do
1159
- it 'accepts' do
1160
- model = define_model_validating_uniqueness(
1161
- attribute_type: :string,
1162
- validation_options: { allow_blank: true }
1163
- )
1164
- record = create_record_from(model, attribute_name => '')
1165
- expect(record).to validate_uniqueness.allow_blank
1166
- end
1167
- end
1168
-
1169
- if active_record_supports_has_secure_password?
1170
- context 'when the model is declared with has_secure_password' do
1171
- context 'given a record whose attribute is nil' do
1172
- it 'accepts' do
1173
- model = define_model_validating_uniqueness(
1174
- validation_options: { allow_blank: true },
1175
- additional_attributes: [{ name: :password_digest, type: :string }]
1176
- ) do |m|
1177
- m.has_secure_password
1178
- end
1179
-
1180
- record = build_record_from(model, attribute_name => nil)
1181
-
1182
- expect(record).to validate_uniqueness.allow_blank
1183
- end
1184
- end
1185
-
1186
- context 'given a record whose attribute is empty' do
1187
- it 'accepts' do
1188
- model = define_model_validating_uniqueness(
1189
- attribute_type: :string,
1190
- validation_options: { allow_blank: true },
1191
- additional_attributes: [{ name: :password_digest, type: :string }]
1192
- ) do |m|
1193
- m.has_secure_password
1194
- end
1195
-
1196
- record = build_record_from(model, attribute_name => '')
1197
-
1198
- expect(record).to validate_uniqueness.allow_blank
1199
- end
1200
- end
1201
- end
1202
- end
1203
- end
1204
-
1205
- context 'when the validation is not declared with allow_blank' do
1206
- context 'given a new record whose attribute is nil' do
1207
- it 'rejects with an appropriate failure message' do
1208
- model = define_model_validating_uniqueness
1209
- record = build_record_from(model, attribute_name => nil)
1210
-
1211
- assertion = lambda do
1212
- expect(record).to validate_uniqueness.allow_blank
1213
- end
1214
-
1215
- message = <<-MESSAGE
1216
- Expected Example to validate that :attr is case-sensitively unique as
1217
- long as it is not blank, but this could not be proved.
1218
- After taking the given Example, setting its :attr to ‹""›, and saving
1219
- it as the existing record, then making a new Example and setting its
1220
- :attr to ‹""› as well, the matcher expected the new Example to be
1221
- valid, but it was invalid instead, producing these validation errors:
1222
-
1223
- * attr: ["has already been taken"]
1224
- MESSAGE
1225
-
1226
- expect(&assertion).to fail_with_message(message)
1227
- end
1228
- end
1229
-
1230
- context 'given an existing record whose attribute is nil' do
1231
- it 'rejects with an appropriate failure message' do
1232
- model = define_model_validating_uniqueness
1233
- record = create_record_from(model, attribute_name => nil)
1234
-
1235
- assertion = lambda do
1236
- expect(record).to validate_uniqueness.allow_blank
1237
- end
1238
-
1239
- message = <<-MESSAGE
1240
- Expected Example to validate that :attr is case-sensitively unique as
1241
- long as it is not blank, but this could not be proved.
1242
- Given an existing Example, after setting its :attr to ‹""›, then
1243
- making a new Example and setting its :attr to ‹""› as well, the
1244
- matcher expected the new Example to be valid, but it was invalid
1245
- instead, producing these validation errors:
1246
-
1247
- * attr: ["has already been taken"]
1248
- MESSAGE
1249
-
1250
- expect(&assertion).to fail_with_message(message)
1251
- end
1252
- end
1253
-
1254
- context 'given a new record whose attribute is empty' do
1255
- it 'rejects with an appropriate failure message' do
1256
- model = define_model_validating_uniqueness(
1257
- attribute_type: :string
1258
- )
1259
- record = build_record_from(model, attribute_name => '')
1260
-
1261
- assertion = lambda do
1262
- expect(record).to validate_uniqueness.allow_blank
1263
- end
1264
-
1265
- message = <<-MESSAGE
1266
- Expected Example to validate that :attr is case-sensitively unique as
1267
- long as it is not blank, but this could not be proved.
1268
- After taking the given Example, setting its :attr to ‹""›, and saving
1269
- it as the existing record, then making a new Example and setting its
1270
- :attr to ‹""› as well, the matcher expected the new Example to be
1271
- valid, but it was invalid instead, producing these validation errors:
1272
-
1273
- * attr: ["has already been taken"]
1274
- MESSAGE
1275
-
1276
- expect(&assertion).to fail_with_message(message)
1277
- end
1278
- end
1279
-
1280
- context 'given an existing record whose attribute is empty' do
1281
- it 'rejects with an appropriate failure message' do
1282
- model = define_model_validating_uniqueness(
1283
- attribute_type: :string
1284
- )
1285
- record = create_record_from(model, attribute_name => '')
1286
-
1287
- assertion = lambda do
1288
- expect(record).to validate_uniqueness.allow_blank
1289
- end
1290
-
1291
- message = <<-MESSAGE
1292
- Expected Example to validate that :attr is case-sensitively unique as
1293
- long as it is not blank, but this could not be proved.
1294
- Given an existing Example, after setting its :attr to ‹""›, then
1295
- making a new Example and setting its :attr to ‹""› as well, the
1296
- matcher expected the new Example to be valid, but it was invalid
1297
- instead, producing these validation errors:
1298
-
1299
- * attr: ["has already been taken"]
1300
- MESSAGE
1301
-
1302
- expect(&assertion).to fail_with_message(message)
1303
- end
1304
- end
1305
- end
1306
-
1307
- context 'when testing that a polymorphic *_type column is one of the validation scopes' do
1308
- it 'sets that column to a meaningful value that works with other validations on the same column' do
1309
- user_model = define_model 'User'
1310
- favorite_columns = {
1311
- favoriteable_id: { type: :integer, options: { null: false } },
1312
- favoriteable_type: { type: :string, options: { null: false } }
1313
- }
1314
- favorite_model = define_model 'Favorite', favorite_columns do
1315
- if respond_to?(:attr_accessible)
1316
- attr_accessible :favoriteable
1317
- end
1318
-
1319
- belongs_to :favoriteable, polymorphic: true
1320
- validates :favoriteable, presence: true
1321
- validates :favoriteable_id, uniqueness: { scope: :favoriteable_type }
1322
- end
1323
-
1324
- user = user_model.create!
1325
- favorite_model.create!(favoriteable: user)
1326
- new_favorite = favorite_model.new
1327
-
1328
- expect(new_favorite).
1329
- to validate_uniqueness_of(:favoriteable_id).
1330
- scoped_to(:favoriteable_type)
1331
- end
1332
-
1333
- context 'if the model the *_type column refers to is namespaced, and shares the last part of its name with an existing model' do
1334
- it 'still works' do
1335
- define_class 'User'
1336
- define_module 'Models'
1337
- user_model = define_model 'Models::User'
1338
- favorite_columns = {
1339
- favoriteable_id: { type: :integer, options: { null: false } },
1340
- favoriteable_type: { type: :string, options: { null: false } }
1341
- }
1342
- favorite_model = define_model 'Models::Favorite', favorite_columns do
1343
- if respond_to?(:attr_accessible)
1344
- attr_accessible :favoriteable
1345
- end
1346
-
1347
- belongs_to :favoriteable, polymorphic: true
1348
- validates :favoriteable, presence: true
1349
- validates :favoriteable_id, uniqueness: { scope: :favoriteable_type }
1350
- end
1351
-
1352
- user = user_model.create!
1353
- favorite_model.create!(favoriteable: user)
1354
- new_favorite = favorite_model.new
1355
-
1356
- expect(new_favorite).
1357
- to validate_uniqueness_of(:favoriteable_id).
1358
- scoped_to(:favoriteable_type)
1359
- end
1360
- end
1361
- end
1362
-
1363
- context 'when the model does not have the attribute being tested' do
1364
- it 'fails with an appropriate failure message' do
1365
- model = define_model(:example)
1366
-
1367
- assertion = lambda do
1368
- expect(model.new).to validate_uniqueness_of(:attr)
1369
- end
1370
-
1371
- message = <<-MESSAGE.strip
1372
- Expected Example to validate that :attr is case-sensitively unique, but
1373
- this could not be proved.
1374
- :attr does not seem to be an attribute on Example.
1375
- MESSAGE
1376
-
1377
- expect(&assertion).to fail_with_message(message)
1378
- end
1379
- end
1380
-
1381
- context 'when the writer method for the attribute changes the case of incoming values' do
1382
- context 'when the validation is case-sensitive' do
1383
- context 'and the matcher is ensuring that the validation is case-sensitive' do
1384
- it 'rejects with an appropriate failure message' do
1385
- model = define_model_validating_uniqueness(
1386
- attribute_name: :name
1387
- )
1388
-
1389
- model.class_eval do
1390
- def name=(name)
1391
- super(name.upcase)
1392
- end
1393
- end
1394
-
1395
- assertion = lambda do
1396
- expect(model.new).to validate_uniqueness_of(:name)
1397
- end
1398
-
1399
- message = <<-MESSAGE.strip
1400
- Expected Example to validate that :name is case-sensitively unique, but
1401
- this could not be proved.
1402
- After taking the given Example, setting its :name to ‹"dummy value"›
1403
- (read back as ‹"DUMMY VALUE"›), and saving it as the existing record,
1404
- then making a new Example and setting its :name to ‹"dummy value"›
1405
- (read back as ‹"DUMMY VALUE"›) as well, the matcher expected the new
1406
- Example to be valid, but it was invalid instead, producing these
1407
- validation errors:
1408
-
1409
- * name: ["has already been taken"]
1410
-
1411
- As indicated in the message above, :name seems to be changing certain
1412
- values as they are set, and this could have something to do with why
1413
- this test is failing. If you or something else has overridden the
1414
- writer method for this attribute to normalize values by changing their
1415
- case in any way (for instance, ensuring that the attribute is always
1416
- downcased), then try adding `ignoring_case_sensitivity` onto the end
1417
- of the uniqueness matcher. Otherwise, you may need to write the test
1418
- yourself, or do something different altogether.
1419
- MESSAGE
1420
-
1421
- expect(&assertion).to fail_with_message(message)
1422
- end
1423
- end
1424
-
1425
- context 'and the matcher is ignoring case sensitivity' do
1426
- it 'accepts (and not raise an error)' do
1427
- model = define_model_validating_uniqueness(
1428
- attribute_name: :name
1429
- )
1430
-
1431
- model.class_eval do
1432
- def name=(name)
1433
- super(name.upcase)
1434
- end
1435
- end
1436
-
1437
- expect(model.new).
1438
- to validate_uniqueness_of(:name).
1439
- ignoring_case_sensitivity
1440
- end
1441
- end
1442
- end
1443
-
1444
- context 'when the validation is case-insensitive' do
1445
- context 'and the matcher is ensuring that the validation is case-insensitive' do
1446
- it 'accepts (and does not raise an error)' do
1447
- model = define_model_validating_uniqueness(
1448
- attribute_name: :name,
1449
- validation_options: { case_sensitive: false },
1450
- )
1451
-
1452
- model.class_eval do
1453
- def name=(name)
1454
- super(name.downcase)
1455
- end
1456
- end
1457
-
1458
- expect(model.new).
1459
- to validate_uniqueness_of(:name).
1460
- case_insensitive
1461
- end
1462
- end
1463
- end
1464
- end
1465
-
1466
- context 'when the column is a boolean column' do
1467
- it 'accepts (and does not print a warning)' do
1468
- record = build_record_validating_uniqueness(attribute_type: :boolean)
1469
- running_validation = -> { expect(record).to validate_uniqueness }
1470
- message =
1471
- 'You attempted to assign a value which is not explicitly `true` or ' +
1472
- '`false`'
1473
-
1474
- expect(&running_validation).not_to print_warning_including(message)
1475
- end
1476
- end
1477
-
1478
- let(:model_attributes) { {} }
1479
-
1480
- def default_attribute
1481
- {
1482
- value_type: :string,
1483
- column_type: :string,
1484
- options: { array: false, null: true }
1485
- }
1486
- end
1487
-
1488
- def normalize_attribute(attribute)
1489
- if attribute.is_a?(Hash)
1490
- attribute_copy = attribute.dup
1491
-
1492
- if attribute_copy.key?(:type)
1493
- attribute_copy[:value_type] = attribute_copy[:type]
1494
- attribute_copy[:column_type] = attribute_copy[:type]
1495
- end
1496
-
1497
- default_attribute.deep_merge(attribute_copy)
1498
- else
1499
- default_attribute.deep_merge(name: attribute)
1500
- end
1501
- end
1502
-
1503
- def normalize_attributes(attributes)
1504
- attributes.map do |attribute|
1505
- normalize_attribute(attribute)
1506
- end
1507
- end
1508
-
1509
- def column_options_from(attributes)
1510
- attributes.inject({}) do |options, attribute|
1511
- options[attribute[:name]] = {
1512
- type: attribute[:column_type],
1513
- options: attribute.fetch(:options, {})
1514
- }
1515
- options
1516
- end
1517
- end
1518
-
1519
- def attributes_with_values_for(model)
1520
- model_attributes[model].each_with_object({}) do |attribute, attrs|
1521
- attrs[attribute[:name]] = attribute.fetch(:value) do
1522
- if attribute[:options][:null]
1523
- nil
1524
- else
1525
- dummy_value_for(
1526
- attribute[:value_type],
1527
- array: attribute[:options][:array]
1528
- )
1529
- end
1530
- end
1531
- end
1532
- end
1533
-
1534
- def dummy_value_for(attribute_type, array: false)
1535
- if array
1536
- [ dummy_scalar_value_for(attribute_type) ]
1537
- else
1538
- dummy_scalar_value_for(attribute_type)
1539
- end
1540
- end
1541
-
1542
- def dummy_scalar_value_for(attribute_type)
1543
- case attribute_type
1544
- when :string, :text
1545
- 'dummy value'
1546
- when :integer
1547
- 1
1548
- when :date
1549
- Date.today
1550
- when :datetime
1551
- Date.today.to_datetime
1552
- when :time
1553
- Time.now
1554
- when :uuid
1555
- SecureRandom.uuid
1556
- when :boolean
1557
- true
1558
- else
1559
- raise ArgumentError, "Unknown type '#{attribute_type}'"
1560
- end
1561
- end
1562
-
1563
- def next_version_of(value, value_type)
1564
- if value.is_a?(Array)
1565
- [ next_version_of(value[0], value_type) ]
1566
- elsif value_type == :uuid
1567
- SecureRandom.uuid
1568
- elsif value.is_a?(Time)
1569
- value + 1
1570
- elsif [true, false].include?(value)
1571
- !value
1572
- elsif value.respond_to?(:next)
1573
- value.next
1574
- end
1575
- end
1576
-
1577
- def build_record_from(model, extra_attributes = {})
1578
- attributes = attributes_with_values_for(model)
1579
- model.new(attributes.merge(extra_attributes))
1580
- end
1581
-
1582
- def create_record_from(model, extra_attributes = {})
1583
- build_record_from(model, extra_attributes).tap do |record|
1584
- record.save!
1585
- end
1586
- end
1587
-
1588
- def define_model_validating_uniqueness(options = {}, &block)
1589
- attribute_name = options.fetch(:attribute_name) { self.attribute_name }
1590
- attribute_type = options.fetch(:attribute_type, :string)
1591
- attribute_options = options.fetch(:attribute_options, {})
1592
- attribute = normalize_attribute(
1593
- name: attribute_name,
1594
- value_type: attribute_type,
1595
- column_type: attribute_type,
1596
- options: attribute_options
1597
- )
1598
-
1599
- if options.key?(:attribute_value)
1600
- attribute[:value] = options[:attribute_value]
1601
- end
1602
-
1603
- scope_attributes = normalize_attributes(options.fetch(:scopes, []))
1604
- scope_attribute_names = scope_attributes.map { |attr| attr[:name] }
1605
- additional_attributes = normalize_attributes(
1606
- options.fetch(:additional_attributes, [])
1607
- )
1608
- attributes = [attribute] + scope_attributes + additional_attributes
1609
- validation_options = options.fetch(:validation_options, {})
1610
- column_options = column_options_from(attributes)
1611
-
1612
- model = define_model(:example, column_options) do |m|
1613
- m.validates_uniqueness_of attribute_name,
1614
- validation_options.merge(scope: scope_attribute_names)
1615
-
1616
- if m.respond_to?(:attr_accessible)
1617
- attributes.each do |attr|
1618
- m.attr_accessible(attr[:name])
1619
- end
1620
- end
1621
-
1622
- block.call(m) if block
1623
- end
1624
-
1625
- model_attributes[model] = attributes
1626
-
1627
- model
1628
- end
1629
-
1630
- def build_record_validating_uniqueness(options = {}, &block)
1631
- model = define_model_validating_uniqueness(options, &block)
1632
- build_record_from(model)
1633
- end
1634
- alias_method :new_record_validating_uniqueness,
1635
- :build_record_validating_uniqueness
1636
-
1637
- def create_record_validating_uniqueness(options = {}, &block)
1638
- build_record_validating_uniqueness(options, &block).tap do |record|
1639
- record.save!
1640
- end
1641
- end
1642
- alias_method :existing_record_validating_uniqueness,
1643
- :create_record_validating_uniqueness
1644
-
1645
- def build_record_validating_scoped_uniqueness_with_enum(options = {})
1646
- options = options.dup
1647
- enum_scope_attribute =
1648
- normalize_attribute(options.delete(:enum_scope)).
1649
- merge(value_type: :integer, column_type: :integer)
1650
- additional_scopes = options.delete(:additional_scopes) { [] }
1651
- options[:scopes] = [enum_scope_attribute] + additional_scopes
1652
- dummy_enum_values = [:foo, :bar]
1653
-
1654
- model = define_model_validating_uniqueness(options)
1655
- model.enum(enum_scope_attribute[:name] => dummy_enum_values)
1656
-
1657
- build_record_from(model)
1658
- end
1659
-
1660
- def define_model_without_validation
1661
- define_model(:example, attribute_name => :string) do |model|
1662
- if model.respond_to?(:attr_accessible)
1663
- model.attr_accessible(attribute_name)
1664
- end
1665
- end
1666
- end
1667
-
1668
- def validate_uniqueness
1669
- validate_uniqueness_of(attribute_name)
1670
- end
1671
-
1672
- def attribute_name
1673
- :attr
1674
- end
1675
-
1676
- def validation_matcher_scenario_args
1677
- super.deep_merge(
1678
- matcher_name: :validate_uniqueness_of,
1679
- model_creator: :"active_record/uniqueness_matcher"
1680
- )
1681
- end
1682
- end