Created
September 23, 2012 19:57
-
-
Save ernie/3772848 to your computer and use it in GitHub Desktop.
Injection.rb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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