shoulda-matchers 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -0
- data/Gemfile.lock +1 -1
- data/NEWS.md +25 -1
- data/README.md +1 -2
- data/gemfiles/3.0.gemfile.lock +1 -1
- data/gemfiles/3.1.gemfile.lock +1 -1
- data/gemfiles/3.2.gemfile.lock +1 -1
- data/lib/shoulda/matchers/action_controller.rb +1 -0
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +81 -0
- data/lib/shoulda/matchers/active_model/comparison_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +5 -0
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +15 -1
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +2 -8
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +2 -0
- data/lib/shoulda/matchers/active_record.rb +5 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +90 -113
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +35 -0
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +35 -0
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +37 -0
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +35 -0
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +57 -0
- data/lib/shoulda/matchers/version.rb +1 -1
- data/spec/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +63 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +1 -1
- data/spec/shoulda/matchers/active_model/comparison_matcher_spec.rb +5 -0
- data/spec/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +18 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +10 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +3 -3
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +13 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +14 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +49 -1
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +39 -4
- metadata +11 -3
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
data/NEWS.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# HEAD
|
2
2
|
|
3
|
+
# v 2.3.0
|
4
|
+
|
5
|
+
* Fix a bug in `ensure_inclusion_of` that would cause issues with using
|
6
|
+
`in_array` with an integer value.
|
7
|
+
|
8
|
+
* Add support for PostgreSQL UUID columns to `validates_uniqueness_of` (#334).
|
9
|
+
|
10
|
+
* Fix `validates_numericality_of` so that `is_equal_to` submatcher works
|
11
|
+
correctly (#326).
|
12
|
+
|
13
|
+
* Fix context support for validation matchers and disallowed values (#313).
|
14
|
+
|
15
|
+
* Add a `counter_cache` submatcher for `belongs_to` associations (#311).
|
16
|
+
|
17
|
+
* Add a `rescue_from` matcher for Rails controllers which checks that the
|
18
|
+
correct ActiveSupport call has been made and that the handlers exist without
|
19
|
+
actually throwing an exception (#287).
|
20
|
+
|
21
|
+
* Changed the scope of AssociationMatcher methods from protected to private.
|
22
|
+
|
23
|
+
* Extracted `#order`, `#through`, and `#dependent` from AssociationMatcher as
|
24
|
+
their own submatchers.
|
25
|
+
|
3
26
|
# v 2.2.0
|
4
27
|
|
5
28
|
* Fix `have_and_belong_to_many` matcher issue for Rails 4.
|
@@ -15,7 +38,8 @@
|
|
15
38
|
* Add missing `failure_message_for_should_not` implementations to
|
16
39
|
`validate_numericality_of` and its submatchers
|
17
40
|
|
18
|
-
* Support validation contexts for testing validations `on: :create` and when
|
41
|
+
* Support validation contexts for testing validations `on: :create` and when
|
42
|
+
using custom contexts like `model.valid?(:my_context)`.
|
19
43
|
|
20
44
|
* Fix a bug in validations with autosaved models.
|
21
45
|
|
data/README.md
CHANGED
@@ -51,8 +51,6 @@ Matchers to test common patterns:
|
|
51
51
|
|
52
52
|
```ruby
|
53
53
|
describe PostsController, "#show" do
|
54
|
-
it { should permit(:title, :body).for(:create) }
|
55
|
-
|
56
54
|
context "for a fictional user" do
|
57
55
|
before do
|
58
56
|
get :show, :id => 1
|
@@ -61,6 +59,7 @@ describe PostsController, "#show" do
|
|
61
59
|
it { should respond_with(:success) }
|
62
60
|
it { should render_template(:show) }
|
63
61
|
it { should_not set_the_flash }
|
62
|
+
it { should rescue_from(ActiveRecord::RecordNotFound).with(:render_404) }
|
64
63
|
end
|
65
64
|
end
|
66
65
|
```
|
data/gemfiles/3.0.gemfile.lock
CHANGED
data/gemfiles/3.1.gemfile.lock
CHANGED
data/gemfiles/3.2.gemfile.lock
CHANGED
@@ -6,6 +6,7 @@ require 'shoulda/matchers/action_controller/set_session_matcher'
|
|
6
6
|
require 'shoulda/matchers/action_controller/route_matcher'
|
7
7
|
require 'shoulda/matchers/action_controller/redirect_to_matcher'
|
8
8
|
require 'shoulda/matchers/action_controller/render_template_matcher'
|
9
|
+
require 'shoulda/matchers/action_controller/rescue_from_matcher'
|
9
10
|
|
10
11
|
module Shoulda
|
11
12
|
module Matchers
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActionController
|
4
|
+
def rescue_from(exception)
|
5
|
+
RescueFromMatcher.new exception
|
6
|
+
end
|
7
|
+
|
8
|
+
class RescueFromMatcher
|
9
|
+
def initialize(exception)
|
10
|
+
@exception = exception
|
11
|
+
end
|
12
|
+
|
13
|
+
def with(method)
|
14
|
+
@expected_method = method
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def matches?(controller)
|
19
|
+
@controller = controller
|
20
|
+
rescues_from_exception? && method_name_matches? && handler_exists?
|
21
|
+
end
|
22
|
+
|
23
|
+
def description
|
24
|
+
description = "rescues from #{exception}"
|
25
|
+
description << " with ##{expected_method}" if expected_method
|
26
|
+
description
|
27
|
+
end
|
28
|
+
|
29
|
+
def failure_message_for_should
|
30
|
+
"Expected #{expectation}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def failure_message_for_should_not
|
34
|
+
"Did not expect #{expectation}"
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :controller, :exception, :expected_method, :handlers
|
40
|
+
|
41
|
+
def expectation
|
42
|
+
expectation = "#{controller} to rescue from #{exception}"
|
43
|
+
|
44
|
+
if expected_method && !method_name_matches?
|
45
|
+
expectation << " with ##{expected_method}"
|
46
|
+
end
|
47
|
+
|
48
|
+
unless handler_exists?
|
49
|
+
expectation << " but #{controller} does not respond to #{expected_method}"
|
50
|
+
end
|
51
|
+
expectation
|
52
|
+
end
|
53
|
+
|
54
|
+
def rescues_from_exception?
|
55
|
+
@handlers = controller.rescue_handlers.select do |handler|
|
56
|
+
handler.first == exception.to_s
|
57
|
+
end
|
58
|
+
handlers.any?
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_name_matches?
|
62
|
+
if expected_method.present?
|
63
|
+
handlers.any? do |handler|
|
64
|
+
handler.last == expected_method
|
65
|
+
end
|
66
|
+
else
|
67
|
+
true
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def handler_exists?
|
72
|
+
if expected_method.present?
|
73
|
+
controller.respond_to? expected_method
|
74
|
+
else
|
75
|
+
true
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -23,6 +23,7 @@ module Shoulda # :nodoc:
|
|
23
23
|
|
24
24
|
class EnsureInclusionOfMatcher < ValidationMatcher # :nodoc:
|
25
25
|
ARBITRARY_OUTSIDE_STRING = 'shouldamatchersteststring'
|
26
|
+
ARBITRARY_OUTSIDE_FIXNUM = 123456789
|
26
27
|
|
27
28
|
def initialize(attribute)
|
28
29
|
super(attribute)
|
@@ -144,8 +145,21 @@ module Shoulda # :nodoc:
|
|
144
145
|
end
|
145
146
|
|
146
147
|
def value_outside_of_array
|
147
|
-
if @array.include?(
|
148
|
+
if @array.include?(outside_value)
|
148
149
|
raise CouldNotDetermineValueOutsideOfArray
|
150
|
+
else
|
151
|
+
outside_value
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def outside_value
|
156
|
+
@outside_value ||= find_outside_value
|
157
|
+
end
|
158
|
+
|
159
|
+
def find_outside_value
|
160
|
+
case @subject.send(@attribute.to_s)
|
161
|
+
when Fixnum
|
162
|
+
ARBITRARY_OUTSIDE_FIXNUM
|
149
163
|
else
|
150
164
|
ARBITRARY_OUTSIDE_STRING
|
151
165
|
end
|
@@ -122,7 +122,7 @@ module Shoulda # :nodoc:
|
|
122
122
|
end
|
123
123
|
|
124
124
|
def failing_submatchers
|
125
|
-
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject
|
125
|
+
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject) }
|
126
126
|
end
|
127
127
|
|
128
128
|
def allowed_types
|
@@ -77,14 +77,6 @@ module Shoulda # :nodoc:
|
|
77
77
|
allows_nil?
|
78
78
|
end
|
79
79
|
|
80
|
-
def description
|
81
|
-
result = 'require '
|
82
|
-
result << 'case sensitive ' unless @options[:case_insensitive]
|
83
|
-
result << "unique value for #{@attribute}"
|
84
|
-
result << " scoped to #{@options[:scopes].join(', ')}" if @options[:scopes].present?
|
85
|
-
result
|
86
|
-
end
|
87
|
-
|
88
80
|
private
|
89
81
|
|
90
82
|
def allows_nil?
|
@@ -197,6 +189,8 @@ module Shoulda # :nodoc:
|
|
197
189
|
'0'
|
198
190
|
elsif column.type == :datetime
|
199
191
|
DateTime.now
|
192
|
+
elsif column.type == :uuid
|
193
|
+
SecureRandom.uuid
|
200
194
|
else
|
201
195
|
0
|
202
196
|
end
|
@@ -58,6 +58,7 @@ module Shoulda # :nodoc:
|
|
58
58
|
matcher = AllowValueMatcher.
|
59
59
|
new(value).
|
60
60
|
for(@attribute).
|
61
|
+
on(@context).
|
61
62
|
with_message(message)
|
62
63
|
|
63
64
|
if strict?
|
@@ -71,6 +72,7 @@ module Shoulda # :nodoc:
|
|
71
72
|
matcher = DisallowValueMatcher.
|
72
73
|
new(value).
|
73
74
|
for(@attribute).
|
75
|
+
on(@context).
|
74
76
|
with_message(message)
|
75
77
|
|
76
78
|
if strict?
|
@@ -1,4 +1,9 @@
|
|
1
1
|
require 'shoulda/matchers/active_record/association_matcher'
|
2
|
+
require 'shoulda/matchers/active_record/association_matchers/counter_cache_matcher'
|
3
|
+
require 'shoulda/matchers/active_record/association_matchers/order_matcher'
|
4
|
+
require 'shoulda/matchers/active_record/association_matchers/through_matcher'
|
5
|
+
require 'shoulda/matchers/active_record/association_matchers/dependent_matcher'
|
6
|
+
require 'shoulda/matchers/active_record/association_matchers/model_reflector'
|
2
7
|
require 'shoulda/matchers/active_record/have_db_column_matcher'
|
3
8
|
require 'shoulda/matchers/active_record/have_db_index_matcher'
|
4
9
|
require 'shoulda/matchers/active_record/have_readonly_attribute_matcher'
|
@@ -76,20 +76,31 @@ module Shoulda # :nodoc:
|
|
76
76
|
@macro = macro
|
77
77
|
@name = name
|
78
78
|
@options = {}
|
79
|
+
@submatchers = []
|
80
|
+
@missing = ''
|
79
81
|
end
|
80
82
|
|
81
83
|
def through(through)
|
82
|
-
|
84
|
+
through_matcher = AssociationMatchers::ThroughMatcher.new(through, name)
|
85
|
+
add_submatcher(through_matcher)
|
83
86
|
self
|
84
87
|
end
|
85
88
|
|
86
89
|
def dependent(dependent)
|
87
|
-
|
90
|
+
dependent_matcher = AssociationMatchers::DependentMatcher.new(dependent, name)
|
91
|
+
add_submatcher(dependent_matcher)
|
88
92
|
self
|
89
93
|
end
|
90
94
|
|
91
95
|
def order(order)
|
92
|
-
|
96
|
+
order_matcher = AssociationMatchers::OrderMatcher.new(order, name)
|
97
|
+
add_submatcher(order_matcher)
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def counter_cache(counter_cache = true)
|
102
|
+
counter_cache_matcher = AssociationMatchers::CounterCacheMatcher.new(counter_cache, name)
|
103
|
+
add_submatcher(counter_cache_matcher)
|
93
104
|
self
|
94
105
|
end
|
95
106
|
|
@@ -118,51 +129,83 @@ module Shoulda # :nodoc:
|
|
118
129
|
self
|
119
130
|
end
|
120
131
|
|
132
|
+
def description
|
133
|
+
description = "#{macro_description} #{name}"
|
134
|
+
description += " class_name => #{options[:class_name]}" if options.key?(:class_name)
|
135
|
+
[description, submatchers.map(&:description)].flatten.join(' ')
|
136
|
+
end
|
137
|
+
|
138
|
+
def failure_message_for_should
|
139
|
+
"Expected #{expectation} (#{missing_options})"
|
140
|
+
end
|
141
|
+
|
142
|
+
def failure_message_for_should_not
|
143
|
+
"Did not expect #{expectation}"
|
144
|
+
end
|
145
|
+
|
121
146
|
def matches?(subject)
|
122
147
|
@subject = subject
|
123
148
|
association_exists? &&
|
124
149
|
macro_correct? &&
|
125
150
|
foreign_key_exists? &&
|
126
|
-
through_association_valid? &&
|
127
|
-
dependent_correct? &&
|
128
151
|
class_name_correct? &&
|
129
|
-
order_correct? &&
|
130
152
|
conditions_correct? &&
|
131
153
|
join_table_exists? &&
|
132
154
|
validate_correct? &&
|
133
|
-
touch_correct?
|
155
|
+
touch_correct? &&
|
156
|
+
submatchers_match?
|
134
157
|
end
|
135
158
|
|
136
|
-
|
137
|
-
|
159
|
+
private
|
160
|
+
|
161
|
+
attr_reader :submatchers, :missing, :subject, :macro, :name, :options
|
162
|
+
|
163
|
+
def add_submatcher(matcher)
|
164
|
+
@submatchers << matcher
|
138
165
|
end
|
139
166
|
|
140
|
-
def
|
141
|
-
|
167
|
+
def macro_description
|
168
|
+
case macro.to_s
|
169
|
+
when 'belongs_to'
|
170
|
+
'belong to'
|
171
|
+
when 'has_many'
|
172
|
+
'have many'
|
173
|
+
when 'has_one'
|
174
|
+
'have one'
|
175
|
+
when 'has_and_belongs_to_many'
|
176
|
+
'have and belong to many'
|
177
|
+
end
|
142
178
|
end
|
143
179
|
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
description
|
180
|
+
def expectation
|
181
|
+
"#{model_class.name} to have a #{macro} association called #{name}"
|
182
|
+
end
|
183
|
+
|
184
|
+
def missing_options
|
185
|
+
[missing, failing_submatchers.map(&:missing_option)].flatten.join
|
151
186
|
end
|
152
187
|
|
153
|
-
|
188
|
+
def failing_submatchers
|
189
|
+
@failing_submatchers ||= submatchers.select do |matcher|
|
190
|
+
!matcher.matches?(subject)
|
191
|
+
end
|
192
|
+
end
|
154
193
|
|
155
194
|
def association_exists?
|
156
195
|
if reflection.nil?
|
157
|
-
@missing = "no association called #{
|
196
|
+
@missing = "no association called #{name}"
|
158
197
|
false
|
159
198
|
else
|
160
199
|
true
|
161
200
|
end
|
162
201
|
end
|
163
202
|
|
203
|
+
def reflection
|
204
|
+
@reflection ||= model_class.reflect_on_association(name)
|
205
|
+
end
|
206
|
+
|
164
207
|
def macro_correct?
|
165
|
-
if reflection.macro ==
|
208
|
+
if reflection.macro == macro
|
166
209
|
true
|
167
210
|
else
|
168
211
|
@missing = "actual association type was #{reflection.macro}"
|
@@ -175,66 +218,33 @@ module Shoulda # :nodoc:
|
|
175
218
|
end
|
176
219
|
|
177
220
|
def belongs_foreign_key_missing?
|
178
|
-
|
221
|
+
macro == :belongs_to && !class_has_foreign_key?(model_class)
|
222
|
+
end
|
223
|
+
|
224
|
+
def model_class
|
225
|
+
subject.class
|
179
226
|
end
|
180
227
|
|
181
228
|
def has_foreign_key_missing?
|
182
|
-
[:has_many, :has_one].include?(
|
229
|
+
[:has_many, :has_one].include?(macro) &&
|
183
230
|
!through? &&
|
184
231
|
!class_has_foreign_key?(associated_class)
|
185
232
|
end
|
186
233
|
|
187
|
-
def
|
188
|
-
|
189
|
-
end
|
190
|
-
|
191
|
-
def through_association_exists?
|
192
|
-
if through_reflection.nil?
|
193
|
-
@missing = "#{model_class.name} does not have any relationship to #{@options[:through]}"
|
194
|
-
false
|
195
|
-
else
|
196
|
-
true
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
def through_association_correct?
|
201
|
-
if @options[:through] == reflection.options[:through]
|
202
|
-
true
|
203
|
-
else
|
204
|
-
@missing = "Expected #{model_class.name} to have #{@name} through #{@options[:through]}, " +
|
205
|
-
"but got it through #{reflection.options[:through]}"
|
206
|
-
false
|
207
|
-
end
|
234
|
+
def through?
|
235
|
+
reflection.options[:through]
|
208
236
|
end
|
209
237
|
|
210
|
-
def
|
211
|
-
|
212
|
-
true
|
213
|
-
else
|
214
|
-
@missing = "#{@name} should have #{@options[:dependent]} dependency"
|
215
|
-
false
|
216
|
-
end
|
238
|
+
def associated_class
|
239
|
+
reflection.klass
|
217
240
|
end
|
218
241
|
|
219
242
|
def class_name_correct?
|
220
|
-
if
|
221
|
-
if
|
243
|
+
if options.key?(:class_name)
|
244
|
+
if options[:class_name].to_s == reflection.klass.to_s
|
222
245
|
true
|
223
246
|
else
|
224
|
-
@missing = "#{
|
225
|
-
false
|
226
|
-
end
|
227
|
-
else
|
228
|
-
true
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def order_correct?
|
233
|
-
if @options.key?(:order)
|
234
|
-
if @options[:order].to_s == reflection.options[:order].to_s
|
235
|
-
true
|
236
|
-
else
|
237
|
-
@missing = "#{@name} should be ordered by #{@options[:order]}"
|
247
|
+
@missing = "#{name} should resolve to #{options[:class_name]} for class_name"
|
238
248
|
false
|
239
249
|
end
|
240
250
|
else
|
@@ -243,11 +253,11 @@ module Shoulda # :nodoc:
|
|
243
253
|
end
|
244
254
|
|
245
255
|
def conditions_correct?
|
246
|
-
if
|
247
|
-
if
|
256
|
+
if options.key?(:conditions)
|
257
|
+
if options[:conditions].to_s == reflection.options[:conditions].to_s
|
248
258
|
true
|
249
259
|
else
|
250
|
-
@missing = "#{
|
260
|
+
@missing = "#{name} should have the following conditions: #{options[:conditions]}"
|
251
261
|
false
|
252
262
|
end
|
253
263
|
else
|
@@ -256,7 +266,7 @@ module Shoulda # :nodoc:
|
|
256
266
|
end
|
257
267
|
|
258
268
|
def join_table_exists?
|
259
|
-
if
|
269
|
+
if macro != :has_and_belongs_to_many ||
|
260
270
|
model_class.connection.tables.include?(join_table)
|
261
271
|
true
|
262
272
|
else
|
@@ -269,7 +279,7 @@ module Shoulda # :nodoc:
|
|
269
279
|
if option_correct?(:validate)
|
270
280
|
true
|
271
281
|
else
|
272
|
-
@missing = "#{
|
282
|
+
@missing = "#{name} should have :validate => #{options[:validate]}"
|
273
283
|
false
|
274
284
|
end
|
275
285
|
end
|
@@ -278,22 +288,22 @@ module Shoulda # :nodoc:
|
|
278
288
|
if option_correct?(:touch)
|
279
289
|
true
|
280
290
|
else
|
281
|
-
@missing = "#{
|
291
|
+
@missing = "#{name} should have :touch => #{options[:touch]}"
|
282
292
|
false
|
283
293
|
end
|
284
294
|
end
|
285
295
|
|
286
296
|
def option_correct?(key)
|
287
|
-
|
297
|
+
!options.key?(key) || reflection_set_properly_for?(key)
|
288
298
|
end
|
289
299
|
|
290
300
|
def reflection_set_properly_for?(key)
|
291
|
-
|
301
|
+
options[key] == !!reflection.options[key]
|
292
302
|
end
|
293
303
|
|
294
304
|
def class_has_foreign_key?(klass)
|
295
|
-
if
|
296
|
-
reflection.options[:foreign_key] ==
|
305
|
+
if options.key?(:foreign_key)
|
306
|
+
reflection.options[:foreign_key] == options[:foreign_key]
|
297
307
|
else
|
298
308
|
if klass.column_names.include?(foreign_key)
|
299
309
|
true
|
@@ -304,10 +314,6 @@ module Shoulda # :nodoc:
|
|
304
314
|
end
|
305
315
|
end
|
306
316
|
|
307
|
-
def model_class
|
308
|
-
@subject.class
|
309
|
-
end
|
310
|
-
|
311
317
|
def join_table
|
312
318
|
if reflection.respond_to? :join_table
|
313
319
|
reflection.join_table.to_s
|
@@ -316,10 +322,6 @@ module Shoulda # :nodoc:
|
|
316
322
|
end
|
317
323
|
end
|
318
324
|
|
319
|
-
def associated_class
|
320
|
-
reflection.klass
|
321
|
-
end
|
322
|
-
|
323
325
|
def foreign_key
|
324
326
|
if foreign_key_reflection
|
325
327
|
if foreign_key_reflection.respond_to?(:foreign_key)
|
@@ -330,41 +332,16 @@ module Shoulda # :nodoc:
|
|
330
332
|
end
|
331
333
|
end
|
332
334
|
|
333
|
-
def through?
|
334
|
-
reflection.options[:through]
|
335
|
-
end
|
336
|
-
|
337
|
-
def reflection
|
338
|
-
@reflection ||= model_class.reflect_on_association(@name)
|
339
|
-
end
|
340
|
-
|
341
335
|
def foreign_key_reflection
|
342
|
-
if [:has_one, :has_many].include?(
|
336
|
+
if [:has_one, :has_many].include?(macro) && reflection.options.include?(:inverse_of)
|
343
337
|
associated_class.reflect_on_association(reflection.options[:inverse_of])
|
344
338
|
else
|
345
339
|
reflection
|
346
340
|
end
|
347
341
|
end
|
348
342
|
|
349
|
-
def
|
350
|
-
|
351
|
-
end
|
352
|
-
|
353
|
-
def expectation
|
354
|
-
"#{model_class.name} to have a #{@macro} association called #{@name}"
|
355
|
-
end
|
356
|
-
|
357
|
-
def macro_description
|
358
|
-
case @macro.to_s
|
359
|
-
when 'belongs_to'
|
360
|
-
'belong to'
|
361
|
-
when 'has_many'
|
362
|
-
'have many'
|
363
|
-
when 'has_one'
|
364
|
-
'have one'
|
365
|
-
when 'has_and_belongs_to_many'
|
366
|
-
'have and belong to many'
|
367
|
-
end
|
343
|
+
def submatchers_match?
|
344
|
+
failing_submatchers.empty?
|
368
345
|
end
|
369
346
|
end
|
370
347
|
end
|