module Puppet::Util::ClassGen
This is a utility module for generating classes. @api public
Attributes
Public Instance Methods
Create a new class. @param name [String] the name of the generated class @param options [Hash] a hash of options @option options [Array<Class>] :array if specified, the generated class is appended to this array @option options [Hash<{String => Object}>] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Proc] :block a block to evaluate in the context of the class (this block can be provided
this way, or as a normal yield block).
@option options [String] :constant (name with first letter capitalized) what to set the constant that references
the generated class to.
@option options [Hash] :hash a hash of existing classes that this class is appended to (name => class).
This hash must be specified if the `:overwrite` option is set to `true`.
@option options [Boolean] :overwrite whether an overwrite of an existing class should be allowed (requires also
defining the `:hash` with existing classes as the test is based on the content of this hash).
@option options [Class] :parent (self) the parent class of the generated class. @option options [String] ('') :prefix the constant prefix to prepend to the constant name referencing the
generated class.
@return [Class] the generated class
# File lib/puppet/util/classgen.rb 33 def genclass(name, options = {}, &block) 34 genthing(name, Class, options, block) 35 end
Creates a new module. @param name [String] the name of the generated module @param options [Hash] hash with options @option options [Array<Class>] :array if specified, the generated class is appended to this array @option options [Hash<{String => Object}>] :attributes a hash that is applied to the generated class
by calling setter methods corresponding to this hash's keys/value pairs. This is done before the given block is evaluated.
@option options [Proc] :block a block to evaluate in the context of the class (this block can be provided
this way, or as a normal yield block).
@option options [String] :constant (name with first letter capitalized) what to set the constant that references
the generated class to.
@option options [Hash] :hash a hash of existing classes that this class is appended to (name => class).
This hash must be specified if the `:overwrite` option is set to `true`.
@option options [Boolean] :overwrite whether an overwrite of an existing class should be allowed (requires also
defining the `:hash` with existing classes as the test is based on the content of this hash). the capitalized name is appended and the result is set as the constant.
@option options [String] ('') :prefix the constant prefix to prepend to the constant name referencing the
generated class.
@return [Module] the generated Module
# File lib/puppet/util/classgen.rb 56 def genmodule(name, options = {}, &block) 57 genthing(name, Module, options, block) 58 end
Removes an existing class. @param name [String] the name of the class to remove @param options [Hash] options @option options [Hash] :hash a hash of existing classes from which the class to be removed is also removed @return [Boolean] whether the class was removed or not
# File lib/puppet/util/classgen.rb 66 def rmclass(name, options) 67 const = genconst_string(name, options) 68 retval = false 69 if is_constant_defined?(const) 70 remove_const(const) 71 retval = true 72 end 73 74 hash = options[:hash] 75 if hash && hash.include?(name) 76 hash.delete(name) 77 retval = true 78 end 79 80 # Let them know whether we did actually delete a subclass. 81 retval 82 end
Private Instance Methods
Generates the constant to create or remove. @api private
# File lib/puppet/util/classgen.rb 88 def genconst_string(name, options) 89 const = options[:constant] 90 unless const 91 prefix = options[:prefix] || "" 92 const = prefix + name2const(name) 93 end 94 95 const 96 end
This does the actual work of creating our class or module. It's just a slightly abstract version of genclass. @api private
# File lib/puppet/util/classgen.rb 101 def genthing(name, type, options, block) 102 name = name.to_s.downcase.intern 103 104 if type == Module 105 #evalmethod = :module_eval 106 evalmethod = :class_eval 107 # Create the class, with the correct name. 108 klass = Module.new do 109 class << self 110 attr_reader :name 111 end 112 @name = name 113 end 114 else 115 options[:parent] ||= self 116 evalmethod = :class_eval 117 # Create the class, with the correct name. 118 klass = Class.new(options[:parent]) do 119 @name = name 120 end 121 end 122 123 # Create the constant as appropriation. 124 handleclassconst(klass, name, options) 125 126 # Initialize any necessary variables. 127 initclass(klass, options) 128 129 block ||= options[:block] 130 131 # Evaluate the passed block if there is one. This should usually 132 # define all of the work. 133 klass.send(evalmethod, &block) if block 134 135 klass.postinit if klass.respond_to? :postinit 136 137 # Store the class in hashes or arrays or whatever. 138 storeclass(klass, name, options) 139 140 klass 141 end
Handle the setting and/or removing of the associated constant. @api private
# File lib/puppet/util/classgen.rb 152 def handleclassconst(klass, name, options) 153 const = genconst_string(name, options) 154 155 if is_constant_defined?(const) 156 if options[:overwrite] 157 Puppet.info _("Redefining %{name} in %{klass}") % { name: name, klass: self } 158 remove_const(const) 159 else 160 raise Puppet::ConstantAlreadyDefined, 161 _("Class %{const} is already defined in %{klass}") % { const: const, klass: self } 162 end 163 end 164 const_set(const, klass) 165 166 const 167 end
Perform the initializations on the class. @api private
# File lib/puppet/util/classgen.rb 172 def initclass(klass, options) 173 klass.initvars if klass.respond_to? :initvars 174 175 attrs = options[:attributes] 176 if attrs 177 attrs.each do |param, value| 178 method = param.to_s + "=" 179 klass.send(method, value) if klass.respond_to? method 180 end 181 end 182 183 [:include, :extend].each do |method| 184 set = options[method] 185 if set 186 set = [set] unless set.is_a?(Array) 187 set.each do |mod| 188 klass.send(method, mod) 189 end 190 end 191 end 192 193 klass.preinit if klass.respond_to? :preinit 194 end
@api private
# File lib/puppet/util/classgen.rb 145 def is_constant_defined?(const) 146 const_defined?(const, false) 147 end
Convert our name to a constant. @api private
# File lib/puppet/util/classgen.rb 198 def name2const(name) 199 name.to_s.capitalize 200 end
Store the class in the appropriate places. @api private
# File lib/puppet/util/classgen.rb 204 def storeclass(klass, klassname, options) 205 hash = options[:hash] 206 if hash 207 if hash.include? klassname and ! options[:overwrite] 208 raise Puppet::SubclassAlreadyDefined, 209 _("Already a generated class named %{klassname}") % { klassname: klassname } 210 end 211 212 hash[klassname] = klass 213 end 214 215 # If we were told to stick it in a hash, then do so 216 array = options[:array] 217 if array 218 if (klass.respond_to? :name and 219 array.find { |c| c.name == klassname } and 220 ! options[:overwrite]) 221 raise Puppet::SubclassAlreadyDefined, 222 _("Already a generated class named %{klassname}") % { klassname: klassname } 223 end 224 225 array << klass 226 end 227 end