Skip to content

Instantly share code, notes, and snippets.

@ernie
Created September 23, 2012 19:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ernie/3772848 to your computer and use it in GitHub Desktop.
Save ernie/3772848 to your computer and use it in GitHub Desktop.
Injection.rb
#!/usr/bin/env ruby
require './injection'
require 'pry'
class CallTracker < BasicObject
attr_reader :tracked_calls
def initialize
@tracked_calls = ::Hash.new { |h, k| h[k] = 0 }
@injected = nil
end
def to_s
"CallTracker"
end
def track(method)
@tracked_calls[method] += 1
end
def injected(base)
[:public, :protected, :private].each do |visibility|
methods = base.send "#{visibility}_methods"
define_methods(base, visibility, methods)
end
end
def define_methods(base, visibility, methods)
tracker = self
base.singleton_class.class_eval do
methods.each do |method|
define_method method do |*args, &block|
tracker.track(method)
super(*args, &block)
end
send(visibility, method)
end
end
end
end
array = []
tracker = CallTracker.new
array.extend Injection.new(tracker, :tracked_calls)
binding.pry
class Injection < Module
attr_reader :name, :object, :as, :methods, :prefix, :suffix
alias to_s name
def initialize(object, *methods)
opts = (methods.pop if Hash === methods.last) || {}
@name, @object, @methods = "Injection(#{object})", object, methods
@prefix, @suffix, @as = opts.values_at :prefix, :suffix, :as
define_reader(as, object)
define_delegators(object, methods)
define_reflection
end
def extended(base)
@object.injected(base) if @object.instance_eval { defined?(injected) }
end
def inspect
@inspect ||= name.dup.tap do |name|
name.insert(-2, " as: ##{as}") if as
name.insert(-2, " methods: #{methods}") unless methods.empty?
name.insert(-2, " format: #{affix('<method>')}") if prefix || suffix
end
end
private
def affix(name)
[prefix, name, suffix].compact.join('_')
end
def define_delegators(object, methods)
methods.each do |name|
define_method affix(name) do |*args, &block|
object.__send__(name, *args, &block)
end
end
end
def define_reader(as, object)
define_method(as) { object } if as
end
def define_reflection
define_method :injections do
singleton_class.ancestors.grep(Injection)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment