rr 0.10.11 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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