Skip to content

Instantly share code, notes, and snippets.

@sorah
Created February 28, 2014 02:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sorah/9263951 to your computer and use it in GitHub Desktop.
Save sorah/9263951 to your computer and use it in GitHub Desktop.
class Foo
def initialize
@hooks = []
@methods = {}
@existing_methods = self.methods
end
def add(mode=nil, &block)
@hooks << block
end
def hola
p :hola
end
def to_proc(methods={})
hooks = @hooks
methods.each do |name, meth|
if @existing_methods.include?(name)
raise ArgumentError, "conflicts with existing method"
end
unless self.respond_to?(name)
self.define_singleton_method(name) { |*args, &block|
(@methods[Thread.current] ||= {})[name].call(self, *args, &block)
}
end
end
this = self
proc do |*args|
begin
methods.each do |name, meth|
(@methods[Thread.current] ||= {})[name] = meth
end
hooks.each do |hook|
this.instance_eval(*args, &hook)
end
ensure
@methods.delete Thread.current
end
end
end
end
class Bar
def a
@a ||= Foo.new
end
def baz
a.to_proc(hello: method(:hello)).call
end
def hello(a)
p :hello
end
end
bar = Bar.new
a = bar.a
a.add { hello }
a.add { hola }
a.add { p 2 }
a.add { |a| p a }
bar.baz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment