Module: Chef::Mixin::LazyModuleInclude

Included in:
DSL::Core, DSL::Recipe, DSL::Recipe::FullDSL
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