Module: Compound::Host

Defined in:
lib/compound/host.rb

Overview

Include this module in a class to gain the ability to host Parts, which each embody a module, appearing to an outside object as if the modules themselves were mixed in, while maintaining separation among the modules. Refer to the README for more information

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(sym, *args, &block) ⇒ Object

Forward an undefined method if it is in one of the Parts



37
38
39
40
41
# File 'lib/compound/host.rb', line 37

def method_missing sym, *args, &block
  component = @_compound_parts && 
              @_compound_parts.detect { |obj| obj.respond_to? sym }
  component ? (component.send sym, *args, &block) : super
end

Instance Method Details

#compound(mod) ⇒ Object

Internalize a new Part embodying the given module



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/compound/host.rb', line 11

def compound mod
  first_time_array = nil
  @_compound_parts ||= (first_time_array=[])
  
  # Pretend that the compounded modules are in the inheritance tree
  singleton_class.send :define_singleton_method, :ancestors do
    super() + first_time_array.map { |part|
      part.instance_variable_get(:@_compound_component_module)
    }
  end if first_time_array
  
  uncompound mod
  @_compound_parts.unshift ::Compound::Part.new self, mod
  mod.compounded(self) if mod.respond_to? :compounded
  return mod
end

#is_a?(mod) ⇒ Boolean

Pretend that the compounded modules are in the inheritance tree

Returns:

  • (Boolean)


67
68
69
70
71
# File 'lib/compound/host.rb', line 67

def is_a? mod
  super or !!(@_compound_parts && @_compound_parts.detect { |part|
    part.instance_variable_get(:@_compound_component_module) == mod
  })
end

#kind_of?(mod) ⇒ Boolean

Pretend that the compounded modules are in the inheritance tree

Returns:

  • (Boolean)


60
61
62
63
64
# File 'lib/compound/host.rb', line 60

def kind_of? mod
  super or !!(@_compound_parts && @_compound_parts.detect { |part|
    part.instance_variable_get(:@_compound_component_module) == mod
  })
end

#method(sym) ⇒ Object

Return the Method object associated with the symbol, even if it is in one of the Parts and not the Host



51
52
53
54
55
56
57
# File 'lib/compound/host.rb', line 51

def method sym
  return super if methods.include? sym
  component = @_compound_parts && 
              @_compound_parts.detect { |obj| obj.respond_to? sym }
  component ? component.method(sym) :
    raise(NameError, "undefined method `#{sym}' for object `#{self}'")
end

#respond_to?(sym, *rest) ⇒ Boolean

Pretend to also respond_to methods in the Parts as well as the Host

Returns:

  • (Boolean)


44
45
46
47
# File 'lib/compound/host.rb', line 44

def respond_to? sym, *rest
  super || !!(@_compound_parts && 
              @_compound_parts.detect { |obj| obj.respond_to? sym })
end

#uncompound(mod) ⇒ Object

Remove the Part associated with the given module



29
30
31
32
33
34
# File 'lib/compound/host.rb', line 29

def uncompound mod
  (@_compound_parts &&
  (@_compound_parts.reject! { |part|
    part.instance_variable_get(:@_compound_component_module) == mod
  } ? mod : nil))
end