rr 0.10.11 → 1.0.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.
Files changed (57) hide show
  1. data/CHANGES +5 -0
  2. data/Gemfile +6 -0
  3. data/README.rdoc +28 -2
  4. data/VERSION.yml +3 -3
  5. data/lib/rr.rb +23 -17
  6. data/lib/rr/adapters/rr_methods.rb +43 -17
  7. data/lib/rr/blank_slate.rb +2 -2
  8. data/lib/rr/class_instance_method_defined.rb +9 -0
  9. data/lib/rr/double.rb +2 -2
  10. data/lib/rr/double_definitions/double_definition.rb +29 -16
  11. data/lib/rr/double_definitions/double_definition_create.rb +52 -86
  12. data/lib/rr/double_definitions/double_injections/any_instance_of.rb +28 -0
  13. data/lib/rr/double_definitions/double_injections/instance.rb +16 -0
  14. data/lib/rr/double_definitions/double_injections/new_instance_of.rb +53 -0
  15. data/lib/rr/double_definitions/strategies/double_injection/any_instance_of.rb +31 -0
  16. data/lib/rr/double_definitions/strategies/double_injection/double_injection_strategy.rb +10 -0
  17. data/lib/rr/double_definitions/strategies/double_injection/instance.rb +17 -0
  18. data/lib/rr/double_definitions/strategies/double_injection/new_instance_of.rb +37 -0
  19. data/lib/rr/double_definitions/strategies/implementation/implementation_strategy.rb +0 -5
  20. data/lib/rr/double_definitions/strategies/implementation/proxy.rb +0 -2
  21. data/lib/rr/double_definitions/strategies/implementation/strongly_typed_reimplementation.rb +0 -2
  22. data/lib/rr/double_definitions/strategies/strategy.rb +0 -27
  23. data/lib/rr/double_definitions/strategies/strategy_methods.rb +53 -0
  24. data/lib/rr/double_definitions/strategies/verification/dont_allow.rb +0 -2
  25. data/lib/rr/double_definitions/strategies/verification/mock.rb +0 -2
  26. data/lib/rr/double_definitions/strategies/verification/stub.rb +0 -2
  27. data/lib/rr/double_definitions/strategies/verification/verification_strategy.rb +0 -5
  28. data/lib/rr/hash_with_object_id_key.rb +4 -0
  29. data/lib/rr/injections/double_injection.rb +94 -71
  30. data/lib/rr/injections/injection.rb +8 -10
  31. data/lib/rr/injections/method_missing_injection.rb +13 -20
  32. data/lib/rr/injections/singleton_method_added_injection.rb +19 -17
  33. data/lib/rr/method_dispatches/base_method_dispatch.rb +1 -1
  34. data/lib/rr/method_dispatches/method_dispatch.rb +4 -4
  35. data/lib/rr/method_dispatches/method_missing_dispatch.rb +17 -14
  36. data/lib/rr/recorded_calls.rb +1 -1
  37. data/lib/rr/space.rb +6 -6
  38. data/lib/rr/times_called_matchers/times_called_matcher.rb +2 -2
  39. data/scratch.rb +118 -0
  40. data/spec/api/any_instance_of/all_instances_of_spec.rb +14 -0
  41. data/spec/api/any_instance_of/any_instance_of_spec.rb +47 -0
  42. data/spec/api/mock/mock_spec.rb +2 -2
  43. data/spec/api/new_instance_of/instance_of_spec.rb +15 -0
  44. data/spec/api/new_instance_of/new_instance_of_spec.rb +61 -0
  45. data/spec/environment_fixture_setup.rb +3 -2
  46. data/spec/rr/adapters/rr_methods_space_spec.rb +8 -10
  47. data/spec/rr/double_definitions/child_double_definition_creator_spec.rb +1 -1
  48. data/spec/rr/double_definitions/double_definition_create_blank_slate_spec.rb +6 -2
  49. data/spec/rr/double_definitions/double_definition_create_spec.rb +1 -52
  50. data/spec/rr/double_injection/double_injection_verify_spec.rb +1 -1
  51. data/spec/rr/rspec/rspec_adapter_spec.rb +5 -5
  52. data/spec/rr/space/space_spec.rb +58 -67
  53. data/spec/spec_helper.rb +2 -2
  54. metadata +33 -9
  55. data/lib/rr/double_definitions/strategies/scope/instance.rb +0 -15
  56. data/lib/rr/double_definitions/strategies/scope/instance_of_class.rb +0 -50
  57. data/lib/rr/double_definitions/strategies/scope/scope_strategy.rb +0 -15
