shoulda-matchers 4.5.1 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +15 -13
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +0 -87
- data/lib/shoulda/matchers/action_controller/flash_store.rb +2 -4
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +3 -6
- data/lib/shoulda/matchers/active_model/helpers.rb +1 -1
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +13 -34
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +3 -5
- data/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +43 -0
- data/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
- data/lib/shoulda/matchers/active_model/qualifiers.rb +1 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +14 -2
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +6 -4
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +47 -1
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +31 -6
- data/lib/shoulda/matchers/active_model/validator.rb +1 -6
- data/lib/shoulda/matchers/active_model.rb +2 -1
- data/lib/shoulda/matchers/active_record/association_matcher.rb +20 -22
- data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +125 -22
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +21 -3
- data/lib/shoulda/matchers/rails_shim.rb +14 -39
- data/lib/shoulda/matchers/util/word_wrap.rb +2 -2
- data/lib/shoulda/matchers/version.rb +1 -1
- data/shoulda-matchers.gemspec +3 -3
- metadata +10 -8
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +0 -161
@@ -78,6 +78,27 @@ module Shoulda
|
|
78
78
|
# should validate_presence_of(:nickname).allow_nil
|
79
79
|
# end
|
80
80
|
#
|
81
|
+
# #### allow_blank
|
82
|
+
#
|
83
|
+
# Use `allow_blank` to assert that the attribute allows blank.
|
84
|
+
#
|
85
|
+
# class Robot
|
86
|
+
# include ActiveModel::Model
|
87
|
+
# attr_accessor :nickname
|
88
|
+
#
|
89
|
+
# validates_presence_of :nickname, allow_blank: true
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# # RSpec
|
93
|
+
# RSpec.describe Robot, type: :model do
|
94
|
+
# it { should validate_presence_of(:nickname).allow_blank }
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# # Minitest (Shoulda)
|
98
|
+
# class RobotTest < ActiveSupport::TestCase
|
99
|
+
# should validate_presence_of(:nickname).allow_blank
|
100
|
+
# end
|
101
|
+
#
|
81
102
|
# ##### on
|
82
103
|
#
|
83
104
|
# Use `on` if your validation applies only under a certain context.
|
@@ -133,6 +154,7 @@ module Shoulda
|
|
133
154
|
# @private
|
134
155
|
class ValidatePresenceOfMatcher < ValidationMatcher
|
135
156
|
include Qualifiers::AllowNil
|
157
|
+
include Qualifiers::AllowBlank
|
136
158
|
|
137
159
|
def initialize(attribute)
|
138
160
|
super
|
@@ -144,7 +166,8 @@ module Shoulda
|
|
144
166
|
|
145
167
|
possibly_ignore_interference_by_writer
|
146
168
|
|
147
|
-
if secure_password_being_validated?
|
169
|
+
if secure_password_being_validated? &&
|
170
|
+
Shoulda::Matchers::RailsShim.active_model_lt_7?
|
148
171
|
ignore_interference_by_writer.default_to(when: :blank?)
|
149
172
|
|
150
173
|
disallowed_values.all? do |value|
|
@@ -152,6 +175,7 @@ module Shoulda
|
|
152
175
|
end
|
153
176
|
else
|
154
177
|
(!expects_to_allow_nil? || allows_value_of(nil)) &&
|
178
|
+
(!expects_to_allow_blank? || allows_value_of('')) &&
|
155
179
|
disallowed_values.all? do |value|
|
156
180
|
disallows_original_or_typecast_value?(value)
|
157
181
|
end
|
@@ -171,6 +195,7 @@ module Shoulda
|
|
171
195
|
end
|
172
196
|
else
|
173
197
|
(expects_to_allow_nil? && disallows_value_of(nil)) ||
|
198
|
+
(expects_to_allow_blank? && disallows_value_of('')) ||
|
174
199
|
disallowed_values.any? do |value|
|
175
200
|
allows_original_or_typecast_value?(value)
|
176
201
|
end
|
@@ -208,7 +233,7 @@ validation for you? Instead of using `validate_presence_of`, try
|
|
208
233
|
end
|
209
234
|
|
210
235
|
def possibly_ignore_interference_by_writer
|
211
|
-
if secure_password_being_validated?
|
236
|
+
if secure_password_being_validated? && RailsShim.active_model_lt_7?
|
212
237
|
ignore_interference_by_writer.default_to(when: :blank?)
|
213
238
|
end
|
214
239
|
end
|
@@ -241,11 +266,11 @@ validation for you? Instead of using `validate_presence_of`, try
|
|
241
266
|
else
|
242
267
|
values = []
|
243
268
|
|
244
|
-
if attribute_accepts_string_values?
|
269
|
+
if attribute_accepts_string_values? && !expects_to_allow_blank?
|
245
270
|
values << ''
|
246
271
|
end
|
247
272
|
|
248
|
-
if !expects_to_allow_nil?
|
273
|
+
if !expects_to_allow_nil? && !expects_to_allow_blank?
|
249
274
|
values << nil
|
250
275
|
end
|
251
276
|
|
@@ -327,8 +352,8 @@ validation for you? Instead of using `validate_presence_of`, try
|
|
327
352
|
end
|
328
353
|
|
329
354
|
def collection_association?
|
330
|
-
association? &&
|
331
|
-
|
355
|
+
association? && [:has_many, :has_and_belongs_to_many].include?(
|
356
|
+
association_reflection.macro,
|
332
357
|
)
|
333
358
|
end
|
334
359
|
|
@@ -98,12 +98,7 @@ module Shoulda
|
|
98
98
|
|
99
99
|
all_validation_errors = record.errors.dup
|
100
100
|
|
101
|
-
validation_error_messages =
|
102
|
-
if record.errors.respond_to?(:[])
|
103
|
-
record.errors[attribute]
|
104
|
-
else
|
105
|
-
record.errors.on(attribute)
|
106
|
-
end
|
101
|
+
validation_error_messages = record.errors[attribute]
|
107
102
|
|
108
103
|
{
|
109
104
|
all_validation_errors: all_validation_errors,
|
@@ -26,7 +26,8 @@ require 'shoulda/matchers/active_model/numericality_matchers/comparison_matcher'
|
|
26
26
|
require 'shoulda/matchers/active_model/numericality_matchers/odd_number_matcher'
|
27
27
|
require 'shoulda/matchers/active_model/numericality_matchers/even_number_matcher'
|
28
28
|
require 'shoulda/matchers/active_model/numericality_matchers/only_integer_matcher'
|
29
|
-
require 'shoulda/matchers/active_model/
|
29
|
+
require 'shoulda/matchers/active_model/numericality_matchers/range_matcher'
|
30
|
+
require 'shoulda/matchers/active_model/numericality_matchers/submatchers'
|
30
31
|
require 'shoulda/matchers/active_model/errors'
|
31
32
|
require 'shoulda/matchers/active_model/have_secure_password_matcher'
|
32
33
|
|
@@ -1004,7 +1004,7 @@ module Shoulda
|
|
1004
1004
|
@submatchers = []
|
1005
1005
|
@missing = ''
|
1006
1006
|
|
1007
|
-
if macro == :belongs_to
|
1007
|
+
if macro == :belongs_to
|
1008
1008
|
required(belongs_to_required_by_default?)
|
1009
1009
|
end
|
1010
1010
|
end
|
@@ -1394,23 +1394,25 @@ module Shoulda
|
|
1394
1394
|
end
|
1395
1395
|
|
1396
1396
|
def class_has_foreign_key?(klass)
|
1397
|
+
@missing = validate_foreign_key(klass)
|
1398
|
+
|
1399
|
+
@missing.nil?
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
def validate_foreign_key(klass)
|
1397
1403
|
if options.key?(:foreign_key) && !foreign_key_correct?
|
1398
|
-
|
1399
|
-
|
1400
|
-
|
1401
|
-
@missing = foreign_key_failure_message(klass, foreign_key)
|
1402
|
-
false
|
1403
|
-
else
|
1404
|
-
true
|
1404
|
+
foreign_key_failure_message(klass, options[:foreign_key])
|
1405
|
+
elsif !has_column?(klass, actual_foreign_key)
|
1406
|
+
foreign_key_failure_message(klass, actual_foreign_key)
|
1405
1407
|
end
|
1406
1408
|
end
|
1407
1409
|
|
1408
1410
|
def has_column?(klass, column)
|
1409
1411
|
case column
|
1410
1412
|
when Array
|
1411
|
-
column.all? { |c| has_column?(klass, c) }
|
1413
|
+
column.all? { |c| has_column?(klass, c.to_s) }
|
1412
1414
|
else
|
1413
|
-
column_names_for(klass).include?(column)
|
1415
|
+
column_names_for(klass).include?(column.to_s)
|
1414
1416
|
end
|
1415
1417
|
end
|
1416
1418
|
|
@@ -1442,19 +1444,15 @@ module Shoulda
|
|
1442
1444
|
end
|
1443
1445
|
end
|
1444
1446
|
|
1445
|
-
def
|
1446
|
-
|
1447
|
-
|
1448
|
-
|
1449
|
-
|
1450
|
-
|
1451
|
-
|
1452
|
-
end
|
1453
|
-
|
1454
|
-
if key.is_a?(Array)
|
1455
|
-
key.map(&:to_s)
|
1447
|
+
def actual_foreign_key
|
1448
|
+
return unless foreign_key_reflection
|
1449
|
+
|
1450
|
+
if foreign_key_reflection.options[:foreign_key]
|
1451
|
+
foreign_key_reflection.options[:foreign_key]
|
1452
|
+
elsif foreign_key_reflection.respond_to?(:foreign_key)
|
1453
|
+
foreign_key_reflection.foreign_key
|
1456
1454
|
else
|
1457
|
-
|
1455
|
+
foreign_key_reflection.primary_key_name
|
1458
1456
|
end
|
1459
1457
|
end
|
1460
1458
|
|
@@ -6,16 +6,22 @@ module Shoulda
|
|
6
6
|
#
|
7
7
|
# class Process < ActiveRecord::Base
|
8
8
|
# enum status: [:running, :stopped, :suspended]
|
9
|
+
#
|
10
|
+
# alias_attribute :kind, :SomeLegacyField
|
11
|
+
#
|
12
|
+
# enum kind: [:foo, :bar]
|
9
13
|
# end
|
10
14
|
#
|
11
15
|
# # RSpec
|
12
16
|
# RSpec.describe Process, type: :model do
|
13
17
|
# it { should define_enum_for(:status) }
|
18
|
+
# it { should define_enum_for(:kind) }
|
14
19
|
# end
|
15
20
|
#
|
16
21
|
# # Minitest (Shoulda)
|
17
22
|
# class ProcessTest < ActiveSupport::TestCase
|
18
23
|
# should define_enum_for(:status)
|
24
|
+
# should define_enum_for(:kind)
|
19
25
|
# end
|
20
26
|
#
|
21
27
|
# #### Qualifiers
|
@@ -110,7 +116,7 @@ module Shoulda
|
|
110
116
|
## ##### with_prefix
|
111
117
|
#
|
112
118
|
# Use `with_prefix` to test that the enum is defined with a `_prefix`
|
113
|
-
# option (Rails
|
119
|
+
# option (Rails 6+ only). Can take either a boolean or a symbol:
|
114
120
|
#
|
115
121
|
# class Issue < ActiveRecord::Base
|
116
122
|
# enum status: [:open, :closed], _prefix: :old
|
@@ -157,6 +163,30 @@ module Shoulda
|
|
157
163
|
# with_suffix
|
158
164
|
# end
|
159
165
|
#
|
166
|
+
# ##### without_scopes
|
167
|
+
#
|
168
|
+
# Use `without_scopes` to test that the enum is defined with
|
169
|
+
# '_scopes: false' option (Rails 5 only). Can take either a boolean or a
|
170
|
+
# symbol:
|
171
|
+
#
|
172
|
+
# class Issue < ActiveRecord::Base
|
173
|
+
# enum status: [:open, :closed], _scopes: false
|
174
|
+
# end
|
175
|
+
#
|
176
|
+
# # RSpec
|
177
|
+
# RSpec.describe Issue, type: :model do
|
178
|
+
# it do
|
179
|
+
# should define_enum_for(:status).
|
180
|
+
# without_scopes
|
181
|
+
# end
|
182
|
+
# end
|
183
|
+
#
|
184
|
+
# # Minitest (Shoulda)
|
185
|
+
# class ProcessTest < ActiveSupport::TestCase
|
186
|
+
# should define_enum_for(:status).
|
187
|
+
# without_scopes
|
188
|
+
# end
|
189
|
+
#
|
160
190
|
# @return [DefineEnumForMatcher]
|
161
191
|
#
|
162
192
|
def define_enum_for(attribute_name)
|
@@ -167,7 +197,7 @@ module Shoulda
|
|
167
197
|
class DefineEnumForMatcher
|
168
198
|
def initialize(attribute_name)
|
169
199
|
@attribute_name = attribute_name
|
170
|
-
@options = { expected_enum_values: [] }
|
200
|
+
@options = { expected_enum_values: [], scopes: true }
|
171
201
|
end
|
172
202
|
|
173
203
|
def description
|
@@ -220,13 +250,19 @@ module Shoulda
|
|
220
250
|
self
|
221
251
|
end
|
222
252
|
|
253
|
+
def without_scopes
|
254
|
+
options[:scopes] = false
|
255
|
+
self
|
256
|
+
end
|
257
|
+
|
223
258
|
def matches?(subject)
|
224
259
|
@record = subject
|
225
260
|
|
226
261
|
enum_defined? &&
|
227
262
|
enum_values_match? &&
|
228
263
|
column_type_matches? &&
|
229
|
-
enum_value_methods_exist?
|
264
|
+
enum_value_methods_exist? &&
|
265
|
+
scope_presence_matches?
|
230
266
|
end
|
231
267
|
|
232
268
|
def failure_message
|
@@ -288,6 +324,10 @@ module Shoulda
|
|
288
324
|
expectation << "_#{expected_suffix}".inspect
|
289
325
|
end
|
290
326
|
|
327
|
+
if exclude_scopes?
|
328
|
+
expectation << ' with no scopes'
|
329
|
+
end
|
330
|
+
|
291
331
|
expectation
|
292
332
|
else
|
293
333
|
simple_description
|
@@ -370,7 +410,10 @@ module Shoulda
|
|
370
410
|
end
|
371
411
|
|
372
412
|
def column
|
373
|
-
|
413
|
+
key = attribute_name.to_s
|
414
|
+
column_name = model.attribute_alias(key) || key
|
415
|
+
|
416
|
+
model.columns_hash[column_name]
|
374
417
|
end
|
375
418
|
|
376
419
|
def model
|
@@ -378,37 +421,81 @@ module Shoulda
|
|
378
421
|
end
|
379
422
|
|
380
423
|
def enum_value_methods_exist?
|
381
|
-
|
382
|
-
|
424
|
+
if instance_methods_exist?
|
425
|
+
true
|
426
|
+
else
|
427
|
+
message = missing_methods_message
|
428
|
+
|
429
|
+
message << " (we can't tell which)"
|
430
|
+
|
431
|
+
@failure_message_continuation = message
|
432
|
+
|
433
|
+
false
|
383
434
|
end
|
435
|
+
end
|
384
436
|
|
385
|
-
|
437
|
+
def scope_presence_matches?
|
438
|
+
if exclude_scopes?
|
439
|
+
if singleton_methods_exist?
|
440
|
+
message = "#{attribute_name.inspect} does map to these values "
|
441
|
+
message << 'but class scope methods were present'
|
442
|
+
|
443
|
+
@failure_message_continuation = message
|
444
|
+
|
445
|
+
false
|
446
|
+
else
|
447
|
+
true
|
448
|
+
end
|
449
|
+
elsif singleton_methods_exist?
|
386
450
|
true
|
387
451
|
else
|
388
|
-
|
389
|
-
|
452
|
+
if enum_defined?
|
453
|
+
message = 'But the class scope methods are not present'
|
454
|
+
else
|
455
|
+
message = missing_methods_message
|
390
456
|
|
391
|
-
|
392
|
-
|
393
|
-
message << 'configured with either a different prefix or '
|
394
|
-
message << 'suffix, or no prefix or suffix at all'
|
395
|
-
else
|
396
|
-
message << 'configured with either a different prefix or no '
|
397
|
-
message << 'prefix at all'
|
398
|
-
end
|
399
|
-
elsif expected_suffix
|
400
|
-
message << 'configured with either a different suffix or no '
|
401
|
-
message << 'suffix at all'
|
457
|
+
message << 'or the class scope methods are not present'
|
458
|
+
message << " (we can't tell which)"
|
402
459
|
end
|
403
460
|
|
404
|
-
message << " (we can't tell which)"
|
405
|
-
|
406
461
|
@failure_message_continuation = message
|
407
462
|
|
408
463
|
false
|
409
464
|
end
|
410
465
|
end
|
411
466
|
|
467
|
+
def missing_methods_message
|
468
|
+
message = "#{attribute_name.inspect} does map to these "
|
469
|
+
message << 'values, but the enum is '
|
470
|
+
|
471
|
+
if expected_prefix
|
472
|
+
if expected_suffix
|
473
|
+
message << 'configured with either a different prefix or '
|
474
|
+
message << 'suffix, or no prefix or suffix at all'
|
475
|
+
else
|
476
|
+
message << 'configured with either a different prefix or no '
|
477
|
+
message << 'prefix at all'
|
478
|
+
end
|
479
|
+
elsif expected_suffix
|
480
|
+
message << 'configured with either a different suffix or no '
|
481
|
+
message << 'suffix at all'
|
482
|
+
else
|
483
|
+
''
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
def singleton_methods_exist?
|
488
|
+
expected_singleton_methods.all? do |method|
|
489
|
+
model.singleton_methods.include?(method)
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
493
|
+
def instance_methods_exist?
|
494
|
+
expected_instance_methods.all? do |method|
|
495
|
+
record.methods.include?(method)
|
496
|
+
end
|
497
|
+
end
|
498
|
+
|
412
499
|
def expected_singleton_methods
|
413
500
|
expected_enum_value_names.map do |name|
|
414
501
|
[expected_prefix, name, expected_suffix].
|
@@ -418,6 +505,18 @@ module Shoulda
|
|
418
505
|
end
|
419
506
|
end
|
420
507
|
|
508
|
+
def expected_instance_methods
|
509
|
+
methods = expected_enum_value_names.map do |name|
|
510
|
+
[expected_prefix, name, expected_suffix].
|
511
|
+
select(&:present?).
|
512
|
+
join('_')
|
513
|
+
end
|
514
|
+
|
515
|
+
methods.flat_map do |m|
|
516
|
+
["#{m}?".to_sym, "#{m}!".to_sym]
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
421
520
|
def expected_prefix
|
422
521
|
if options.include?(:prefix)
|
423
522
|
if options[:prefix] == true
|
@@ -438,6 +537,10 @@ module Shoulda
|
|
438
537
|
end
|
439
538
|
end
|
440
539
|
|
540
|
+
def exclude_scopes?
|
541
|
+
!options[:scopes]
|
542
|
+
end
|
543
|
+
|
441
544
|
def to_hash(value)
|
442
545
|
if value.is_a?(Array)
|
443
546
|
value.each_with_index.inject({}) do |hash, (item, index)|
|
@@ -52,7 +52,7 @@ module Shoulda
|
|
52
52
|
#
|
53
53
|
# Use `with_options` to assert that a column has been defined with
|
54
54
|
# certain options (`:precision`, `:limit`, `:default`, `:null`, `:scale`,
|
55
|
-
# or `:
|
55
|
+
# `:primary` or `:array`).
|
56
56
|
#
|
57
57
|
# class CreatePhones < ActiveRecord::Migration
|
58
58
|
# def change
|
@@ -84,7 +84,7 @@ module Shoulda
|
|
84
84
|
|
85
85
|
# @private
|
86
86
|
class HaveDbColumnMatcher
|
87
|
-
OPTIONS = %i(precision limit default null scale primary).freeze
|
87
|
+
OPTIONS = %i(precision limit default null scale primary array).freeze
|
88
88
|
|
89
89
|
def initialize(column)
|
90
90
|
@column = column
|
@@ -115,7 +115,8 @@ module Shoulda
|
|
115
115
|
correct_default? &&
|
116
116
|
correct_null? &&
|
117
117
|
correct_scale? &&
|
118
|
-
correct_primary?
|
118
|
+
correct_primary? &&
|
119
|
+
correct_array?
|
119
120
|
end
|
120
121
|
|
121
122
|
def failure_message
|
@@ -258,6 +259,23 @@ module Shoulda
|
|
258
259
|
end
|
259
260
|
end
|
260
261
|
|
262
|
+
def correct_array?
|
263
|
+
return true unless @options.key?(:array)
|
264
|
+
|
265
|
+
if matched_column.array? == @options[:array]
|
266
|
+
true
|
267
|
+
else
|
268
|
+
@missing = "#{model_class} has a db column named #{@column} "
|
269
|
+
@missing <<
|
270
|
+
if @options[:primary]
|
271
|
+
'that is not array, but should be'
|
272
|
+
else
|
273
|
+
'that is array, but should not be'
|
274
|
+
end
|
275
|
+
false
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
261
279
|
def matched_column
|
262
280
|
@_matched_column ||= begin
|
263
281
|
column = model_class.columns.detect do |each|
|
@@ -3,24 +3,12 @@ module Shoulda
|
|
3
3
|
# @private
|
4
4
|
module RailsShim # rubocop:disable Metrics/ModuleLength
|
5
5
|
class << self
|
6
|
-
def action_pack_gte_5?
|
7
|
-
Gem::Requirement.new('>= 5').satisfied_by?(action_pack_version)
|
8
|
-
end
|
9
|
-
|
10
|
-
def action_pack_lt_5?
|
11
|
-
Gem::Requirement.new('< 5').satisfied_by?(action_pack_version)
|
12
|
-
end
|
13
|
-
|
14
6
|
def action_pack_version
|
15
7
|
Gem::Version.new(::ActionPack::VERSION::STRING)
|
16
8
|
rescue NameError
|
17
9
|
Gem::Version.new('0')
|
18
10
|
end
|
19
11
|
|
20
|
-
def active_record_gte_5?
|
21
|
-
Gem::Requirement.new('>= 5').satisfied_by?(active_record_version)
|
22
|
-
end
|
23
|
-
|
24
12
|
def active_record_gte_6?
|
25
13
|
Gem::Requirement.new('>= 6').satisfied_by?(active_record_version)
|
26
14
|
end
|
@@ -31,6 +19,20 @@ module Shoulda
|
|
31
19
|
Gem::Version.new('0')
|
32
20
|
end
|
33
21
|
|
22
|
+
def active_model_version
|
23
|
+
Gem::Version.new(::ActiveModel::VERSION::STRING)
|
24
|
+
rescue NameError
|
25
|
+
Gem::Version.new('0')
|
26
|
+
end
|
27
|
+
|
28
|
+
def active_model_st_6_1?
|
29
|
+
Gem::Requirement.new('< 6.1').satisfied_by?(active_model_version)
|
30
|
+
end
|
31
|
+
|
32
|
+
def active_model_lt_7?
|
33
|
+
Gem::Requirement.new('< 7').satisfied_by?(active_model_version)
|
34
|
+
end
|
35
|
+
|
34
36
|
def generate_validation_message(
|
35
37
|
record,
|
36
38
|
attribute,
|
@@ -57,17 +59,6 @@ module Shoulda
|
|
57
59
|
)
|
58
60
|
end
|
59
61
|
|
60
|
-
def make_controller_request(context, verb, action, request_params)
|
61
|
-
params =
|
62
|
-
if action_pack_gte_5?
|
63
|
-
{ params: request_params }
|
64
|
-
else
|
65
|
-
request_params
|
66
|
-
end
|
67
|
-
|
68
|
-
context.__send__(verb, action, params)
|
69
|
-
end
|
70
|
-
|
71
62
|
def serialized_attributes_for(model)
|
72
63
|
attribute_types_for(model).
|
73
64
|
inject({}) do |hash, (attribute_name, attribute_type)|
|
@@ -85,26 +76,10 @@ module Shoulda
|
|
85
76
|
serialized_attributes_for(model)[attribute_name.to_s]
|
86
77
|
end
|
87
78
|
|
88
|
-
def tables_and_views(connection)
|
89
|
-
if active_record_gte_5?
|
90
|
-
connection.data_sources
|
91
|
-
else
|
92
|
-
connection.tables
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
79
|
def verb_for_update
|
97
80
|
:patch
|
98
81
|
end
|
99
82
|
|
100
|
-
def validation_message_key_for_association_required_option
|
101
|
-
if active_record_gte_5?
|
102
|
-
:required
|
103
|
-
else
|
104
|
-
:blank
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
83
|
def parent_of(mod)
|
109
84
|
if mod.respond_to?(:module_parent)
|
110
85
|
mod.module_parent
|
@@ -92,7 +92,7 @@ module Shoulda
|
|
92
92
|
if line.list_item?
|
93
93
|
combined_lines << line
|
94
94
|
else
|
95
|
-
combined_lines.last <<
|
95
|
+
combined_lines.last << " #{line}".squeeze(' ')
|
96
96
|
end
|
97
97
|
|
98
98
|
combined_lines
|
@@ -185,7 +185,7 @@ module Shoulda
|
|
185
185
|
leftover = ''
|
186
186
|
else
|
187
187
|
fitted_line = line[0..index].rstrip
|
188
|
-
leftover = line[index + 1
|
188
|
+
leftover = line[index + 1..]
|
189
189
|
end
|
190
190
|
|
191
191
|
{ fitted_line: fitted_line, leftover: leftover }
|
data/shoulda-matchers.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
|
27
27
|
s.metadata = {
|
28
28
|
'bug_tracker_uri' => 'https://github.com/thoughtbot/shoulda-matchers/issues',
|
29
|
-
'changelog_uri' => 'https://github.com/thoughtbot/shoulda-matchers/blob/
|
29
|
+
'changelog_uri' => 'https://github.com/thoughtbot/shoulda-matchers/blob/main/CHANGELOG.md',
|
30
30
|
'documentation_uri' => 'https://matchers.shoulda.io/docs',
|
31
31
|
'homepage_uri' => 'https://matchers.shoulda.io',
|
32
32
|
'source_code_uri' => 'https://github.com/thoughtbot/shoulda-matchers',
|
@@ -36,6 +36,6 @@ Gem::Specification.new do |s|
|
|
36
36
|
'shoulda-matchers.gemspec']
|
37
37
|
s.require_paths = ['lib']
|
38
38
|
|
39
|
-
s.required_ruby_version = '>= 2.
|
40
|
-
s.add_dependency('activesupport', '>=
|
39
|
+
s.required_ruby_version = '>= 2.6.0'
|
40
|
+
s.add_dependency('activesupport', '>= 5.2.0')
|
41
41
|
end
|