Configure
Configure offers an easy way for configure your application using a DSL. It provides a single-method interface that receives a block and returns well-structured configuration values.
Usage
The most simple way configure can be used is to pass a block to the Configure.process method and receive back a hash with the configuration values.
laser = Configure.process {
label "red laser"
wave_length 700
}
laser == {
:label => "red laser",
:wave_length => 700
} # => true
Nested configurations
It is also possible to pass blocks to configuration keys and combine multiple values to an array.
laser = Configure.process {
label "red and violet pulse laser"
pulse {
wave_length 700
duration 20
}
pulse {
wave_length 400
duration 20
}
}
laser == {
:label => "red and violet pulse laser",
:pulse => [
{ :wave_length => 700, :duration => 20 },
{ :wave_length => 400, :duration => 20 }
]
} # => true
If arguments and a block is passed to a configuration key, the arguments are stored at the :arguments key inside the nested configuration.
laser = Configure.process {
label "red pulse laser"
pulse "test" {
wave_length 700
duration 20
}
}
laser = {
:label => "red pulse laser",
:pulse => {
:wave_length => 700,
:duration => 20,
:arguments => [ "test" ]
}
} # => true
Schema
In order receive a more structured configuration, a schema can be passed to the Configure.process method. This schema is a simple hash, that can be created - off course - using the configure syntax ;-) (Guess how the schema-structure is defined internally ;-) )
Defaults
schema = Configure::Schema.build {
defaults {
wave_length 700
duration 20
}
}
laser = Configure.process(schema) {
label "violet pulse laser"
wave_length 400
}
laser = {
:label => "violet pulse laser",
:wave_length => 400,
:duration => 20
} # => true
Nested schemas
Nested schema have to go to the nested section.
schema = Configure::Schema.build {
nested {
pulse {
defaults {
wave_length 700
duration 20
}
}
}
}
If a nested schema provides the key argument_keys, the arguments that have been passed along with the nested configuration, are stored to these keys. The rest will be assigned to the :arguments key as before.
schema = Configure::Schema.build {
nested {
pulse {
argument_keys :wave_length, :duration
}
}
}
laser = Configure.process(schema) {
pulse(700, 20, :extra) {
label "red pulse"
}
}
laser == {
:pulse => {
:wave_length => 700,
:duration => 20,
:arguments => [ :extra ]
:label => "red pulse"
}
} # => true
The :nested_default attribute can be used to define a default schema for all nested blocks.
Configuration class
Sometimes, a hash may not be the best data structure to store the configuration. If a more strict structure is needed, the attribute :configuration_class can be set the schema. When the configuration is processed, the class is instantiated and the values are set via key= or the []= methods. If both is not possible, an exception is raised.
class Laser
attr_accessor :label
attr_accessor :wave_length
attr_accessor :duration
end
schema = Configure::Schema.build {
configuration_class Laser
defaults {
duration 20
}
}
laser = Configure.process(schema) {
label "red laser"
wave_length 700
}
laser.is_a? Laser # => true
laser.label == "red laser" # => true
laser.wave_length == 700 # => true
laser.duration == 20 # => true
Configure.process(schema) {
invalid_key "value"
} # => raises Configure::InvalidKeyError
The Only list
If the :only attribute is defined in a schema, only the values of the given keys are allowed to be set.
schema = Configure::Schema.build {
only :duration
}
laser = Configure.process(schema) {
wave_length 700
} # => raises Configure::InvalidKeyError
The Not-Nil list
If the :not_nil attribute is defined in a schema, an error will be raised if one of the values of the given keys remains nil.
schema = Configure::Schema.build {
only :wave_length, :duration
not_nil :duration
}
laser = Configure.process(schema) {
wave_length 700
} # => raises Configure::NilValueError
Development
Development has been done test-driven and the code follows at most the Clean Code paradigms. Code smells has been removed by using the reek code smell detector.
This project is still under development. Any bug report and contribution is welcome!
Support
Apart from contribution, support via Flattr is welcome.