Skip to content

Instantly share code, notes, and snippets.

@x0bandeira
Last active August 29, 2015 14:07
Show Gist options
  • Save x0bandeira/a9d3c73337dc46b75547 to your computer and use it in GitHub Desktop.
Save x0bandeira/a9d3c73337dc46b75547 to your computer and use it in GitHub Desktop.
Probe into all instance method calls for a given class
# will look into all method call in instances of given class
module Probe
def self.instances(klass, opts = {})
methods = if opts.is_a?(Array)
opts
else
methods_list(klass, opts)
end
methods.uniq.each do |m|
method = klass.instance_method(m)
if klass.included_modules.include?(method.owner)
probe_instance_module_method(klass, method.owner, m)
elsif klass == method.owner
probe_instance_method(klass, m)
else
raise "Don't know what to do with #{m}"
end
end
end
def self.methods_list(klass, opts)
klass.instance_methods(false)
end
def self.probe_instance_module_method(klass, modulez, method)
on_class(klass) do
<<EOD
def #{method}(*args)
Probe.register("#{klass.name}", :#{method}, args)
m = #{modulez.name}.instance_method(:#{method})
m.bind(self)
m.call(*args)
end
EOD
end
end
def self.probe_instance_method(klass, method)
aliaz = alias_method_name(method)
on_class(klass) do
<<EOD
alias :#{aliaz} :#{method}
def #{method}(*args)
Probe.register("#{klass.name}", :#{method}, args)
send(:#{aliaz}, *args)
end
EOD
end
end
def self.on_class(klass, &block)
eval <<EOD
class #{klass.name}
#{block.call}
end
EOD
end
def self.alias_method_name(method_name)
"__" << method_name.to_s.gsub(/\?/, "_q").gsub(/\!/, "_bang").gsub(/\=/, "_eql") << "_original"
end
def self.register(kn, m, args = [])
puts "-> #{kn}##{m}(#{args.join(", ")})"
self.mem ||= []
self.mem << [kn, m, args]
end
mattr_accessor :mem
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment