Method: Module#method_space
- Defined in:
- lib/core/facets/module/method_space.rb
#method_space(name, mod = nil, &blk) ⇒ Object
Create method namespaces, allowing for method chains but still accessing the object’s instance.
class A
attr_writer :x
method_space :inside do
def x; @x; end
end
end
a = A.new
a.x = 10
a.inside.x #=> 10
expect NoMethodError do
a.x
end
NOTE: This method is not a common core extension and is not loaded automatically when using require 'facets'.
CREDIT: Pit Captain
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/core/facets/module/method_space.rb', line 32 def method_space(name, mod=nil, &blk) ## If block is given then create a module, otherwise ## get the name of the module. if block_given? name = name.to_s raise ArgumentError if mod mod = Module.new(&blk) else if Module === name mod = name name = mod.basename.downcase end mod = mod.dup end ## Include the module. This is neccessary, otherwise ## Ruby won't let us bind the instance methods. include mod ## Save the instance methods of the module and ## replace them with a "transparent" version. methods = {} mod.instance_methods(false).each do |m| methods[m.to_sym] = mod.instance_method(m) mod.module_eval %{ def #{m}(*a,&b) super(*a,&b) end } ##mod.instance_eval do ## define_method(m) ## super ## end ##end end ## Add a method for the namespace that delegates ## via the Functor to the saved instance methods. define_method(name) do mtab = methods Functor.new do |op, *args| if meth = mtab[op.to_sym] meth.bind(self).call(*args) else #self.__send__(op, *args) raise NoMethodError, "undefined method `#{m}'" end end end end |