Class: Configurability::Config
- Inherits:
-
Object
- Object
- Configurability::Config
- Extended by:
- Forwardable, Loggability
- Includes:
- DataUtilities
- Defined in:
- lib/configurability/config.rb
Overview
A configuration object class for systems with Configurability
Author/s
-
Michael Granger <[email protected]>
-
Mahlon E. Smith <[email protected]>
This class also delegates some of its methods to the underlying struct:
- Configurability::Config::Struct#to_hash
-
#to_hash (delegated to its internal Struct)
- Configurability::Config::Struct#member?
-
#member? (delegated to its internal Struct)
- Configurability::Config::Struct#members
-
#members (delegated to its internal Struct)
- Configurability::Config::Struct#merge
-
#merge (delegated to its internal Struct)
- Configurability::Config::Struct#merge!
-
#merge! (delegated to its internal Struct)
- Configurability::Config::Struct#each
-
#each (delegated to its internal Struct)
- Configurability::Config::Struct#[]
-
#[] (delegated to its internal Struct)
- Configurability::Config::Struct#[]=
-
#[]= (delegated to its internal Struct)
Defined Under Namespace
Modules: DataUtilities Classes: Struct
Instance Attribute Summary collapse
-
#path ⇒ Object
the path to the config file, if loaded from a file.
-
#struct ⇒ Object
readonly
The underlying config data structure.
-
#time_created ⇒ Object
The time the configuration was loaded.
Class Method Summary collapse
-
.load(path, defaults = nil, &block) ⇒ Object
Read and return a Configurability::Config object from the file at the given
path. -
.merge_complex_hashes(key, oldval, newval) ⇒ Object
Recursive hash-merge function.
Instance Method Summary collapse
-
#changed? ⇒ Boolean
Returns
trueif the configuration has changed since it was last loaded, either by setting one of its members or changing the file from which it was loaded. -
#changed_reason ⇒ Object
If the configuration has changed, return the reason.
-
#dump ⇒ Object
Return the config object as a YAML hash.
-
#initialize(source = nil, path = nil, defaults = nil, &block) ⇒ Config
constructor
Create a new Configurability::Config object.
-
#inspect ⇒ Object
Return a human-readable, compact representation of the configuration suitable for debugging.
-
#install ⇒ Object
Install this config object in any objects that have added Configurability.
-
#is_older_than?(path) ⇒ Boolean
Return
trueif the specifiedfileis newer than the time the receiver was created. -
#reload ⇒ Object
Reload the configuration from the original source if it has changed.
-
#respond_to?(sym) ⇒ Boolean
Returns
truefor methods which can be autoloaded. -
#write(path = @path, *args) ⇒ Object
Write the configuration object using the specified name and any additional
args.
Methods included from DataUtilities
#stringify_keys, #symbolify_keys
Constructor Details
#initialize(source = nil, path = nil, defaults = nil, &block) ⇒ Config
Create a new Configurability::Config object. If the optional source argument is specified, parse the config from it. If one is given, the block will be evaluated in the context of the config object after the config is loaded, unless it accepts an argument, in which case the config object is passed as the argument.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/configurability/config.rb', line 81 def initialize( source=nil, path=nil, defaults=nil, &block ) # Shift the hash parameter if it shows up as the path if path.is_a?( Hash ) defaults = path path = nil end # Make a deep copy of the defaults before loading so we don't modify # the argument @defaults = defaults ? Marshal.load( Marshal.dump(defaults) ) : nil @time_created = Time.now @path = path if source @struct = self.make_configstruct_from_source( source, @defaults ) else @struct = Configurability::Config::Struct.new( @defaults ) end if block Configurability.log.debug "Block arity is: %p" % [ block.arity ] # A block with an argument is called with the config as the argument # instead of instance_evaled case block.arity when 0, -1 # 1.9 and 1.8, respectively Configurability.log.debug "Instance evaling in the context of %p" % [ self ] self.instance_eval( &block ) else block.call( self ) end end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *args) ⇒ Object (protected)
Handle calls to struct-members
272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/configurability/config.rb', line 272 def method_missing( sym, *args ) key = sym.to_s.sub( /(=|\?)$/, '' ).to_sym self.class.class_eval %{ def #{key}; @struct.#{key}; end def #{key}=(arg); @struct.#{key} = arg; end def #{key}?; @struct.#{key}?; end } return self.method( sym ).call( *args ) end |
Instance Attribute Details
#path ⇒ Object
the path to the config file, if loaded from a file
132 133 134 |
# File 'lib/configurability/config.rb', line 132 def path @path end |
#struct ⇒ Object (readonly)
The underlying config data structure
126 127 128 |
# File 'lib/configurability/config.rb', line 126 def struct @struct end |
#time_created ⇒ Object
The time the configuration was loaded
129 130 131 |
# File 'lib/configurability/config.rb', line 129 def time_created @time_created end |
Class Method Details
.load(path, defaults = nil, &block) ⇒ Object
Read and return a Configurability::Config object from the file at the given path.
55 56 57 58 59 60 |
# File 'lib/configurability/config.rb', line 55 def self::load( path, defaults=nil, &block ) path = Pathname( path ). source = path.read Configurability.log.debug "Read %d bytes from %s" % [ source.length, path ] return new( source, path, defaults, &block ) end |
.merge_complex_hashes(key, oldval, newval) ⇒ Object
Recursive hash-merge function. Used as the block argument to a Hash#merge.
64 65 66 67 68 |
# File 'lib/configurability/config.rb', line 64 def self::merge_complex_hashes( key, oldval, newval ) return oldval.merge( newval, &method(:merge_complex_hashes) ) if oldval.respond_to?( :merge ) && newval.respond_to?( :merge ) return newval end |
Instance Method Details
#changed? ⇒ Boolean
Returns true if the configuration has changed since it was last loaded, either by setting one of its members or changing the file from which it was loaded.
178 179 180 |
# File 'lib/configurability/config.rb', line 178 def changed? return self.changed_reason ? true : false end |
#changed_reason ⇒ Object
If the configuration has changed, return the reason. If it hasn’t, returns nil.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/configurability/config.rb', line 185 def changed_reason if @struct.dirty? Configurability.log.debug "Changed_reason: struct was modified" return "Struct was modified" end if self.path && self.is_older_than?( self.path ) Configurability.log.debug "Source file (%s) has changed." % [ self.path ] return "Config source (%s) has been updated since %s" % [ self.path, self.time_created ] end return nil end |
#dump ⇒ Object
Return the config object as a YAML hash
143 144 145 146 |
# File 'lib/configurability/config.rb', line 143 def dump strhash = stringify_keys( self.to_h ) return YAML.dump( strhash ) end |
#inspect ⇒ Object
Return a human-readable, compact representation of the configuration suitable for debugging.
232 233 234 235 236 237 238 239 240 |
# File 'lib/configurability/config.rb', line 232 def inspect return "#<%s:0x%0x16 loaded from %s; %d sections: %s>" % [ self.class.name, self.object_id * 2, self.path ? self.path : "memory", self.struct.members.length, self.struct.members.join( ', ' ) ] end |
#install ⇒ Object
Install this config object in any objects that have added Configurability.
137 138 139 |
# File 'lib/configurability/config.rb', line 137 def install Configurability.configure_objects( self ) end |
#is_older_than?(path) ⇒ Boolean
Return true if the specified file is newer than the time the receiver was created.
203 204 205 206 207 208 209 |
# File 'lib/configurability/config.rb', line 203 def is_older_than?( path ) return false unless path.exist? st = path.stat Configurability.log.debug "File mtime is: %s, comparison time is: %s" % [ st.mtime, @time_created ] return st.mtime > @time_created end |
#reload ⇒ Object
Reload the configuration from the original source if it has changed. Returns true if it was reloaded and false otherwise.
214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/configurability/config.rb', line 214 def reload raise "can't reload from an in-memory source" unless self.path if self.changed? self.time_created = Time.now source = self.path.read @struct = self.make_configstruct_from_source( source, @defaults ) self.install return true else return false end end |
#respond_to?(sym) ⇒ Boolean
Returns true for methods which can be autoloaded
169 170 171 172 |
# File 'lib/configurability/config.rb', line 169 def respond_to?( sym ) return true if @struct.member?( sym.to_s.sub(/(=|\?)$/, '').to_sym ) super end |
#write(path = @path, *args) ⇒ Object
Write the configuration object using the specified name and any additional args.
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/configurability/config.rb', line 151 def write( path=@path, *args ) unless path.is_a?( String ) || path.is_a?( Pathname ) args.unshift( path ) path = @path end raise ArgumentError, "No name associated with this config." unless path self.log.info "Writing config to %s with args: %p" % [ path, args ] path = Pathname( path ) path.open( File::WRONLY|File::CREAT|File::TRUNC, *args ) do |ofh| ofh.print( self.dump ) end end |