@@ -0,0 +1,28 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module DoubleInjections
4
+ class AnyInstanceOf
5
+ extend(Module.new do
6
+ include RR::Adapters::RRMethods
7
+
8
+ def call(subject_class, stubbed_methods=nil, &block)
9
+ ::RR::DoubleDefinitions::DoubleDefinitionCreate.set_default_double_injection_strategy(lambda do |double_definition_create|
10
+ ::RR::DoubleDefinitions::Strategies::DoubleInjection::AnyInstanceOf.new(double_definition_create)
11
+ end) do
12
+ if stubbed_methods
13
+ subject_class.class_eval do
14
+ stubbed_methods.each do |name, value|
15
+ value_proc = value.is_a?(Proc) ? value : lambda {value}
16
+ RR.stub(subject_class, name).returns(&value_proc)
17
+ end
18
+ end
19
+ else
20
+ block.call(subject_class)
21
+ end
22
+ end
23
+ end
24
+ end)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module DoubleInjections
4
+ class Instance
5
+ extend(Module.new do
6
+ include ::RR::Adapters::RRMethods
7
+
8
+ def call(double_method_name, *args, &definition_eval_block)
9
+ double_definition_create = DoubleDefinitions::DoubleDefinitionCreate.new
10
+ double_definition_create.send(double_method_name, *args, &definition_eval_block)
11
+ end
12
+ end)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,53 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module DoubleInjections
4
+ class NewInstanceOf
5
+ extend(Module.new do
6
+ include RR::Adapters::RRMethods
7
+ def call(subject, stubbed_methods={})
8
+ double_definition_create = DoubleDefinitionCreate.new.stub
9
+ stub.proxy(subject).allocate do |instance|
10
+ add_stubbed_methods(instance, stubbed_methods)
11
+ add_method_chain_definition(instance, double_definition_create)
12
+ yield(instance) if block_given?
13
+ instance
14
+ end
15
+ stub(subject).new do |*args|
16
+ instance = subject.allocate
17
+ initialize_subject_instance(instance, args)
18
+ end
19
+ DoubleDefinitionCreateBlankSlate.new(double_definition_create)
20
+ end
21
+
22
+ protected
23
+ def add_stubbed_methods(subject_instance, stubbed_methods)
24
+ stubbed_methods.each do |name, value|
25
+ value_proc = value.is_a?(Proc) ? value : lambda {value}
26
+ stub(subject_instance, name).returns(&value_proc)
27
+ end
28
+ end
29
+
30
+ def add_method_chain_definition(subject_instance, double_definition_create)
31
+ implementation_strategy = double_definition_create.implementation_strategy
32
+ if implementation_strategy.method_name
33
+ stub(subject_instance).method_missing(
34
+ implementation_strategy.method_name,
35
+ *implementation_strategy.args,
36
+ &implementation_strategy.handler
37
+ )
38
+ end
39
+ end
40
+
41
+ def initialize_subject_instance(subject_instance, args)
42
+ if args.last.is_a?(ProcFromBlock)
43
+ subject_instance.__send__(:initialize, *args[0..(args.length-2)], &args.last)
44
+ else
45
+ subject_instance.__send__(:initialize, *args)
46
+ end
47
+ subject_instance
48
+ end
49
+ end)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,31 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module Strategies
4
+ module DoubleInjection
5
+ # This class is Deprecated.
6
+ # Calling instance_of will cause all instances of the passed in Class
7
+ # to have the Double defined.
8
+ #
9
+ # The following example mocks all User's valid? method and return false.
10
+ # mock.instance_of(User).valid? {false}
11
+ #
12
+ # The following example mocks and proxies User#projects and returns the
13
+ # first 3 projects.
14
+ # mock.instance_of(User).projects do |projects|
15
+ # projects[0..2]
16
+ # end
17
+ class AnyInstanceOf < DoubleInjectionStrategy
18
+ protected
19
+ def do_call
20
+ if !double_definition_create.no_subject? && !double_definition_create.subject.is_a?(Class)
21
+ raise ArgumentError, "instance_of only accepts class objects"
22
+ end
23
+ # subject, method_name
24
+ double_injection = Injections::DoubleInjection.find_or_create(subject, method_name)
25
+ Double.new(double_injection, definition)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,10 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module Strategies
4
+ module DoubleInjection
5
+ class DoubleInjectionStrategy < Strategy
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module Strategies
4
+ module DoubleInjection
5
+ class Instance < DoubleInjectionStrategy
6
+ protected
7
+ def do_call
8
+ double_injection = Injections::DoubleInjection.find_or_create(
9
+ (class << subject; self; end), method_name
10
+ )
11
+ Double.new(double_injection, definition)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module Strategies
4
+ module DoubleInjection
5
+ # This class is Deprecated.
6
+ # Calling instance_of will cause all instances of the passed in Class
7
+ # to have the Double defined.
8
+ #
9
+ # The following example mocks all User's valid? method and return false.
10
+ # mock.instance_of(User).valid? {false}
11
+ #
12
+ # The following example mocks and proxies User#projects and returns the
13
+ # first 3 projects.
14
+ # mock.instance_of(User).projects do |projects|
15
+ # projects[0..2]
16
+ # end
17
+ class NewInstanceOf < DoubleInjectionStrategy
18
+ protected
19
+ def do_call
20
+ if !double_definition_create.no_subject? && !double_definition_create.subject.is_a?(Class)
21
+ raise ArgumentError, "instance_of only accepts class objects"
22
+ end
23
+ DoubleDefinitions::DoubleInjections::NewInstanceOf.call(subject) do |subject|
24
+ add_double_to_instance(subject)
25
+ end
26
+ end
27
+
28
+ def add_double_to_instance(instance)
29
+ double_injection = Injections::DoubleInjection.find_or_create((class << instance; self; end), method_name)
30
+ Double.new(double_injection, definition)
31
+ instance
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -3,11 +3,6 @@ module RR
3
3
  module Strategies
