Class: Util::ConfigYaml
- Inherits:
-
Hash
- Object
- Hash
- Util::ConfigYaml
- Defined in:
- ../lib/config.rb
Overview
The main configuration component of the GERET library. The ConfigYaml instance loads the file with the YAML syntax and provides the configuration values and the generic factory for the creation of Ruby classes. This facility allows the separation of the generic GE algorithm from its internal classes using the “Injection of control” design pattern.
Class Method Summary (collapse)
-
+ (Object) parse_options(args, options = {})
This helper function takes the options hash and overloads its values according the args.
-
+ (Object) remove_options!(args)
This helper function removes all items beginning with ’--’ from the argument array.
Instance Method Summary (collapse)
-
- (Object) factory(key, *args)
Create the instance of the class which is dynamically specified by the YAML file.
-
- (ConfigYaml) initialize(file = nil)
constructor
Load the YAML file and prepare the hash of configuration values.
Constructor Details
- (ConfigYaml) initialize(file = nil)
Load the YAML file and prepare the hash of configuration values. For example, if the file.yaml contains this text:
selector:
class: MySelector
require: myselector_class.rb
attribute1: 3
attr2: something
option1: 42
composite_option:
level1:
level2: foo
then, after the calling:
cfg = ConfigYaml.new('file.yaml')
the cfg[‘selector’] will be the hash of factory configuration values:
{'class'=>'MySelector', 'require'=>'myselector_class.rb', 'attribute1'=>3, 'attr2'=>'something'}
the cfg[‘option1’] will contain the value 42 and, the cfg[‘composite_option’] will be:
{ 'level1' => {'level2'=>'foo'} }
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File '../lib/config.rb', line 38 def initialize file=nil super() @class_methods = Set.new return if file.nil? obj = YAML::load( File.open( file ) ) raise "ConfigYaml: top level yaml object is not a hash" unless obj.kind_of? Hash update obj each_value do |details| requirement = details.fetch( 'require', nil ) require requirement unless requirement.nil? end end |
Class Method Details
+ (Object) parse_options(args, options = {})
This helper function takes the options hash and overloads its values according the args. Note the ’-’ character separates the level of the hashing.
For example:
args = ['file.txt', '--arg=12', '--no', '--opt-sub=xyz', 'file2.out', '--opt-sub2-sub3=4.4']
opts = ConfigYaml.( args, {'orig'=>42, 'arg'=>'22'} )
opts will be:
{ 'orig'=>42, 'arg'=>12, 'no'=>nil, 'opt'=>{'sub'=>'xyz', 'sub2'=>{'sub3'=>4.4} } }
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File '../lib/config.rb', line 147 def ConfigYaml.( args, = {} ) args.each do |arg| next unless /^--/ =~ arg key, value = arg.sub( /^--/, '' ).split('=') value = value.to_i if value.to_i.to_s == value value = value.to_f if value.to_f.to_s == value hsh = keys = key.split(/-/) while keys.size > 1 k = keys.shift hsh[k] = {} unless hsh.has_key? k hsh = hsh[k] end hsh[ keys.last ] = value end end |
+ (Object) remove_options!(args)
This helper function removes all items beginning with ’--’ from the argument array. Eg.:
ARGV = ['file.txt', '--option=42', 'file2.txt', '--quiet', '-x', 'output.txt']
ConfigYaml. ARGV
ARGV is now:
['file.txt', 'file2.txt', '-x', 'output.txt']
173 174 175 |
# File '../lib/config.rb', line 173 def ConfigYaml. args args.delete_if { |arg| /^--/ =~ arg } end |
Instance Method Details
- (Object) factory(key, *args)
Create the instance of the class which is dynamically specified by the YAML file. The key (the first argument) has to be present as the section in the configuration, the class subsection contains the name of the class. All remaining args of the factory method are then passed as the constructor arguments. The optional require subsection the file with the class implementation (all GERET’s own classes are automatically present via require ‘lib/geret’). Subsections with leading underscores are interpreted as names of class methods. The underscores are removed from the methods’ names and methods are called once, just before the creation of the first instance. Remaining keys are considered as attribute names and their values are always assigned to the newly created instance.
For example, if the file.yaml contains this text:
selector:
class: MySelector
require: myselector_class.rb
attribute1: 3
attr2: something
_prepare_context: 42
then the code:
cfg = ConfigYaml.new('file.yaml')
sel = cfg.factory( 'selector', 'my_1st_arg', '2nd_one' )
sel = cfg.factory( 'selector', 'another', 'instance' )
is equivalent to:
require 'myselector_class.rb'
MySelector.prepare_context( 42 )
sel = MySelector.new( 'my_1st_arg', '2nd_one' )
sel.attribute1 = 3
sel.attr2 = 'something'
sel = MySelector.new( 'another', 'instance' )
sel.attribute1 = 3
sel.attr2 = 'something'
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File '../lib/config.rb', line 94 def factory( key, *args ) details = fetch( key, nil ) raise "ConfigYaml: missing key when calling factory('#{key}')" if details.nil? klass = details.fetch( 'class', nil ) raise "ConfigYaml: missing class when calling factory('#{key}')" if klass.nil? requirement = details.fetch( 'require', nil ) require requirement unless requirement.nil? unless @class_methods.include? klass @class_methods.add klass static_keys = details.keys.find_all { |k| k[0].chr == '_' } static_keys.each do |k| method = k.sub( /^_/, '' ) text = "#{klass}.#{method}( #{ details[k].inspect } )" eval text end end if args.empty? text = "#{klass}.new( #{ details.fetch( 'initialize', '' ) } )" else text = "#{klass}.new( " args.each_index { |index| text += "args[#{index}]," } text = text[ 0...text.size-1 ] + ' )' end begin instance = eval text rescue => details raise "ConfigYaml: cannot eval '#{text}' (missing require?)\n" + details.inspect end details.each_pair do |k,value| next if ['class','initialize', 'require'].include? k next if k[0].chr == '_' # no class methods, please eval "instance.#{k} = #{value.inspect}" end instance end |