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 32 def genclass(name, options = {}, &block) 33 genthing(name, Class, options, block) 34 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 55 def genmodule(name, options = {}, &block) 56 genthing(name, Module, options, block) 57 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 65 def rmclass(name, options) 66 const = genconst_string(name, options) 67 retval = false 68 if is_constant_defined?(const) 69 remove_const(const) 70 retval = true 71 end 72 73 hash = options[:hash] 74 if hash && hash.include?(name) 75 hash.delete(name) 76 retval = true 77 end 78 79 # Let them know whether we did actually delete a subclass. 80 retval 81 end
Private Instance Methods
Generates the constant to create or remove. @api private
# File lib/puppet/util/classgen.rb 87 def genconst_string(name, options) 88 const = options[:constant] 89 unless const 90 prefix = options[:prefix] || "" 91 const = prefix + name2const(name) 92 end 93 94 const 95 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 100 def genthing(name, type, options, block) 101 name = name.to_s.downcase.intern 102 103 if type == Module 104 #evalmethod = :module_eval 105 evalmethod = :class_eval 106 # Create the class, with the correct name. 107 klass = Module.new do 108 class << self 109 attr_reader :name 110 end 111 @name = name 112 end 113 else 114 options[:parent] ||= self 115 evalmethod = :class_eval 116 # Create the class, with the correct name. 117 klass = Class.new(options[:parent]) do 118 @name = name 119 end 120 end 121 122 # Create the constant as appropriation. 123 handleclassconst(klass, name, options) 124 125 # Initialize any necessary variables. 126 initclass(klass, options) 127 128 block ||= options[:block] 129 130 # Evaluate the passed block if there is one. This should usually 131 # define all of the work. 132 klass.send(evalmethod, &block) if block 133 134 klass.postinit if klass.respond_to? :postinit 135 136 # Store the class in hashes or arrays or whatever. 137 storeclass(klass, name, options) 138 139 klass 140 end
Handle the setting and/or removing of the associated constant. @api private
# File lib/puppet/util/classgen.rb 151 def handleclassconst(klass, name, options) 152 const = genconst_string(name, options) 153 154 if is_constant_defined?(const) 155 if options[:overwrite] 156 Puppet.info _("Redefining %{name} in %{klass}") % { name: name, klass: self } 157 remove_const(const) 158 else 159 raise Puppet::ConstantAlreadyDefined, 160 _("Class %{const} is already defined in %{klass}") % { const: const, klass: self } 161 end 162 end 163 const_set(const, klass) 164 165 const 166 end
Perform the initializations on the class. @api private
# File lib/puppet/util/classgen.rb 171 def initclass(klass, options) 172 klass.initvars if klass.respond_to? :initvars 173 174 attrs = options[:attributes] 175 if attrs 176 attrs.each do |param, value| 177 method = param.to_s + "=" 178 klass.send(method, value) if klass.respond_to? method 179 end 180 end 181 182 [:include, :extend].each do |method| 183 set = options[method] 184 if set 185 set = [set] unless set.is_a?(Array) 186 set.each do |mod| 187 klass.send(method, mod) 188 end 189 end 190 end 191 192 klass.preinit if klass.respond_to? :preinit 193 end
@api private
# File lib/puppet/util/classgen.rb 144 def is_constant_defined?(const) 145 const_defined?(const, false) 146 end
Convert our name to a constant. @api private
# File lib/puppet/util/classgen.rb 197 def name2const(name) 198 name.to_s.capitalize 199 end
Store the class in the appropriate places. @api private
# File lib/puppet/util/classgen.rb 203 def storeclass(klass, klassname, options) 204 hash = options[:hash] 205 if hash 206 if hash.include? klassname and ! options[:overwrite] 207 raise Puppet::SubclassAlreadyDefined, 208 _("Already a generated class named %{klassname}") % { klassname: klassname } 209 end 210 211 hash[klassname] = klass 212 end 213 214 # If we were told to stick it in a hash, then do so 215 array = options[:array] 216 if array 217 if (klass.respond_to? :name and 218 array.find { |c| c.name == klassname } and 219 ! options[:overwrite]) 220 raise Puppet::SubclassAlreadyDefined, 221 _("Already a generated class named %{klassname}") % { klassname: klassname } 222 end 223 224 array << klass 225 end 226 end