4
4
  module Implementation
5
5
  class ImplementationStrategy < Strategy
6
- class << self
7
- def register_self_at_double_definition_create(strategy_method_name)
8
- DoubleDefinitionCreate.register_implementation_strategy_class(self, strategy_method_name)
9
- end
10
- end
11
6
  end
12
7
  end
13
8
  end
@@ -48,8 +48,6 @@ module RR
48
48
  # "My new return value"
49
49
  # end
50
50
  class Proxy < ImplementationStrategy
51
- register("proxy", :probe)
52
-
53
51
  protected
54
52
  def do_call
55
53
  definition.implemented_by_original_method
@@ -3,8 +3,6 @@ module RR
3
3
  module Strategies
4
4
  module Implementation
5
5
  class StronglyTypedReimplementation < Reimplementation
6
- register("strong")
7
-
8
6
  protected
9
7
  def do_call
10
8
  super
@@ -2,29 +2,6 @@ module RR
2
2
  module DoubleDefinitions
3
3
  module Strategies
4
4
  class Strategy
5
- class << self
6
- attr_reader :strategy_method_name
7
- def register(strategy_method_name, *alias_method_names)
8
- @strategy_method_name = strategy_method_name
9
- register_self_at_double_definition_create(strategy_method_name)
10
- DoubleDefinitionCreate.class_eval do
11
- alias_method_names.each do |alias_method_name|
12
- alias_method alias_method_name, strategy_method_name
13
- end
14
- end
15
- RR::Adapters::RRMethods.register_strategy_class(self, strategy_method_name)
16
- DoubleDefinition.register_strategy_class(self, strategy_method_name)
17
- RR::Adapters::RRMethods.class_eval do
18
- alias_method_names.each do |alias_method_name|
19
- alias_method alias_method_name, strategy_method_name
20
- end
21
- end
22
- end
23
-
24
- def register_self_at_double_definition_create(strategy_method_name)
25
- end
26
- end
27
-
28
5
  attr_reader :double_definition_create, :definition, :method_name, :args, :handler
