Module: DR::MetaModule

Included in:
DynamicModule
Defined in:
lib/dr/ruby_ext/meta_ext.rb

Overview

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

Instance Method Summary collapse

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



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# 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) ⇒ Object

add_methods(method1, method2, ...) add_methods(method1, name2: method2, ...) add_methods(aClass, :method_name1, :method_name2) add_methods(aClass, :method_name1, new_name2: :method_name2)



197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# 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) ⇒ Object

module Z def x; "x"; end end module Enumerable extend MetaModule full_include Z end Array.new.x => "x"



159
160
161
162
163
164
165
166
167
# 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) ⇒ Object



144
145
146
147
148
149
# 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) ⇒ Object

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



137
138
139
140
141
142
# 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]) ⇒ Object

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



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# 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