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.