29
6
  include Space::Reader
30
7
 
@@ -37,10 +14,6 @@ module RR
37
14
  do_call
38
15
  end
39
16
 
40
- def name
41
- self.class.strategy_method_name
42
- end
43
-
44
17
  def verify_subject(subject)
45
18
  end
46
19
 
@@ -0,0 +1,53 @@
1
+ module RR
2
+ module DoubleDefinitions
3
+ module Strategies
4
+ module StrategyMethods
5
+ extend(Module.new do
6
+ def lately_bound_alias_method(target_method_name, source_method_name)
7
+ module_eval((<<-METHOD), __FILE__, __LINE__+1)
8
+ def #{target_method_name}(*args, &block)
9
+ #{source_method_name}(*args, &block)
10
+ end
11
+ METHOD
12
+ end
13
+ end)
14
+
15
+ def mock!(method_name=nil, &definition_eval_block)
16
+ mock(Object.new, method_name, &definition_eval_block)
17
+ end
18
+
19
+ def stub!(method_name=nil, &definition_eval_block)
20
+ stub(Object.new, method_name, &definition_eval_block)
21
+ end
22
+
23
+ def dont_allow!(method_name=nil, &definition_eval_block)
24
+ dont_allow(Object.new, method_name, &definition_eval_block)
25
+ end
26
+ lately_bound_alias_method :do_not_allow, :dont_allow
27
+ lately_bound_alias_method :do_not_allow!, :dont_allow!
28
+
29
+ def proxy!(method_name=nil, &definition_eval_block)
30
+ proxy(Object.new, method_name, &definition_eval_block)
31
+ end
32
+ lately_bound_alias_method :probe, :proxy
33
+ lately_bound_alias_method :probe!, :proxy!
34
+
35
+ def strong!(method_name=nil, &definition_eval_block)
36
+ strong(Object.new, method_name, &definition_eval_block)
37
+ end
38
+
39
+ def any_instance_of!(method_name=nil, &definition_eval_block)
40
+ any_instance_of(Object.new, method_name, &definition_eval_block)
41
+ end
42
+ lately_bound_alias_method :all_instances_of, :any_instance_of
43
+ lately_bound_alias_method :all_instances_of!, :any_instance_of!
44
+
45
+ def instance_of!(method_name=nil, &definition_eval_block)
46
+ instance_of(Object.new, method_name, &definition_eval_block)
47
+ end
48
+ lately_bound_alias_method :new_instance_of, :instance_of
49
+ lately_bound_alias_method :new_instance_of!, :instance_of!
50
+ end
51
+ end
52
+ end
53
+ end
@@ -19,8 +19,6 @@ module RR
19
19
  # m.method3.with_no_args # Do not allow method3 with no arguments
20
20
  # end
21
21
  class DontAllow < VerificationStrategy
22
- register("dont_allow", :do_not_allow, :dont_call, :do_not_call)
23
-
24
22
  protected
25
23
  def do_call
26
24
  definition.never
@@ -31,8 +31,6 @@ module RR
31
31
  # method_name_2(arg_1, arg_2) {return_value_2}
32
32
  # end
33
33
  class Mock < VerificationStrategy
