shoulda-matchers 4.5.1 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|