shoulda-matchers 4.4.1 → 4.5.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 +22 -0
- data/README.md +7 -9
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +4 -2
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +3 -2
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +26 -21
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +6 -8
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +6 -8
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +16 -13
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +2 -1
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -6
- data/lib/shoulda/matchers/action_controller/route_params.rb +1 -1
- data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +18 -16
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +29 -27
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -5
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +51 -25
- data/lib/shoulda/matchers/active_model/helpers.rb +1 -1
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -34
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +9 -1
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +8 -7
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +26 -25
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +6 -6
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +39 -26
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +2 -2
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +6 -6
- data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +2 -4
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
- data/lib/shoulda/matchers/active_model/validator.rb +3 -3
- data/lib/shoulda/matchers/active_record.rb +26 -26
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +6 -3
- data/lib/shoulda/matchers/active_record/association_matcher.rb +80 -40
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
- data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -9
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +12 -7
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +23 -5
- data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +3 -3
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +8 -8
- data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +46 -8
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +39 -17
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +7 -7
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +12 -10
- data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +11 -7
- data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +2 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +13 -9
- data/lib/shoulda/matchers/active_record/uniqueness.rb +1 -1
- data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
- data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +78 -71
- data/lib/shoulda/matchers/doublespeak.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
- data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
- data/lib/shoulda/matchers/doublespeak/object_double.rb +1 -1
- data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
- data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
- data/lib/shoulda/matchers/error.rb +1 -1
- data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +14 -13
- data/lib/shoulda/matchers/integrations/configuration.rb +1 -1
- data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
- data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
- data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
- data/lib/shoulda/matchers/rails_shim.rb +5 -3
- data/lib/shoulda/matchers/util.rb +7 -2
- data/lib/shoulda/matchers/util/word_wrap.rb +7 -7
- data/lib/shoulda/matchers/version.rb +1 -1
- data/lib/shoulda/matchers/warn.rb +3 -3
- data/shoulda-matchers.gemspec +10 -7
- metadata +11 -10
@@ -260,11 +260,11 @@ validation for you? Instead of using `validate_presence_of`, try
|
|
260
260
|
|
261
261
|
def reason_for_existing_presence_validation
|
262
262
|
if belongs_to_association_configured_to_be_required?
|
263
|
-
"you've instructed your `belongs_to` association to add a "
|
263
|
+
"you've instructed your `belongs_to` association to add a "\
|
264
264
|
'presence validation to the attribute'
|
265
265
|
else
|
266
266
|
# assume ::ActiveRecord::Base.belongs_to_required_by_default == true
|
267
|
-
'ActiveRecord is configured to add a presence validation to all '
|
267
|
+
'ActiveRecord is configured to add a presence validation to all '\
|
268
268
|
'`belongs_to` associations, and this includes yours'
|
269
269
|
end
|
270
270
|
end
|
@@ -67,7 +67,7 @@ module Shoulda
|
|
67
67
|
message << "\n"
|
68
68
|
message << Shoulda::Matchers.word_wrap(
|
69
69
|
failure_reason,
|
70
|
-
indent: 2
|
70
|
+
indent: 2,
|
71
71
|
)
|
72
72
|
end
|
73
73
|
end
|
@@ -79,7 +79,7 @@ module Shoulda
|
|
79
79
|
message << "\n"
|
80
80
|
message << Shoulda::Matchers.word_wrap(
|
81
81
|
failure_reason,
|
82
|
-
indent: 2
|
82
|
+
indent: 2,
|
83
83
|
)
|
84
84
|
end
|
85
85
|
end
|
@@ -137,15 +137,15 @@ module Shoulda
|
|
137
137
|
|
138
138
|
def overall_failure_message
|
139
139
|
Shoulda::Matchers.word_wrap(
|
140
|
-
"Expected #{model.name} to #{description}, but this could not be "
|
141
|
-
'proved.'
|
140
|
+
"Expected #{model.name} to #{description}, but this could not be "\
|
141
|
+
'proved.',
|
142
142
|
)
|
143
143
|
end
|
144
144
|
|
145
145
|
def overall_failure_message_when_negated
|
146
146
|
Shoulda::Matchers.word_wrap(
|
147
|
-
"Expected #{model.name} not to #{description}, but this could "
|
148
|
-
'not be proved.'
|
147
|
+
"Expected #{model.name} not to #{description}, but this could "\
|
148
|
+
'not be proved.',
|
149
149
|
)
|
150
150
|
end
|
151
151
|
|
@@ -15,10 +15,8 @@ module Shoulda
|
|
15
15
|
|
16
16
|
def call
|
17
17
|
if description_clauses_for_qualifiers.any?
|
18
|
-
main_description
|
19
|
-
|
20
|
-
', ' +
|
21
|
-
description_clauses_for_qualifiers.to_sentence
|
18
|
+
"#{main_description}#{clause_for_allow_blank_or_nil},"\
|
19
|
+
" #{description_clauses_for_qualifiers.to_sentence}"
|
22
20
|
else
|
23
21
|
main_description + clause_for_allow_blank_or_nil
|
24
22
|
end
|
@@ -5,7 +5,7 @@ module Shoulda
|
|
5
5
|
class ValidationMessageFinder
|
6
6
|
include Helpers
|
7
7
|
|
8
|
-
def initialize(instance, attribute, context=nil)
|
8
|
+
def initialize(instance, attribute, context = nil)
|
9
9
|
@instance = instance
|
10
10
|
@attribute = attribute
|
11
11
|
@context = context
|
@@ -50,7 +50,7 @@ module Shoulda
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def validated_instance
|
53
|
-
@
|
53
|
+
@_validated_instance ||= validate_instance
|
54
54
|
end
|
55
55
|
|
56
56
|
def validate_instance
|
@@ -58,8 +58,6 @@ module Shoulda
|
|
58
58
|
@instance
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
65
|
-
|
@@ -108,14 +108,14 @@ module Shoulda
|
|
108
108
|
{
|
109
109
|
all_validation_errors: all_validation_errors,
|
110
110
|
validation_error_messages: validation_error_messages,
|
111
|
-
validation_exception_message: nil
|
111
|
+
validation_exception_message: nil,
|
112
112
|
}
|
113
|
-
rescue ::ActiveModel::StrictValidationFailed =>
|
113
|
+
rescue ::ActiveModel::StrictValidationFailed => e
|
114
114
|
@captured_validation_exception = true
|
115
115
|
{
|
116
116
|
all_validation_errors: nil,
|
117
117
|
validation_error_messages: [],
|
118
|
-
validation_exception_message:
|
118
|
+
validation_exception_message: e.message,
|
119
119
|
}
|
120
120
|
end
|
121
121
|
end
|
@@ -1,29 +1,29 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
21
|
-
require
|
22
|
-
require
|
23
|
-
require
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
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_implicit_order_column'
|
18
|
+
require 'shoulda/matchers/active_record/have_readonly_attribute_matcher'
|
19
|
+
require 'shoulda/matchers/active_record/have_rich_text_matcher'
|
20
|
+
require 'shoulda/matchers/active_record/have_secure_token_matcher'
|
21
|
+
require 'shoulda/matchers/active_record/serialize_matcher'
|
22
|
+
require 'shoulda/matchers/active_record/accept_nested_attributes_for_matcher'
|
23
|
+
require 'shoulda/matchers/active_record/define_enum_for_matcher'
|
24
|
+
require 'shoulda/matchers/active_record/uniqueness'
|
25
|
+
require 'shoulda/matchers/active_record/validate_uniqueness_of_matcher'
|
26
|
+
require 'shoulda/matchers/active_record/have_attached_matcher'
|
27
27
|
|
28
28
|
module Shoulda
|
29
29
|
module Matchers
|
@@ -158,17 +158,20 @@ module Shoulda
|
|
158
158
|
end
|
159
159
|
|
160
160
|
def allow_destroy_correct?
|
161
|
-
failure_message = "#{should_or_should_not(@options[:allow_destroy])}
|
161
|
+
failure_message = "#{should_or_should_not(@options[:allow_destroy])}"\
|
162
|
+
' allow destroy'
|
162
163
|
verify_option_is_correct(:allow_destroy, failure_message)
|
163
164
|
end
|
164
165
|
|
165
166
|
def limit_correct?
|
166
|
-
failure_message = "limit should be #{@options[:limit]},
|
167
|
+
failure_message = "limit should be #{@options[:limit]},"\
|
168
|
+
" got #{config[:limit]}"
|
167
169
|
verify_option_is_correct(:limit, failure_message)
|
168
170
|
end
|
169
171
|
|
170
172
|
def update_only_correct?
|
171
|
-
failure_message = "#{should_or_should_not(@options[:update_only])}
|
173
|
+
failure_message = "#{should_or_should_not(@options[:update_only])}"\
|
174
|
+
' be update only'
|
172
175
|
verify_option_is_correct(:update_only, failure_message)
|
173
176
|
end
|
174
177
|
|
@@ -985,6 +985,13 @@ module Shoulda
|
|
985
985
|
|
986
986
|
# @private
|
987
987
|
class AssociationMatcher
|
988
|
+
MACROS = {
|
989
|
+
'belongs_to' => 'belong to',
|
990
|
+
'has_many' => 'have many',
|
991
|
+
'has_one' => 'have one',
|
992
|
+
'has_and_belongs_to_many' => 'have and belong to many',
|
993
|
+
}.freeze
|
994
|
+
|
988
995
|
delegate :reflection, :model_class, :associated_class, :through?,
|
989
996
|
:polymorphic?, to: :reflector
|
990
997
|
|
@@ -1128,7 +1135,9 @@ module Shoulda
|
|
1128
1135
|
|
1129
1136
|
def description
|
1130
1137
|
description = "#{macro_description} #{name}"
|
1131
|
-
|
1138
|
+
if options.key?(:class_name)
|
1139
|
+
description += " class_name => #{options[:class_name]}"
|
1140
|
+
end
|
1132
1141
|
[description, submatchers.map(&:description)].flatten.join(' ')
|
1133
1142
|
end
|
1134
1143
|
|
@@ -1163,7 +1172,8 @@ module Shoulda
|
|
1163
1172
|
end
|
1164
1173
|
|
1165
1174
|
def option_verifier
|
1166
|
-
@
|
1175
|
+
@_option_verifier ||=
|
1176
|
+
AssociationMatchers::OptionVerifier.new(reflector)
|
1167
1177
|
end
|
1168
1178
|
|
1169
1179
|
protected
|
@@ -1171,7 +1181,7 @@ module Shoulda
|
|
1171
1181
|
attr_reader :submatchers, :missing, :subject, :macro
|
1172
1182
|
|
1173
1183
|
def reflector
|
1174
|
-
@
|
1184
|
+
@_reflector ||= AssociationMatchers::ModelReflector.new(subject, name)
|
1175
1185
|
end
|
1176
1186
|
|
1177
1187
|
def add_submatcher(matcher_class, *args)
|
@@ -1186,16 +1196,7 @@ module Shoulda
|
|
1186
1196
|
end
|
1187
1197
|
|
1188
1198
|
def macro_description
|
1189
|
-
|
1190
|
-
when 'belongs_to'
|
1191
|
-
'belong to'
|
1192
|
-
when 'has_many'
|
1193
|
-
'have many'
|
1194
|
-
when 'has_one'
|
1195
|
-
'have one'
|
1196
|
-
when 'has_and_belongs_to_many'
|
1197
|
-
'have and belong to many'
|
1198
|
-
end
|
1199
|
+
MACROS[macro.to_s]
|
1199
1200
|
end
|
1200
1201
|
|
1201
1202
|
def expectation
|
@@ -1215,14 +1216,14 @@ module Shoulda
|
|
1215
1216
|
end
|
1216
1217
|
|
1217
1218
|
def failing_submatchers
|
1218
|
-
@
|
1219
|
-
|
1219
|
+
@_failing_submatchers ||= submatchers.reject do |matcher|
|
1220
|
+
matcher.matches?(subject)
|
1220
1221
|
end
|
1221
1222
|
end
|
1222
1223
|
|
1223
1224
|
def missing_options_for_failing_submatchers
|
1224
|
-
if defined?(@
|
1225
|
-
@
|
1225
|
+
if defined?(@_failing_submatchers)
|
1226
|
+
@_failing_submatchers.map(&:missing_option)
|
1226
1227
|
else
|
1227
1228
|
[]
|
1228
1229
|
end
|
@@ -1252,8 +1253,8 @@ module Shoulda
|
|
1252
1253
|
def validate_inverse_of_through_association
|
1253
1254
|
reflector.validate_inverse_of_through_association!
|
1254
1255
|
true
|
1255
|
-
rescue ::ActiveRecord::ActiveRecordError =>
|
1256
|
-
@missing =
|
1256
|
+
rescue ::ActiveRecord::ActiveRecordError => e
|
1257
|
+
@missing = e.message
|
1257
1258
|
false
|
1258
1259
|
end
|
1259
1260
|
|
@@ -1282,10 +1283,14 @@ module Shoulda
|
|
1282
1283
|
|
1283
1284
|
def class_name_correct?
|
1284
1285
|
if options.key?(:class_name)
|
1285
|
-
if option_verifier.correct_for_constant?(
|
1286
|
+
if option_verifier.correct_for_constant?(
|
1287
|
+
:class_name,
|
1288
|
+
options[:class_name],
|
1289
|
+
)
|
1286
1290
|
true
|
1287
1291
|
else
|
1288
|
-
@missing = "#{name} should resolve to #{options[:class_name]}
|
1292
|
+
@missing = "#{name} should resolve to #{options[:class_name]}"\
|
1293
|
+
' for class_name'
|
1289
1294
|
false
|
1290
1295
|
end
|
1291
1296
|
else
|
@@ -1294,7 +1299,10 @@ module Shoulda
|
|
1294
1299
|
end
|
1295
1300
|
|
1296
1301
|
def join_table_correct?
|
1297
|
-
if
|
1302
|
+
if (
|
1303
|
+
macro != :has_and_belongs_to_many ||
|
1304
|
+
join_table_matcher.matches?(@subject)
|
1305
|
+
)
|
1298
1306
|
true
|
1299
1307
|
else
|
1300
1308
|
@missing = join_table_matcher.failure_message
|
@@ -1303,8 +1311,10 @@ module Shoulda
|
|
1303
1311
|
end
|
1304
1312
|
|
1305
1313
|
def join_table_matcher
|
1306
|
-
@
|
1307
|
-
|
1314
|
+
@_join_table_matcher ||= AssociationMatchers::JoinTableMatcher.new(
|
1315
|
+
self,
|
1316
|
+
reflector,
|
1317
|
+
)
|
1308
1318
|
end
|
1309
1319
|
|
1310
1320
|
def class_exists?
|
@@ -1317,10 +1327,14 @@ module Shoulda
|
|
1317
1327
|
|
1318
1328
|
def autosave_correct?
|
1319
1329
|
if options.key?(:autosave)
|
1320
|
-
if option_verifier.correct_for_boolean?(
|
1330
|
+
if option_verifier.correct_for_boolean?(
|
1331
|
+
:autosave,
|
1332
|
+
options[:autosave],
|
1333
|
+
)
|
1321
1334
|
true
|
1322
1335
|
else
|
1323
|
-
@missing = "#{name} should have autosave set to
|
1336
|
+
@missing = "#{name} should have autosave set to"\
|
1337
|
+
" #{options[:autosave]}"
|
1324
1338
|
false
|
1325
1339
|
end
|
1326
1340
|
else
|
@@ -1333,23 +1347,27 @@ module Shoulda
|
|
1333
1347
|
|
1334
1348
|
if option_verifier.correct_for_boolean?(
|
1335
1349
|
:index_errors,
|
1336
|
-
options[:index_errors]
|
1350
|
+
options[:index_errors],
|
1337
1351
|
)
|
1338
1352
|
true
|
1339
1353
|
else
|
1340
1354
|
@missing =
|
1341
1355
|
"#{name} should have index_errors set to " +
|
1342
|
-
|
1356
|
+
options[:index_errors].to_s
|
1343
1357
|
false
|
1344
1358
|
end
|
1345
1359
|
end
|
1346
1360
|
|
1347
1361
|
def conditions_correct?
|
1348
1362
|
if options.key?(:conditions)
|
1349
|
-
if option_verifier.correct_for_relation_clause?(
|
1363
|
+
if option_verifier.correct_for_relation_clause?(
|
1364
|
+
:conditions,
|
1365
|
+
options[:conditions],
|
1366
|
+
)
|
1350
1367
|
true
|
1351
1368
|
else
|
1352
|
-
@missing = "#{name} should have the following conditions:
|
1369
|
+
@missing = "#{name} should have the following conditions:" +
|
1370
|
+
" #{options[:conditions]}"
|
1353
1371
|
false
|
1354
1372
|
end
|
1355
1373
|
else
|
@@ -1376,22 +1394,38 @@ module Shoulda
|
|
1376
1394
|
end
|
1377
1395
|
|
1378
1396
|
def class_has_foreign_key?(klass)
|
1379
|
-
if options.key?(:foreign_key)
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
@missing = "#{klass} does not have a #{foreign_key} foreign key."
|
1397
|
+
if options.key?(:foreign_key) && !foreign_key_correct?
|
1398
|
+
@missing = foreign_key_failure_message(klass, options[:foreign_key])
|
1399
|
+
false
|
1400
|
+
elsif !column_names_for(klass).include?(foreign_key)
|
1401
|
+
@missing = foreign_key_failure_message(klass, foreign_key)
|
1385
1402
|
false
|
1403
|
+
else
|
1404
|
+
true
|
1386
1405
|
end
|
1387
1406
|
end
|
1388
1407
|
|
1408
|
+
def foreign_key_correct?
|
1409
|
+
option_verifier.correct_for_string?(
|
1410
|
+
:foreign_key,
|
1411
|
+
options[:foreign_key],
|
1412
|
+
)
|
1413
|
+
end
|
1414
|
+
|
1415
|
+
def foreign_key_failure_message(klass, foreign_key)
|
1416
|
+
"#{klass} does not have a #{foreign_key} foreign key."
|
1417
|
+
end
|
1418
|
+
|
1389
1419
|
def primary_key_correct?(klass)
|
1390
1420
|
if options.key?(:primary_key)
|
1391
|
-
if option_verifier.correct_for_string?(
|
1421
|
+
if option_verifier.correct_for_string?(
|
1422
|
+
:primary_key,
|
1423
|
+
options[:primary_key],
|
1424
|
+
)
|
1392
1425
|
true
|
1393
1426
|
else
|
1394
|
-
@missing = "#{klass} does not have a #{options[:primary_key]}
|
1427
|
+
@missing = "#{klass} does not have a #{options[:primary_key]}"\
|
1428
|
+
' primary key'
|
1395
1429
|
false
|
1396
1430
|
end
|
1397
1431
|
else
|
@@ -1410,8 +1444,14 @@ module Shoulda
|
|
1410
1444
|
end
|
1411
1445
|
|
1412
1446
|
def foreign_key_reflection
|
1413
|
-
if
|
1414
|
-
|
1447
|
+
if (
|
1448
|
+
[:has_one, :has_many].include?(macro) &&
|
1449
|
+
reflection.options.include?(:inverse_of) &&
|
1450
|
+
reflection.options[:inverse_of] != false
|
1451
|
+
)
|
1452
|
+
associated_class.reflect_on_association(
|
1453
|
+
reflection.options[:inverse_of],
|
1454
|
+
)
|
1415
1455
|
else
|
1416
1456
|
reflection
|
1417
1457
|
end
|
@@ -19,7 +19,10 @@ module Shoulda
|
|
19
19
|
def matches?(subject)
|
20
20
|
self.subject = ModelReflector.new(subject, name)
|
21
21
|
|
22
|
-
if option_verifier.correct_for_string?(
|
22
|
+
if option_verifier.correct_for_string?(
|
23
|
+
:counter_cache,
|
24
|
+
counter_cache,
|
25
|
+
)
|
23
26
|
true
|
24
27
|
else
|
25
28
|
self.missing_option = "#{name} should have #{description}"
|
@@ -32,7 +35,7 @@ module Shoulda
|
|
32
35
|
attr_accessor :subject, :counter_cache, :name
|
33
36
|
|
34
37
|
def option_verifier
|
35
|
-
@
|
38
|
+
@_option_verifier ||= OptionVerifier.new(subject)
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|