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

[View source]

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

def descendants
  @descendants ||= []
end

#include(*classes) ⇒ Object

[View source]

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.

[View source]

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