# Copyright (c) 2009 Paolo Capriotti # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. class Proc # # Bind this Proc to an object. # def bind(object) block, time = self, Time.now (class << object; self end).class_eval do method_name = "__bind_#{time.to_i}_#{time.usec}" define_method(method_name, &block) method = instance_method(method_name) remove_method(method_name) method end.bind(object) end end # # A Factory is a wrapper around a Proc that exposes it through its {Factory#new # new} method. # # Wrapping a Proc in a Factory is useful to have a uniform API across classes # and custom object-creating lambdas. For instance, if a method create_object # takes a class as argument, like: # # def create_object(klass) # obj = klass.new('foo') # # do something with obj # obj # end # # you can pass modified class constructors: # # create_object(Factory.new {|arg| Array.new(4) { arg } }) # # and have the method behave as if the passed argument were a normal class. # class Factory # # A Factory can specify a component, which is the class used to # instantiate the objects created by this Factory. # # When non-nil, it should satisfy component == new(*args).class. # # @return the component of this Factory # attr_reader :component # # Create a factory object. # # @param component[Class] the factory component # @param &blk the wrapped Proc # def initialize(component = nil, &blk) @blk = blk @component = component end # # Call the wrapped Proc # def new(*args) @blk[*args] end # # Rebind this Factory. # # Binding a Factory to an object causes the wrapped Proc to be executed in # the given object's scope. # # @param object the object to bind this Factory to # def __bind__(object) Factory.new(@component, &@blk.bind(object)) end end