shoulda-matchers 4.3.0 → 4.4.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/README.md +157 -77
- data/lib/shoulda/matchers.rb +13 -12
- data/lib/shoulda/matchers/action_controller.rb +13 -13
- data/lib/shoulda/matchers/active_model.rb +15 -26
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +5 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +5 -1
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +2 -21
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +27 -3
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +32 -0
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +27 -0
- data/lib/shoulda/matchers/active_record.rb +13 -23
- data/lib/shoulda/matchers/active_record/association_matcher.rb +20 -4
- data/lib/shoulda/matchers/active_record/association_matchers.rb +12 -0
- data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +12 -6
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +20 -3
- data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +147 -0
- data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +106 -0
- data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +28 -9
- data/lib/shoulda/matchers/active_record/uniqueness.rb +5 -5
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +2 -2
- data/lib/shoulda/matchers/doublespeak.rb +8 -7
- data/lib/shoulda/matchers/independent.rb +0 -2
- data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +3 -0
- data/lib/shoulda/matchers/integrations.rb +6 -6
- data/lib/shoulda/matchers/integrations/test_frameworks.rb +4 -2
- data/lib/shoulda/matchers/rails_shim.rb +4 -0
- data/lib/shoulda/matchers/util.rb +9 -4
- data/lib/shoulda/matchers/util/word_wrap.rb +1 -1
- data/lib/shoulda/matchers/version.rb +1 -1
- metadata +8 -8
- data/MIT-LICENSE +0 -22
- data/lib/shoulda/matchers/independent/delegate_method_matcher/stubbed_target.rb +0 -37
@@ -1,34 +1,9 @@
|
|
1
|
+
require 'shoulda/matchers/active_model/allow_mass_assignment_of_matcher'
|
1
2
|
require 'shoulda/matchers/active_model/helpers'
|
2
3
|
require 'shoulda/matchers/active_model/qualifiers'
|
3
4
|
require 'shoulda/matchers/active_model/validation_matcher'
|
4
|
-
require 'shoulda/matchers/active_model/validation_matcher/build_description'
|
5
|
-
require 'shoulda/matchers/active_model/validator'
|
6
|
-
require 'shoulda/matchers/active_model/allow_value_matcher'
|
7
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error'
|
8
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error'
|
9
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/attribute_setter'
|
10
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator'
|
11
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/attribute_setters'
|
12
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators'
|
13
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/successful_check'
|
14
|
-
require 'shoulda/matchers/active_model/allow_value_matcher/successful_setting'
|
15
|
-
require 'shoulda/matchers/active_model/disallow_value_matcher'
|
16
|
-
require 'shoulda/matchers/active_model/validate_length_of_matcher'
|
17
|
-
require 'shoulda/matchers/active_model/validate_inclusion_of_matcher'
|
18
|
-
require 'shoulda/matchers/active_model/validate_exclusion_of_matcher'
|
19
5
|
require 'shoulda/matchers/active_model/validate_absence_of_matcher'
|
20
6
|
require 'shoulda/matchers/active_model/validate_presence_of_matcher'
|
21
|
-
require 'shoulda/matchers/active_model/validate_acceptance_of_matcher'
|
22
|
-
require 'shoulda/matchers/active_model/validate_confirmation_of_matcher'
|
23
|
-
require 'shoulda/matchers/active_model/validate_numericality_of_matcher'
|
24
|
-
require 'shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher'
|
25
|
-
require 'shoulda/matchers/active_model/numericality_matchers/comparison_matcher'
|
26
|
-
require 'shoulda/matchers/active_model/numericality_matchers/odd_number_matcher'
|
27
|
-
require 'shoulda/matchers/active_model/numericality_matchers/even_number_matcher'
|
28
|
-
require 'shoulda/matchers/active_model/numericality_matchers/only_integer_matcher'
|
29
|
-
require 'shoulda/matchers/active_model/allow_mass_assignment_of_matcher'
|
30
|
-
require 'shoulda/matchers/active_model/errors'
|
31
|
-
require 'shoulda/matchers/active_model/have_secure_password_matcher'
|
32
7
|
|
33
8
|
module Shoulda
|
34
9
|
module Matchers
|
@@ -89,6 +64,20 @@ module Shoulda
|
|
89
64
|
# end
|
90
65
|
#
|
91
66
|
module ActiveModel
|
67
|
+
autoload :AllowValueMatcher, 'shoulda/matchers/active_model/allow_value_matcher'
|
68
|
+
autoload :CouldNotDetermineValueOutsideOfArray, 'shoulda/matchers/active_model/errors'
|
69
|
+
autoload :CouldNotSetPasswordError, 'shoulda/matchers/active_model/errors'
|
70
|
+
autoload :DisallowValueMatcher, 'shoulda/matchers/active_model/disallow_value_matcher'
|
71
|
+
autoload :HaveSecurePasswordMatcher, 'shoulda/matchers/active_model/have_secure_password_matcher'
|
72
|
+
autoload :NonNullableBooleanError, 'shoulda/matchers/active_model/errors'
|
73
|
+
autoload :NumericalityMatchers, 'shoulda/matchers/active_model/numericality_matchers'
|
74
|
+
autoload :ValidateAcceptanceOfMatcher, 'shoulda/matchers/active_model/validate_acceptance_of_matcher'
|
75
|
+
autoload :ValidateConfirmationOfMatcher, 'shoulda/matchers/active_model/validate_confirmation_of_matcher'
|
76
|
+
autoload :ValidateExclusionOfMatcher, 'shoulda/matchers/active_model/validate_exclusion_of_matcher'
|
77
|
+
autoload :ValidateInclusionOfMatcher, 'shoulda/matchers/active_model/validate_inclusion_of_matcher'
|
78
|
+
autoload :ValidateLengthOfMatcher, 'shoulda/matchers/active_model/validate_length_of_matcher'
|
79
|
+
autoload :ValidateNumericalityOfMatcher, 'shoulda/matchers/active_model/validate_numericality_of_matcher'
|
80
|
+
autoload :Validator, 'shoulda/matchers/active_model/validator'
|
92
81
|
end
|
93
82
|
end
|
94
83
|
end
|
@@ -305,6 +305,15 @@ module Shoulda
|
|
305
305
|
|
306
306
|
# @private
|
307
307
|
class AllowValueMatcher
|
308
|
+
autoload :AttributeChangedValueError, 'shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error'
|
309
|
+
autoload :AttributeDoesNotExistError, 'shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error'
|
310
|
+
autoload :AttributeSetter, 'shoulda/matchers/active_model/allow_value_matcher/attribute_setter'
|
311
|
+
autoload :AttributeSetterAndValidator, 'shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator'
|
312
|
+
autoload :AttributeSetters, 'shoulda/matchers/active_model/allow_value_matcher/attribute_setters'
|
313
|
+
autoload :AttributeSettersAndValidators, 'shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators'
|
314
|
+
autoload :SuccessfulCheck, 'shoulda/matchers/active_model/allow_value_matcher/successful_check'
|
315
|
+
autoload :SuccessfulSetting, 'shoulda/matchers/active_model/allow_value_matcher/successful_setting'
|
316
|
+
|
308
317
|
include Helpers
|
309
318
|
include Qualifiers::IgnoringInterferenceByWriter
|
310
319
|
|
@@ -3,6 +3,11 @@ module Shoulda
|
|
3
3
|
module ActiveModel
|
4
4
|
# @private
|
5
5
|
module NumericalityMatchers
|
6
|
+
autoload :ComparisonMatcher, 'shoulda/matchers/active_model/numericality_matchers/comparison_matcher'
|
7
|
+
autoload :EvenNumberMatcher, 'shoulda/matchers/active_model/numericality_matchers/even_number_matcher'
|
8
|
+
autoload :NumericTypeMatcher, 'shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher'
|
9
|
+
autoload :OddNumberMatcher, 'shoulda/matchers/active_model/numericality_matchers/odd_number_matcher'
|
10
|
+
autoload :OnlyIntegerMatcher, 'shoulda/matchers/active_model/numericality_matchers/only_integer_matcher'
|
6
11
|
end
|
7
12
|
end
|
8
13
|
end
|
@@ -9,7 +9,8 @@ module Shoulda
|
|
9
9
|
:>= => :greater_than_or_equal_to,
|
10
10
|
:< => :less_than,
|
11
11
|
:<= => :less_than_or_equal_to,
|
12
|
-
:== => :equal_to
|
12
|
+
:== => :equal_to,
|
13
|
+
:!= => :other_than,
|
13
14
|
}
|
14
15
|
|
15
16
|
def initialize(numericality_matcher, value, operator)
|
@@ -125,6 +126,8 @@ module Shoulda
|
|
125
126
|
[true, false, false]
|
126
127
|
when :<=
|
127
128
|
[true, true, false]
|
129
|
+
when :!=
|
130
|
+
[true, false, true]
|
128
131
|
end
|
129
132
|
end
|
130
133
|
|
@@ -146,6 +149,7 @@ module Shoulda
|
|
146
149
|
when :== then "equal to"
|
147
150
|
when :< then "less than"
|
148
151
|
when :<= then "less than or equal to"
|
152
|
+
when :!= then 'other than'
|
149
153
|
end
|
150
154
|
end
|
151
155
|
end
|
@@ -311,15 +311,6 @@ EOT
|
|
311
311
|
self
|
312
312
|
end
|
313
313
|
|
314
|
-
def allow_blank
|
315
|
-
@options[:allow_blank] = true
|
316
|
-
self
|
317
|
-
end
|
318
|
-
|
319
|
-
def expects_to_allow_blank?
|
320
|
-
@options[:allow_blank]
|
321
|
-
end
|
322
|
-
|
323
314
|
def allow_nil
|
324
315
|
@options[:allow_nil] = true
|
325
316
|
self
|
@@ -423,14 +414,14 @@ EOT
|
|
423
414
|
allows_all_values_in_array? &&
|
424
415
|
disallows_all_values_outside_of_array? &&
|
425
416
|
allows_nil_value? &&
|
426
|
-
|
417
|
+
allow_blank_matches?
|
427
418
|
end
|
428
419
|
|
429
420
|
def does_not_match_for_array?
|
430
421
|
disallows_any_values_in_array? ||
|
431
422
|
allows_any_value_outside_of_array? ||
|
432
423
|
disallows_nil_value? ||
|
433
|
-
|
424
|
+
allow_blank_does_not_match?
|
434
425
|
end
|
435
426
|
|
436
427
|
def allows_lower_value
|
@@ -616,16 +607,6 @@ EOT
|
|
616
607
|
@options[:allow_nil] && disallows_value_of(nil)
|
617
608
|
end
|
618
609
|
|
619
|
-
def allows_blank_value?
|
620
|
-
@options[:allow_blank] != true ||
|
621
|
-
BLANK_VALUES.all? { |value| allows_value_of(value) }
|
622
|
-
end
|
623
|
-
|
624
|
-
def disallows_blank_value?
|
625
|
-
@options[:allow_blank] &&
|
626
|
-
BLANK_VALUES.any? { |value| disallows_value_of(value) }
|
627
|
-
end
|
628
|
-
|
629
610
|
def inspected_array
|
630
611
|
Shoulda::Matchers::Util.inspect_values(@array).to_sentence(
|
631
612
|
two_words_connector: " or ",
|
@@ -232,13 +232,34 @@ module Shoulda
|
|
232
232
|
# it { should validate_length_of(:bio).is_at_least(15).allow_nil }
|
233
233
|
# end
|
234
234
|
#
|
235
|
-
# #
|
235
|
+
# # Minitest (Shoulda)
|
236
236
|
# class UserTest < ActiveSupport::TestCase
|
237
237
|
# should validate_length_of(:bio).is_at_least(15).allow_nil
|
238
238
|
# end
|
239
239
|
#
|
240
240
|
# @return [ValidateLengthOfMatcher]
|
241
241
|
#
|
242
|
+
# # ##### allow_blank
|
243
|
+
#
|
244
|
+
# Use `allow_blank` to assert that the attribute allows blank.
|
245
|
+
#
|
246
|
+
# class User
|
247
|
+
# include ActiveModel::Model
|
248
|
+
# attr_accessor :bio
|
249
|
+
#
|
250
|
+
# validates_length_of :bio, minimum: 15, allow_blank: true
|
251
|
+
# end
|
252
|
+
#
|
253
|
+
# # RSpec
|
254
|
+
# describe User do
|
255
|
+
# it { should validate_length_of(:bio).is_at_least(15).allow_blank }
|
256
|
+
# end
|
257
|
+
#
|
258
|
+
# # Minitest (Shoulda)
|
259
|
+
# class UserTest < ActiveSupport::TestCase
|
260
|
+
# should validate_length_of(:bio).is_at_least(15).allow_blank
|
261
|
+
# end
|
262
|
+
#
|
242
263
|
def validate_length_of(attr)
|
243
264
|
ValidateLengthOfMatcher.new(attr)
|
244
265
|
end
|
@@ -331,7 +352,8 @@ module Shoulda
|
|
331
352
|
|
332
353
|
lower_bound_matches? &&
|
333
354
|
upper_bound_matches? &&
|
334
|
-
allow_nil_matches?
|
355
|
+
allow_nil_matches? &&
|
356
|
+
allow_blank_matches?
|
335
357
|
end
|
336
358
|
|
337
359
|
def does_not_match?(subject)
|
@@ -339,7 +361,8 @@ module Shoulda
|
|
339
361
|
|
340
362
|
lower_bound_does_not_match? ||
|
341
363
|
upper_bound_does_not_match? ||
|
342
|
-
allow_nil_does_not_match?
|
364
|
+
allow_nil_does_not_match? ||
|
365
|
+
allow_blank_does_not_match?
|
343
366
|
end
|
344
367
|
|
345
368
|
private
|
@@ -376,6 +399,7 @@ module Shoulda
|
|
376
399
|
def disallows_lower_length?
|
377
400
|
!@options.key?(:minimum) ||
|
378
401
|
@options[:minimum] == 0 ||
|
402
|
+
(@options[:minimum] == 1 && expects_to_allow_blank?) ||
|
379
403
|
disallows_length_of?(
|
380
404
|
@options[:minimum] - 1,
|
381
405
|
translated_short_message
|
@@ -204,6 +204,33 @@ module Shoulda
|
|
204
204
|
# is_greater_than(21)
|
205
205
|
# end
|
206
206
|
#
|
207
|
+
# ##### is_other_than
|
208
|
+
#
|
209
|
+
# Use `is_other_than` to test usage of the `:other_than` option.
|
210
|
+
# This asserts that the attribute can take a number which is not equal to
|
211
|
+
# the given value.
|
212
|
+
#
|
213
|
+
# class Person
|
214
|
+
# include ActiveModel::Model
|
215
|
+
# attr_accessor :legal_age
|
216
|
+
#
|
217
|
+
# validates_numericality_of :legal_age, other_than: 21
|
218
|
+
# end
|
219
|
+
#
|
220
|
+
# # RSpec
|
221
|
+
# RSpec.describe Person, type: :model do
|
222
|
+
# it do
|
223
|
+
# should validate_numericality_of(:legal_age).
|
224
|
+
# is_other_than(21)
|
225
|
+
# end
|
226
|
+
# end
|
227
|
+
#
|
228
|
+
# # Minitest (Shoulda)
|
229
|
+
# class PersonTest < ActiveSupport::TestCase
|
230
|
+
# should validate_numericality_of(:legal_age).
|
231
|
+
# is_other_than(21)
|
232
|
+
# end
|
233
|
+
#
|
207
234
|
# ##### even
|
208
235
|
#
|
209
236
|
# Use `even` to test usage of the `:even` option. This asserts that the
|
@@ -395,6 +422,11 @@ module Shoulda
|
|
395
422
|
self
|
396
423
|
end
|
397
424
|
|
425
|
+
def is_other_than(value)
|
426
|
+
prepare_submatcher(comparison_matcher_for(value, :!=).for(@attribute))
|
427
|
+
self
|
428
|
+
end
|
429
|
+
|
398
430
|
def with_message(message)
|
399
431
|
@expects_custom_validation_message = true
|
400
432
|
@expected_message = message
|
@@ -3,6 +3,8 @@ module Shoulda
|
|
3
3
|
module ActiveModel
|
4
4
|
# @private
|
5
5
|
class ValidationMatcher
|
6
|
+
autoload :BuildDescription, 'shoulda/matchers/active_model/validation_matcher/build_description'
|
7
|
+
|
6
8
|
include Qualifiers::IgnoringInterferenceByWriter
|
7
9
|
|
8
10
|
def initialize(attribute)
|
@@ -24,6 +26,11 @@ module Shoulda
|
|
24
26
|
self
|
25
27
|
end
|
26
28
|
|
29
|
+
def allow_blank
|
30
|
+
options[:allow_blank] = true
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
27
34
|
def strict
|
28
35
|
@expects_strict = true
|
29
36
|
self
|
@@ -116,8 +123,20 @@ module Shoulda
|
|
116
123
|
)
|
117
124
|
end
|
118
125
|
|
126
|
+
def allow_blank_matches?
|
127
|
+
!expects_to_allow_blank? ||
|
128
|
+
blank_values.all? { |value| allows_value_of(value) }
|
129
|
+
end
|
130
|
+
|
131
|
+
def allow_blank_does_not_match?
|
132
|
+
expects_to_allow_blank? &&
|
133
|
+
blank_values.all? { |value| disallows_value_of(value) }
|
134
|
+
end
|
135
|
+
|
119
136
|
private
|
120
137
|
|
138
|
+
attr_reader :options
|
139
|
+
|
121
140
|
def overall_failure_message
|
122
141
|
Shoulda::Matchers.word_wrap(
|
123
142
|
"Expected #{model.name} to #{description}, but this could not be " +
|
@@ -161,6 +180,14 @@ module Shoulda
|
|
161
180
|
@last_submatcher_run = matcher
|
162
181
|
matcher.matches?(subject)
|
163
182
|
end
|
183
|
+
|
184
|
+
def expects_to_allow_blank?
|
185
|
+
options[:allow_blank]
|
186
|
+
end
|
187
|
+
|
188
|
+
def blank_values
|
189
|
+
['', ' ', "\n", "\r", "\t", "\f"]
|
190
|
+
end
|
164
191
|
end
|
165
192
|
end
|
166
193
|
end
|
@@ -1,26 +1,3 @@
|
|
1
|
-
require "shoulda/matchers/active_record/association_matcher"
|
2
|
-
require "shoulda/matchers/active_record/association_matchers"
|
3
|
-
require "shoulda/matchers/active_record/association_matchers/counter_cache_matcher"
|
4
|
-
require "shoulda/matchers/active_record/association_matchers/inverse_of_matcher"
|
5
|
-
require "shoulda/matchers/active_record/association_matchers/join_table_matcher"
|
6
|
-
require "shoulda/matchers/active_record/association_matchers/order_matcher"
|
7
|
-
require "shoulda/matchers/active_record/association_matchers/through_matcher"
|
8
|
-
require "shoulda/matchers/active_record/association_matchers/dependent_matcher"
|
9
|
-
require "shoulda/matchers/active_record/association_matchers/required_matcher"
|
10
|
-
require "shoulda/matchers/active_record/association_matchers/optional_matcher"
|
11
|
-
require "shoulda/matchers/active_record/association_matchers/source_matcher"
|
12
|
-
require "shoulda/matchers/active_record/association_matchers/model_reflector"
|
13
|
-
require "shoulda/matchers/active_record/association_matchers/model_reflection"
|
14
|
-
require "shoulda/matchers/active_record/association_matchers/option_verifier"
|
15
|
-
require "shoulda/matchers/active_record/have_db_column_matcher"
|
16
|
-
require "shoulda/matchers/active_record/have_db_index_matcher"
|
17
|
-
require "shoulda/matchers/active_record/have_readonly_attribute_matcher"
|
18
|
-
require "shoulda/matchers/active_record/have_rich_text_matcher"
|
19
|
-
require "shoulda/matchers/active_record/have_secure_token_matcher"
|
20
|
-
require "shoulda/matchers/active_record/serialize_matcher"
|
21
|
-
require "shoulda/matchers/active_record/accept_nested_attributes_for_matcher"
|
22
|
-
require "shoulda/matchers/active_record/define_enum_for_matcher"
|
23
|
-
require "shoulda/matchers/active_record/uniqueness"
|
24
1
|
require "shoulda/matchers/active_record/validate_uniqueness_of_matcher"
|
25
2
|
|
26
3
|
module Shoulda
|
@@ -28,6 +5,19 @@ module Shoulda
|
|
28
5
|
# This module provides matchers that are used to test behavior within
|
29
6
|
# ActiveRecord classes.
|
30
7
|
module ActiveRecord
|
8
|
+
autoload :AcceptNestedAttributesForMatcher, 'shoulda/matchers/active_record/accept_nested_attributes_for_matcher'
|
9
|
+
autoload :AssociationMatcher, 'shoulda/matchers/active_record/association_matcher'
|
10
|
+
autoload :AssociationMatchers, 'shoulda/matchers/active_record/association_matchers'
|
11
|
+
autoload :DefineEnumForMatcher, 'shoulda/matchers/active_record/define_enum_for_matcher'
|
12
|
+
autoload :HaveAttachedMatcher, 'shoulda/matchers/active_record/have_attached_matcher'
|
13
|
+
autoload :HaveDbColumnMatcher, 'shoulda/matchers/active_record/have_db_column_matcher'
|
14
|
+
autoload :HaveDbIndexMatcher, 'shoulda/matchers/active_record/have_db_index_matcher'
|
15
|
+
autoload :HaveImplicitOrderColumnMatcher, 'shoulda/matchers/active_record/have_implicit_order_column'
|
16
|
+
autoload :HaveReadonlyAttributeMatcher, 'shoulda/matchers/active_record/have_readonly_attribute_matcher'
|
17
|
+
autoload :HaveRichText, 'shoulda/matchers/active_record/have_rich_text_matcher'
|
18
|
+
autoload :HaveSecureTokenMatcher, 'shoulda/matchers/active_record/have_secure_token_matcher'
|
19
|
+
autoload :SerializeMatcher, 'shoulda/matchers/active_record/serialize_matcher'
|
20
|
+
autoload :Uniqueness, 'shoulda/matchers/active_record/uniqueness'
|
31
21
|
end
|
32
22
|
end
|
33
23
|
end
|
@@ -920,21 +920,21 @@ module Shoulda
|
|
920
920
|
# asserts that the table you're referring to actually exists.
|
921
921
|
#
|
922
922
|
# class Person < ActiveRecord::Base
|
923
|
-
# has_and_belongs_to_many :issues, join_table:
|
923
|
+
# has_and_belongs_to_many :issues, join_table: :people_tickets
|
924
924
|
# end
|
925
925
|
#
|
926
926
|
# # RSpec
|
927
927
|
# RSpec.describe Person, type: :model do
|
928
928
|
# it do
|
929
929
|
# should have_and_belong_to_many(:issues).
|
930
|
-
# join_table(
|
930
|
+
# join_table(:people_tickets)
|
931
931
|
# end
|
932
932
|
# end
|
933
933
|
#
|
934
934
|
# # Minitest (Shoulda)
|
935
935
|
# class PersonTest < ActiveSupport::TestCase
|
936
936
|
# should have_and_belong_to_many(:issues).
|
937
|
-
# join_table(
|
937
|
+
# join_table(:people_tickets)
|
938
938
|
# end
|
939
939
|
#
|
940
940
|
# ##### validate
|
@@ -1144,6 +1144,7 @@ module Shoulda
|
|
1144
1144
|
@subject = subject
|
1145
1145
|
association_exists? &&
|
1146
1146
|
macro_correct? &&
|
1147
|
+
validate_inverse_of_through_association &&
|
1147
1148
|
(polymorphic? || class_exists?) &&
|
1148
1149
|
foreign_key_exists? &&
|
1149
1150
|
primary_key_exists? &&
|
@@ -1198,7 +1199,14 @@ module Shoulda
|
|
1198
1199
|
end
|
1199
1200
|
|
1200
1201
|
def expectation
|
1201
|
-
|
1202
|
+
expectation =
|
1203
|
+
"#{model_class.name} to have a #{macro} association called #{name}"
|
1204
|
+
|
1205
|
+
if through?
|
1206
|
+
expectation << " through #{reflector.has_and_belongs_to_many_name}"
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
expectation
|
1202
1210
|
end
|
1203
1211
|
|
1204
1212
|
def missing_options
|
@@ -1241,6 +1249,14 @@ module Shoulda
|
|
1241
1249
|
end
|
1242
1250
|
end
|
1243
1251
|
|
1252
|
+
def validate_inverse_of_through_association
|
1253
|
+
reflector.validate_inverse_of_through_association!
|
1254
|
+
true
|
1255
|
+
rescue ::ActiveRecord::ActiveRecordError => error
|
1256
|
+
@missing = error.message
|
1257
|
+
false
|
1258
|
+
end
|
1259
|
+
|
1244
1260
|
def macro_supports_primary_key?
|
1245
1261
|
macro == :belongs_to ||
|
1246
1262
|
([:has_many, :has_one].include?(macro) && !through?)
|
@@ -3,6 +3,18 @@ module Shoulda
|
|
3
3
|
module ActiveRecord
|
4
4
|
# @private
|
5
5
|
module AssociationMatchers
|
6
|
+
autoload :CounterCacheMatcher, 'shoulda/matchers/active_record/association_matchers/counter_cache_matcher'
|
7
|
+
autoload :InverseOfMatcher, 'shoulda/matchers/active_record/association_matchers/inverse_of_matcher'
|
8
|
+
autoload :JoinTableMatcher, 'shoulda/matchers/active_record/association_matchers/join_table_matcher'
|
9
|
+
autoload :OrderMatcher, 'shoulda/matchers/active_record/association_matchers/order_matcher'
|
10
|
+
autoload :ThroughMatcher, 'shoulda/matchers/active_record/association_matchers/through_matcher'
|
11
|
+
autoload :DependentMatcher, 'shoulda/matchers/active_record/association_matchers/dependent_matcher'
|
12
|
+
autoload :RequiredMatcher, 'shoulda/matchers/active_record/association_matchers/required_matcher'
|
13
|
+
autoload :OptionalMatcher, 'shoulda/matchers/active_record/association_matchers/optional_matcher'
|
14
|
+
autoload :SourceMatcher, 'shoulda/matchers/active_record/association_matchers/source_matcher'
|
15
|
+
autoload :ModelReflector, 'shoulda/matchers/active_record/association_matchers/model_reflector'
|
16
|
+
autoload :ModelReflection, 'shoulda/matchers/active_record/association_matchers/model_reflection'
|
17
|
+
autoload :OptionVerifier, 'shoulda/matchers/active_record/association_matchers/option_verifier'
|
6
18
|
end
|
7
19
|
end
|
8
20
|
end
|