34
- register "mock"
35
-
36
34
  protected
37
35
  def do_call
38
36
  definition.with(*args).once
@@ -31,8 +31,6 @@ module RR
31
31
  # method_name_2(arg_1, arg_2) {return_value_2}
32
32
  # end
33
33
  class Stub < VerificationStrategy
34
- register "stub"
35
-
36
34
  protected
37
35
  def do_call
38
36
  definition.any_number_of_times
@@ -3,11 +3,6 @@ module RR
3
3
  module Strategies
4
4
  module Verification
5
5
  class VerificationStrategy < Strategy
6
- class << self
7
- def register_self_at_double_definition_create(strategy_method_name)
8
- DoubleDefinitionCreate.register_verification_strategy_class(self, strategy_method_name)
9
- end
10
- end
11
6
  end
12
7
  end
13
8
  end
@@ -13,6 +13,10 @@ module RR
13
13
  super(key.__id__)
14
14
  end
15
15
 
16
+ def has_key?(key)
17
+ super(key.__id__)
18
+ end
19
+
16
20
  alias_method :set_with_object_id, :[]=
17
21
 
18
22
  def []=(key, value)
@@ -4,67 +4,95 @@ module RR
4
4
  # A double_injection has 0 to many Double objects. Each Double
5
5
  # has Argument Expectations and Times called Expectations.
6
6
  class DoubleInjection < Injection
7
- class << self
8
- def create(subject, method_name)
9
- instances[subject][method_name.to_sym] ||= begin
10
- new(subject, method_name.to_sym, (class << subject; self; end)).bind
7
+ extend(Module.new do
8
+ def find_or_create(subject_class, method_name)
9
+ instances[subject_class][method_name.to_sym] ||= begin
10
+ new(subject_class, method_name.to_sym).bind
11
11
  end
12
12
  end
13
13
 
14
- def exists?(subject, method_name)
15
- instances.include?(subject) && instances[subject].include?(method_name.to_sym)
14
+ def find_or_create_by_subject(subject, method_name)
15
+ find_or_create(class << subject; self; end, method_name)
16
+ end
17
+
18
+ def find(subject_class, method_name)
19
+ instances[subject_class] && instances[subject_class][method_name.to_sym]
20
+ end
21
+
22
+ def find_by_subject(subject, method_name)
23
+ find(class << subject; self; end, method_name)
24
+ end
25
+
26
+ def exists?(subject_class, method_name)
27
+ !!find(subject_class, method_name)
28
+ end
29
+
30
+ def exists_by_subject?(subject, method_name)
31
+ exists?((class << subject; self; end), method_name)
32
+ end
33
+
34
+ def dispatch_method(subject, subject_class, method_name, arguments, block)
35
+ subject_eigenclass = (class << subject; self; end)
36
+ if exists?(subject_class, method_name) && (subject_class == subject_eigenclass || subject_eigenclass.superclass != (class << Class; self; end))
37
+ find(subject_class, method_name.to_sym).dispatch_method(subject, arguments, block)
38
+ else
39
+ new(subject_class, method_name.to_sym).dispatch_original_method(subject, arguments, block)
40
+ end
16
41
  end
17
42
 
18
43
  def reset
19
- instances.each do |subject, method_double_map|
44
+ instances.each do |subject_class, method_double_map|
45
+ SingletonMethodAddedInjection.find(subject_class) && SingletonMethodAddedInjection.find(subject_class).reset
20
46
  method_double_map.keys.each do |method_name|
21
- reset_double(subject, method_name)
47
+ reset_double(subject_class, method_name)
22
48
  end
49
+ Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances.has_key?(subject_class)
23
50
  end
24
51
  end
25
52
 
26
53
  def verify(*subjects)
27
- subjects = Injections::DoubleInjection.instances.keys if subjects.empty?
28
- subjects.each do |subject|
29
- instances.include?(subject) &&
30
- instances[subject].keys.each do |method_name|
31
- verify_double(subject, method_name)
54
+ subject_classes = subjects.empty? ?
55
+ Injections::DoubleInjection.instances.keys :
56
+ subjects.map {|subject| class << subject; self; end}
57
+ subject_classes.each do |subject_class|
58
+ instances.include?(subject_class) &&
59
+ instances[subject_class].keys.each do |method_name|
60
+ verify_double(subject_class, method_name)
32
61
  end &&
33
- instances.delete(subject)
62
+ instances.delete(subject_class)
34
63
  end
35
64
  end
36
65
 
37
66
  # Verifies the DoubleInjection for the passed in subject and method_name.
38
- def verify_double(subject, method_name)
39
- Injections::DoubleInjection.instances[subject][method_name].verify
67
+ def verify_double(subject_class, method_name)
68
+ Injections::DoubleInjection.find(subject_class, method_name).verify
40
69
  ensure
41
- reset_double subject, method_name
70
+ reset_double subject_class, method_name
42
71
  end
43
72
 
44
73
  # Resets the DoubleInjection for the passed in subject and method_name.
45
- def reset_double(subject, method_name)
46
- double_injection = Injections::DoubleInjection.instances[subject].delete(method_name)
47
- Injections::DoubleInjection.instances.delete(subject) if Injections::DoubleInjection.instances[subject].empty?
74
+ def reset_double(subject_class, method_name)
75
+ double_injection = Injections::DoubleInjection.instances[subject_class].delete(method_name)
48
76
  double_injection.reset
77
+ Injections::DoubleInjection.instances.delete(subject_class) if Injections::DoubleInjection.instances[subject_class].empty?
49
78
  end
50
79
 
51
80
  def instances
52
- @instances ||= HashWithObjectIdKey.new do |hash, subject_object|
53
- hash.set_with_object_id(subject_object, {})
81
+ @instances ||= HashWithObjectIdKey.new do |hash, subject_class|
82
+ hash.set_with_object_id(subject_class, {})
54
83
  end
55
84
  end
56
- end
85
+ end)
57
86
 
