#:title: Module Macros #-- # Module Macros # v 1.0 # # Copyright (c) 2004 George Moschovitis # Copyright (c) 2005 Thomas Sawyer # # Ruby License # # This module is free software. You may use, modify, and/or redistribute this # software under the same terms as Ruby. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # # # $Id: macro.rb,v 1.0 2005/04/28 03:10:10 transami Exp $ # # ========================================================================== # Revision History :: # YYYY.MM.DD Ver. Dev. Description # -------------------------------------------------------------------------- # 2005.04.28 1.0 Trans * Minor modifications to documentation. # ========================================================================== #++ # = Description # # A macro construction for creating dynamic mixins. # # == Example # # module Mixin # macro { |options| %{ # def hello # puts 'Hello from #{options[:name]}' # end # } } # end # # class MyClass # include Mixin, :name => 'tml' # end # # m = MyClass.new # m.hello -> 'Hello from tml' # # == Author(s) # # * George Moschovitis # * Thomas Sawyer # class Module def macro( &blk ) (@macros ||= []) << blk end def macros ; @macros ||= [] ; end alias_method :include_without_macros, :include def include(*args) options = args.last.is_a?(Hash) ? args.pop : {} for mod in args mod.append_dynamic_features( self, options ) end include_without_macros(*args) end # Note: Is this the best name for this callback? def append_dynamic_features( base, options ) macros.each do |m| base.class_eval m.call( options ) end end alias_method :extend_without_macros, :extend def extend(*args) options = args.last.is_a?(Hash) ? args.pop : {} for mod in args mod.extend_dynamic_object( self, options ) end extend_without_macros(*args) end # Note: Is this the best name for this callback? def extend_dynamic_object( base, options ) macros.each do |m| (class << base; self ; end).class_eval m.call( options ) end end end