@@ -45,8 +45,12 @@ module MemoizedHelpers
45
45
#
46
46
# @see #should
47
47
def subject
48
- raise NotImplementedError , 'This definition is here for documentation purposes only'
49
- ' - it is overriden anyway below when this module gets included.'
48
+ __memoized . fetch ( :subject ) do
49
+ __memoized [ :subject ] = begin
50
+ described = described_class || self . class . description
51
+ Class === described ? described . new : described
52
+ end
53
+ end
50
54
end
51
55
52
56
# When `should` is called with no explicit receiver, the call is
@@ -148,12 +152,6 @@ def preserve_accessed_lets
148
152
149
153
def self . included ( mod )
150
154
mod . extend ( ClassMethods )
151
-
152
- # This logic defines an implicit subject
153
- mod . subject do
154
- described = described_class || self . class . description
155
- Class === described ? described . new : described
156
- end
157
155
end
158
156
159
157
module ClassMethods
@@ -190,12 +188,16 @@ module ClassMethods
190
188
# end
191
189
# end
192
190
def let ( name , &block )
193
- MemoizedHelpers . define_memoized_method (
194
- self ,
195
- name ,
196
- MemoizedHelpers . memoized_method_name_for ( name , 'let' ) ,
197
- &block
198
- )
191
+ # We have to pass the block directly to `define_method` to
192
+ # allow it to use method constructs like `super` and `return`.
193
+ raise "#let or #subject called without a block" if block . nil?
194
+ MemoizedHelpers . module_for ( self ) . send ( :define_method , name , &block )
195
+
196
+ # Apply the memoization. The method has been defined in an ancestor
197
+ # module so we can use `super` here to get the value.
198
+ define_method ( name ) do
199
+ __memoized . fetch ( name ) { |k | __memoized [ k ] = super ( &nil ) }
200
+ end
199
201
end
200
202
201
203
# Just like `let`, except the block is invoked by an implicit `before`
@@ -287,11 +289,10 @@ def let!(name, &block)
287
289
# @see MemoizedHelpers#should
288
290
def subject ( name = nil , &block )
289
291
if name
290
- subject_method_name = MemoizedHelpers . memoized_method_name_for ( name , "subject" )
291
- MemoizedHelpers . define_memoized_method ( self , name , subject_method_name , &block )
292
+ let ( name , &block )
292
293
alias_method :subject , name
293
294
294
- self ::NamedSubjectPreventSuper . __send__ ( :define_method , subject_method_name ) do
295
+ self ::NamedSubjectPreventSuper . send ( :define_method , name ) do
295
296
raise NotImplementedError , "`super` in named subjects is not supported"
296
297
end
297
298
else
@@ -468,30 +469,14 @@ def self.module_for(example_group)
468
469
}
469
470
end
470
471
471
- example_group . __send__ ( :include , mod )
472
472
example_group . const_set ( :LetDefinitions , mod )
473
473
mod
474
474
end
475
475
end
476
476
477
477
# @api private
478
- def self . memoized_method_name_for ( name , let_or_subject )
479
- "__rspec_#{ let_or_subject } _definition_#{ name } "
480
- end
481
-
482
- # @api private
483
- def self . define_memoized_method ( example_group , name , memoized_method_name , &block )
484
- # We have to pass the block directly to `define_method` to
485
- # allow it to use method constructs like `super` and `return`.
486
- raise "#let or #subject called without a block" if block . nil?
487
-
488
- MemoizedHelpers . module_for ( example_group ) . __send__ ( :define_method , memoized_method_name , &block )
489
-
490
- # Apply the memoization. The method has been defined in an ancestor
491
- # module so we can use `super` here to get the value.
492
- example_group . __send__ ( :define_method , name ) do
493
- __memoized . fetch ( name ) { |k | __memoized [ k ] = send ( memoized_method_name , &nil ) }
494
- end
478
+ def self . define_helpers_on ( example_group )
479
+ example_group . send ( :include , module_for ( example_group ) )
495
480
end
496
481
497
482
if Module . method ( :const_defined? ) . arity == 1 # for 1.8
0 commit comments