58
87
  attr_reader :subject_class, :method_name, :doubles
59
88
 
60
89
  MethodArguments = Struct.new(:arguments, :block)
61
90
 
62
- def initialize(subject, method_name, subject_class)
63
- @subject = subject
91
+ def initialize(subject_class, method_name)
64
92
  @subject_class = subject_class
65
93
  @method_name = method_name.to_sym
66
94
  @doubles = []
67
- @bypass_bound_method = nil
95
+ @dispatch_method_delegates_to_dispatch_original_method = nil
68
96
  end
69
97
 
70
98
  # RR::DoubleInjection#register_double adds the passed in Double
@@ -77,20 +105,37 @@ module RR
77
105
  # that dispatches to the matching Double when the method
78
106
  # is called.
79
107
  def bind
80
- if subject_respond_to_method?(method_name)
81
- if subject_has_method_defined?(method_name)
82
- if subject_is_proxy_for_method?(method_name)
83
- bind_method
84
- else
85
- bind_method_with_alias
86
- end
87
- else
88
- Injections::MethodMissingInjection.create(subject)
89
- Injections::SingletonMethodAddedInjection.create(subject)
90
- end
108
+ if subject_has_method_defined?(method_name)
109
+ bind_method_with_alias
91
110
  else
92
- bind_method
111
+ Injections::MethodMissingInjection.find_or_create(subject_class)
112
+ Injections::SingletonMethodAddedInjection.find_or_create(subject_class)
113
+ bind_method_that_self_destructs_and_delegates_to_method_missing
114
+ end
115
+ self
116
+ end
117
+
118
+ def bind_method_that_self_destructs_and_delegates_to_method_missing
119
+ subject_class_object_id = subject_class.object_id
120
+ subject_class.class_eval(<<-METHOD, __FILE__, __LINE__ + 1)
121
+ def #{method_name}(*args, &block)
122
+ ObjectSpace._id2ref(#{subject_class_object_id}).class_eval do
123
+ remove_method(:#{method_name})
124
+ end
125
+ method_missing(:#{method_name}, *args, &block)
93
126
  end
127
+ METHOD
128
+ self
129
+ end
130
+
131
+ def bind_method
132
+ subject_class_object_id = subject_class.object_id
133
+ subject_class.class_eval(<<-METHOD, __FILE__, __LINE__ + 1)
134
+ def #{method_name}(*args, &block)
135
+ arguments = MethodArguments.new(args, block)
136
+ RR::Injections::DoubleInjection.dispatch_method(self, ObjectSpace._id2ref(#{subject_class_object_id}), :#{method_name}, arguments.arguments, arguments.block)
137
+ end
138
+ METHOD
94
139
  self
95
140
  end
96
141
 
@@ -118,48 +163,36 @@ module RR
118
163
  end
119
164
  end
120
165
 
121
- def dispatch_method(args, block)
122
- dispatch = MethodDispatches::MethodDispatch.new(self, args, block)
123
- if @bypass_bound_method
124
- dispatch.call_original_method
166
+ def dispatch_method(subject, args, block)
167
+ if @dispatch_method_delegates_to_dispatch_original_method
168
+ dispatch_original_method(subject, args, block)
125
169
  else
170
+ dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block)
126
171
  dispatch.call
127
172
  end
128
173
  end
129
174
 
130
- def dispatch_method_missing(method_name, args, block)
131
- MethodDispatches::MethodMissingDispatch.new(subject, method_name, args, block).call
175
+ def dispatch_original_method(subject, args, block)
176
+ dispatch = MethodDispatches::MethodDispatch.new(self, subject, args, block)
177
+ dispatch.call_original_method
132
178
  end
133
179
 
134
180
  def subject_has_original_method_missing?
135
- subject_respond_to_method?(original_method_missing_alias_name)
181
+ ClassInstanceMethodDefined.call(subject_class, MethodDispatches::MethodMissingDispatch.original_method_missing_alias_name)
136
182
  end
137
183
 
138
184
  def original_method_alias_name
139
185
  "__rr__original_#{@method_name}"
140
186
  end
141
187
 
142
- def original_method_missing_alias_name
143
- MethodDispatches::MethodMissingDispatch.original_method_missing_alias_name
144
- end
145
-
146
- def bypass_bound_method
147
- @bypass_bound_method = true
188
+ def dispatch_method_delegates_to_dispatch_original_method
189
+ @dispatch_method_delegates_to_dispatch_original_method = true
148
190
  yield
149
191
  ensure
150
- @bypass_bound_method = nil
192
+ @dispatch_method_delegates_to_dispatch_original_method = nil
151
193
  end
152
194
 
153
195
  protected
154
- def subject_is_proxy_for_method?(method_name_in_question)
155
- !(
156
- class << @subject;
157
- self;
158
- end).
159
- instance_methods.
160
- detect {|method_name| method_name.to_sym == method_name_in_question.to_sym}
161
- end
162
-
163
196
  def deferred_bind_method
164
197
  unless subject_has_method_defined?(original_method_alias_name)
165
198
  bind_method_with_alias
@@ -171,16 +204,6 @@ module RR
171
204
  subject_class.__send__(:alias_method, original_method_alias_name, method_name)
172
205
  bind_method
173
206
  end
174
-
175
- def bind_method
176
- subject = @subject.is_a?(Class) && !@subject.name.to_s.empty? ? @subject.name : "self"
177
- subject_class.class_eval(<<-METHOD, __FILE__, __LINE__ + 1)
178
- def #{@method_name}(*args, &block)
179
- arguments = MethodArguments.new(args, block)
180
- RR::Injections::DoubleInjection.create(#{subject}, :#{@method_name}).dispatch_method(arguments.arguments, arguments.block)
181
- end
182
- METHOD
183
- end
184
207
  end
185
208
  end
186
209
  end