Module: DR::MetaModule
- Included in:
- DynamicModule
- Defined in:
- lib/drain/ruby_ext/meta_ext.rb
Overview
helping with metaprograming facilities usage: Module Foo; extend DR::MetaModule; include_complete Ploum; end
Instance Method Summary collapse
-
#add_method(name = nil, method) ⇒ Object
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.
- #add_methods(*args) ⇒ Object
-
#full_include(other) ⇒ Object
module Z def x; "x"; end end module Enumerable extend MetaModule full_include Z end Array.new.x => "x".
-
#get_unbound_method(method_name, &block) ⇒ Object
Taken from sinatra/base.rb: return an unbound method from a block, with owner the current module Conversely, from a (bound) method, calling to_proc (hence &m) gives a lambda Note: rather than doing m=get_unbound_method('',&block);m.bind(obj).call(args) one could do obj.instance_exec(args,&block).
-
#include_ancestors(m) ⇒ Object
include_ancestor includes all modules ancestor, so one can do singleton_class.include_ancestors(m) to have a fully featured extend.
-
#include_complete(obj) ⇒ Object
include a module and extend its singleton_class (along with its ancestors).
-
#includes_extends_host_with(instance_module = nil, class_module = nil, hooks: [:included,:extended]) ⇒ Object
When included/extended (according to :hooks, add the following instance and class methods).
Instance Method Details
#add_method(name = nil, method) ⇒ Object
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
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/drain/ruby_ext/meta_ext.rb', line 149 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) ⇒ Object
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/drain/ruby_ext/meta_ext.rb', line 170 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) ⇒ Object
module Z def x; "x"; end end module Enumerable extend MetaModule full_include Z end Array.new.x => "x"
123 124 125 126 127 128 129 130 131 |
# File 'lib/drain/ruby_ext/meta_ext.rb', line 123 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 |
#get_unbound_method(method_name, &block) ⇒ Object
Taken from sinatra/base.rb: return an unbound method from a block, with owner the current module Conversely, from a (bound) method, calling to_proc (hence &m) gives a lambda Note: rather than doing m=get_unbound_method('',&block);m.bind(obj).call(args) one could do obj.instance_exec(args,&block)
139 140 141 142 143 144 |
# File 'lib/drain/ruby_ext/meta_ext.rb', line 139 def get_unbound_method(method_name, &block) define_method(method_name, &block) method = instance_method method_name remove_method method_name method end |
#include_ancestors(m) ⇒ Object
include_ancestor includes all modules ancestor, so one can do singleton_class.include_ancestors(m) to have a fully featured extend
100 101 102 103 104 105 |
# File 'lib/drain/ruby_ext/meta_ext.rb', line 100 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 |
#include_complete(obj) ⇒ Object
include a module and extend its singleton_class (along with its ancestors)
108 109 110 111 112 113 |
# File 'lib/drain/ruby_ext/meta_ext.rb', line 108 def include_complete(obj) ancestors=Meta.all_ancestors(obj) 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]) ⇒ Object
When included/extended (according to :hooks, add the following instance and class methods)
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/drain/ruby_ext/meta_ext.rb', line 78 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 |