Module: Puppet::Util::SubclassLoader

Included in:
Network::Handler
Defined in:
lib/vendor/puppet/util/subclass_loader.rb

Overview

A module for loading subclasses into an array and retrieving them by name. Also sets up a method for each class so that you can just do Klass.subclass, rather than Klass.subclass(:subclass).

This module is currently used by network handlers and clients.

Instance Attribute Summary collapse

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args) ⇒ Object

See if we can load a class.



61
62
63
64
65
66
67
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 61

def method_missing(method, *args)
  unless self == self.classloader
    super
  end
  return nil unless defined?(@subclassname)
  self.send(@subclassname, method) || nil
end

Instance Attribute Details

#classloaderObject

Returns the value of attribute classloader.



7
8
9
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 7

def classloader
  @classloader
end

#loaderObject

Returns the value of attribute loader.



7
8
9
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 7

def loader
  @loader
end

Instance Method Details

#eachObject

Iterate over each of the subclasses.



10
11
12
13
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 10

def each
  @subclasses ||= []
  @subclasses.each { |c| yield c }
end

#handle_subclasses(name, path) ⇒ Object

The hook method that sets up subclass loading. We need the name of the method to create and the path in which to look for them.

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 17

def handle_subclasses(name, path)
  raise ArgumentError, "Must be a class to use SubclassLoader" unless self.is_a?(Class)
  @subclasses = []

        @loader = Puppet::Util::Autoload.new(
      self,
      
    path, :wrap => false
  )

  @subclassname = name

  @classloader = self

  # Now create a method for retrieving these subclasses by name.  Note
  # that we're defining a class method here, not an instance.
  meta_def(name) do |subname|
    subname = subname.to_s.downcase

    unless c = @subclasses.find { |c| c.name.to_s.downcase == subname }
      loader.load(subname)
      c = @subclasses.find { |c| c.name.to_s.downcase == subname }

      # Now make the method that returns this subclass.  This way we
      # normally avoid the method_missing method.
      define_method(subname) { c } if c and ! respond_to?(subname)
    end
    return c
  end
end

#inherited(sub) ⇒ Object

Add a new class to our list. Note that this has to handle subclasses of subclasses, thus the reason we’re keeping track of the @@classloader.



50
51
52
53
54
55
56
57
58
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 50

def inherited(sub)
  @subclasses ||= []
  sub.classloader = self.classloader
  if self.classloader == self
    @subclasses << sub
  else
    @classloader.inherited(sub)
  end
end

#name(dummy_argument = :work_arround_for_ruby_GC_bug) ⇒ Object

Retrieve or calculate a name.



70
71
72
73
74
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 70

def name(dummy_argument=:work_arround_for_ruby_GC_bug)
  @name ||= self.to_s.sub(/.+::/, '').intern

  @name
end

#subclassesObject

Provide a list of all subclasses.



77
78
79
80
# File 'lib/vendor/puppet/util/subclass_loader.rb', line 77

def subclasses
  @loader.loadall
  @subclasses.collect { |klass| klass.name }
end