module DR::MetaModule

helping with metaprograming facilities usage: Module Foo; extend DR::MetaModule; include_complete Ploum; end

Public Instance Methods

add_method(name=nil,method) click to toggle source

essentially like define_method, but can pass a Method or an UnboundMethod see also dr/core_ext which add UnboundMethod#to_proc so we could instead use define_method(name,&method) and it would work

# File lib/dr/ruby_ext/meta_ext.rb, line 172
def add_method(name=nil,method)
        name=method.name unless name
        name=name.to_sym
        #if we have a (bound) method, we can convert it to a proc, but the
        #'self' inside it keeps being the 'self' of the original object (even
        #in instance_eval).
        #Since usually we'll want to change the self, it's better to unbind it
        method=method.unbind if method.class==Method
        case method
        when UnboundMethod
                #here the block passed is evaluated using instance_eval, so self is the
                #object calling, not the current module
                define_method name do |*args,&block|
                        method.bind(self).call(*args,&block)
                end
        else
                #if method is a block/Proc, this is the same as define_method(name,method)
                define_method(name,&method)
        end
end
add_methods(*args) click to toggle source

add_methods(method1, method2, …) add_methods({name1: method1, name2: method2, …}) add_methods(aClass, :method_name1, :method_name2) add_methods(aClass, {new_name1: :method_name1, new_name2: :method_name2})

# File lib/dr/ruby_ext/meta_ext.rb, line 197
def add_methods(*args)
        return if args.empty?
        if Module === args.first
                mod=args.shift
                #we include methods from mod, the arguments should be method names
                if args.size == 1 and Hash === args.first
                        #we have a hash {new_name => old_name}
                        args.first.each do |k,v|
                                add_method(k,mod.instance_method(v.to_sym))
                        end
                else
                        args.each do |m|
                                add_method(mod.instance_method(m.to_sym))
                        end
                end
        else
                if args.size == 1 and Hash === args.first
                        #we have a hash {new_name => method}
                        args.first.each do |k,v|
                                add_method(k,v)
                        end
                else
                        args.each do |m|
                                add_method(m)
                        end
                end
        end
end
full_include(other) click to toggle source

module Z

def x; "x"; end

end module Enumerable

extend MetaModule
full_include Z

end Array.new.x => “x”

# File lib/dr/ruby_ext/meta_ext.rb, line 159
def full_include other
        include other
        if self.class == Module
                this = self
                ObjectSpace.each_object Module do |mod|
                        mod.send :include, this if mod < self
                end
        end
end
include_all_ancestors(obj) click to toggle source
# File lib/dr/ruby_ext/meta_ext.rb, line 144
def include_all_ancestors(obj)
        ancestors=Meta.all_ancestors(obj)
        ancestors.reverse.each do |m|
                include m if m.class==Module
        end
end
include_ancestors(m) click to toggle source

include_ancestor includes all modules ancestor, so one can do singleton_class.include_ancestors(String) to include the Module ancestors of String into the class

# File lib/dr/ruby_ext/meta_ext.rb, line 137
def include_ancestors(m)
        ancestors=m.respond_to?(:ancestors) ? m.ancestors : m.singleton_class.ancestors
        ancestors.reverse.each do |m|
                include m if m.class==Module
        end
end
includes_extends_host_with(instance_module=nil, class_module=nil, hooks: [:included,:extended]) click to toggle source

When included/extended (according to :hooks, add the following instance and class methods)

# File lib/dr/ruby_ext/meta_ext.rb, line 115
def includes_extends_host_with(instance_module=nil, class_module=nil, hooks: [:included,:extended])
        @_include_module ||= []
        @_extension_module ||= []
        @_include_module << instance_module
        @_extension_module << class_module
        hooks.each do |hook|
                define_singleton_method hook do |base|
                        #we use send here because :include is private in Module
                        @_include_module.each do |m|
                                m=const_get(m) if ! Module===m
                                base.send(:include, m)
                        end
                        @_extension_module.each do |m|
                                m=const_get(m) if ! Module===m
                                base.extend(m)
                        end
                end
        end
end