File: method_missing_dispatch.rb

package info (click to toggle)
ruby-rr 3.1.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,424 kB
  • sloc: ruby: 11,405; makefile: 7
file content (71 lines) | stat: -rw-r--r-- 2,186 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module RR
  module MethodDispatches
    class MethodMissingDispatch < BaseMethodDispatch
      extend(Module.new do
        def original_method_missing_alias_name
          "__rr__original_method_missing"
        end
      end)

      attr_reader :subject, :subject_class, :method_name

      def initialize(subject, subject_class, method_name, args, kwargs, block)
        @subject = subject
        @subject_class = subject_class
        @method_name = method_name
        @args = args
        @kwargs = kwargs
        @block = block
      end

      def call
        if Injections::DoubleInjection.exists?(subject_class, method_name)
          @double = find_double_to_attempt
          if double
            return_value = extract_subject_from_return_value(call_implementation)
            if after_call_proc
              extract_subject_from_return_value(after_call_proc.call(return_value))
            else
              return_value
            end
          else
            double_not_found_error
          end
        else
          call_original_method
        end
      end

      def call_original_method
        Injections::DoubleInjection.find_or_create(subject_class, method_name).dispatch_method_delegates_to_dispatch_original_method do
          call_original_method_missing
        end
      end

    protected
      def call_implementation
        if implementation_is_original_method?
          space.record_call(subject, method_name, args, kwargs, block)
          double.method_call(args, kwargs)
          call_original_method
        else
          if double_injection = Injections::DoubleInjection.find(subject_class, method_name)
            double_injection.bind_method
            # The DoubleInjection takes care of calling double.method_call
            if KeywordArguments.fully_supported?
              subject.__send__(method_name, *args, **kwargs, &block)
            else
              subject.__send__(method_name, *args, &block)
            end
          else
            nil
          end
        end
      end

      def double_injection
        Injections::DoubleInjection.find_or_create(subject_class, method_name)
      end
    end
  end
end