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.