Module: DR::Meta

Extended by:
Meta
Included in:
Meta
Defined in:
lib/drain/ruby_ext/meta_ext.rb

Instance Method Summary collapse

Instance Method Details

#all_ancestors(obj) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/drain/ruby_ext/meta_ext.rb', line 16

def all_ancestors(obj)
	obj=obj.singleton_class unless Module===obj
	found=[]
	stack=[obj]
	while !stack.empty? do
		obj=stack.shift
		next if found.include?(obj)
		found<<obj
		stack.push(* obj.ancestors.select {|m| !(stack+found).include?(m)})
		sing=obj.singleton_class
		stack << sing unless sing.ancestors.select {|m| m.class==Module}.reduce(true) {|b,m| b && found.include?(m)}
	end
	return found
end

#apply(*args, method: nil, to: self, **opts, &block) ⇒ Object

If we don't want to extend a module with Meta, we can still do Meta.apply(String,method: Meta.instance_method(:include_ancestors),to: self) Note: another way is to use Symbold#to_proc which works like this: foo=:foo.to_proc; foo.call(obj,*args) #=> obj.method(:foo).call(*args) essentially apply is a 'useless' wrapper to .call, but it also works for UnboundMethod. See also dr/core_ext that add 'UnboundMethod#call'



50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/drain/ruby_ext/meta_ext.rb', line 50

def apply(*args,method: nil, to: self, **opts,&block)
	#note, in to self is Meta, except if we include it in another
	#module so that it would make sense
	method=method.unbind if method.class==Method
	case method
	when UnboundMethod
		method=method.bind(to)
	end
	if opts.empty?
		method.call(*args,&block)
	else
		method.call(*args,**opts,&block)
	end
end

#extend_objectObject

add extend_ancestors and extend_complete to Object



32
33
34
35
36
37
38
39
40
41
# File 'lib/drain/ruby_ext/meta_ext.rb', line 32

def extend_object
	include_ancestors=Meta.method(:include_ancestors)
	include_complete=Meta.method(:include_complete)
	Object.define_method(:extend_ancestors) do |m|
		include_ancestors.bind(singleton_class).call(m)
	end
	Object.define_method(:extend_complete) do |m|
		include_complete.bind(singleton_class).call(m)
	end
end

#get_bound_method(obj, method_name, &block) ⇒ Object



65
66
67
68
69
70
# File 'lib/drain/ruby_ext/meta_ext.rb', line 65

def get_bound_method(obj, method_name, &block)
	obj.singleton_class.send(:define_method,method_name, &block)
	method = obj.method method_name
	obj.singleton_class.send(:remove_method,method_name)
	method
end

#refined_module(klass) ⇒ Object

from http://stackoverflow.com/questions/18551058/better-way-to-turn-a-ruby-class-into-a-module-than-using-refinements convert a class into a module using refinements ex: (Class.new { include Meta.refined_module(String) { def length; super+5; end } }).new("foo").length #=> 8



7
8
9
10
11
12
13
14
# File 'lib/drain/ruby_ext/meta_ext.rb', line 7

def refined_module(klass)
	klass=klass.singleton_class unless Module===klass
	Module.new do
		include refine(klass) {
			yield if block_given?
		}
	end
end