Class: RR::Injections::MethodMissingInjection

Inherits:
Injection
  • Object
show all
Includes:
ClassInstanceMethodDefined
Defined in:
lib/rr/injections/method_missing_injection.rb

Constant Summary collapse

BoundObjects =
{}

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ClassInstanceMethodDefined

#class_instance_method_defined

Methods inherited from Injection

#original_method, #subject_has_method_defined?, #subject_has_original_method?

Methods included from Space::Reader

#space

Constructor Details

#initialize(subject_class) ⇒ MethodMissingInjection

Returns a new instance of MethodMissingInjection.



22
23
24
25
# File 'lib/rr/injections/method_missing_injection.rb', line 22

def initialize(subject_class)
  @subject_class = subject_class
  @placeholder_method_defined = false
end

Instance Attribute Details

#subject_classObject (readonly)

Returns the value of attribute subject_class.



20
21
22
# File 'lib/rr/injections/method_missing_injection.rb', line 20

def subject_class
  @subject_class
end

Instance Method Details

#bindObject



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
# File 'lib/rr/injections/method_missing_injection.rb', line 27

def bind
  unless class_instance_method_defined(subject_class, original_method_alias_name)
    unless class_instance_method_defined(subject_class, :method_missing)
      @placeholder_method_defined = true
      subject_class.class_eval do
        def method_missing(method_name, *args, &block)
          super
        end
      end
    end
    # Ruby 1.9 will raise a NoMethodError when #method_missing is defined
    # on the subject, but #to_ary isn't. #method_missing will always be
    # defined thanks to BasicObject, but #to_ary may not, so in this case
    # we need to supply our own. Furthermore, Ruby has special logic to
    # handle the return value of #to_ary; if it is nil, then it tells Ruby
    # to ignore #to_ary altogether and use a default rule to arrayify the
    # object in question.
    unless class_instance_method_defined(subject_class, :to_ary)
      subject_class.class_eval do
        def to_ary; nil; end
      end
    end
    subject_class.__send__(:alias_method, original_method_alias_name, :method_missing)
    bind_method
  end
  self
end

#resetObject



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/rr/injections/method_missing_injection.rb', line 55

def reset
  if subject_has_method_defined?(original_method_alias_name)
    memoized_original_method_alias_name = original_method_alias_name
    placeholder_method_defined = @placeholder_method_defined
    subject_class.class_eval do
      remove_method :method_missing
      unless placeholder_method_defined
        alias_method :method_missing, memoized_original_method_alias_name
      end
      remove_method memoized_original_method_alias_name
    end
  end
end