Module: Hijacker::Spy

Included in:
Hijacker
Defined in:
lib/hijacker/spy.rb

Constant Summary collapse

REJECTED_METHODS =
(Object.instance_methods | Module.methods | %w{__original_[\w\d]+})
FORBIDDEN_CLASSES =
[Array, Hash, String, Fixnum, Float, Numeric, Symbol, Proc, Class, Object, Module]

Instance Method Summary collapse

Instance Method Details

#restore(object) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/hijacker/spy.rb', line 36

def restore(object)
  receiver = if object.is_a?(Class)
    object
  else
    (class << object; self; end)
  end
  guess_instance_methods_from(object).select{|m| m.to_s =~ /__original_/}.each do |met|
    met = met.to_s.gsub!("__original_", "")
    receiver.send(:undef_method, :"#{met}")
    receiver.send(:alias_method, :"#{met}", :"__original_#{met}")
  end

  receiver = (class << object; self; end)
  guess_singleton_methods_from(object).select{|m| m.to_s =~ /__original_/}.each do |met|
    met = met.to_s.gsub!("__original_", "")
    receiver.send(:undef_method, :"#{met}")
    receiver.send(:alias_method, :"#{met}", :"__original_#{met}")
  end
end

#spy(object, options = {}) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/hijacker/spy.rb', line 14

def spy(object, options = {})
  raise "Cannot spy on the following forbidden classes: #{FORBIDDEN_CLASSES.map(&:to_s).join(', ')}" if FORBIDDEN_CLASSES.include?(object)
  rejection = /^(#{REJECTED_METHODS.join('|')})/
  only = options[:only]
  uri = options[:uri]
  custom_rejection = options[:reject] if options[:reject].is_a?(Regexp)

  inst_methods = guess_instance_methods_from(object).reject{|m| m.to_s =~ rejection}.reject{|m| m.to_s =~ custom_rejection}
  sing_methods = guess_singleton_methods_from(object).reject{|m| m.to_s =~ rejection}.reject{|m| m.to_s =~ custom_rejection}

  receiver = if object.is_a?(Class)
    object
  else
    (class << object; self; end)
  end

  define_hijacked(inst_methods, receiver, uri) unless options[:only] == :singleton_methods
  receiver = (class << object; self; end)
  define_hijacked(sing_methods, receiver, uri) unless options[:only] == :instance_methods

end

#spying(*args, &block) ⇒ Object



7
8
9
10
11
12
# File 'lib/hijacker/spy.rb', line 7

def spying(*args, &block)
  raise "No block given" unless block
  Hijacker.spy(*args)
  block.call
  Hijacker.restore(args.first)
end