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.
Iterate over each of the subclasses.
# File lib/puppet/util/subclass_loader.rb, line 10 def each @subclasses ||= [] @subclasses.each { |c| yield c } end
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.
# File lib/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
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.
# File lib/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
See if we can load a class.
# File lib/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
Retrieve or calculate a name.
# File lib/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
Provide a list of all subclasses.
# File lib/puppet/util/subclass_loader.rb, line 77 def subclasses @loader.loadall @subclasses.collect { |klass| klass.name } end