Module: Chef::Mixin::LazyModuleInclude

Included in:
DSL::Recipe, DSL::Universal
Defined in:
lib/chef/mixin/lazy_module_include.rb

Overview

If you have:

module A

extend LazyModuleInclude

end

module B

include A

end

module C

include B

end

module Monkeypatches

def monkey
  puts "monkey!"
end

end

A.send(:include, Monkeypatches)

Then B and C and any classes that they’re included in will also get the #monkey method patched into them.

Instance Method Summary collapse

Instance Method Details

#descendantsObject



63
64
65
# File 'lib/chef/mixin/lazy_module_include.rb', line 63

def descendants
  @descendants ||= []
end

#include(*classes) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/chef/mixin/lazy_module_include.rb', line 67

def include(*classes)
  super
  classes.each do |klass|
    descendants.each do |descendant|
      descendant.send(:include, klass)
    end
  end
end

#included(klass) ⇒ Object

Most of the magick is in this hook which creates a closure over the parent class and then builds an “infector” module which infects all descendants and which is responsible for updating the list of descendants in the parent class.



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/chef/mixin/lazy_module_include.rb', line 49

def included(klass)
  super
  parent_klass = self
  infector = Module.new do
    define_method(:included) do |subklass|
      super(subklass)
      subklass.extend(infector)
      parent_klass.descendants.push(subklass)
    end
  end
  klass.extend(infector)
  parent_klass.descendants.push(klass)
end