Configurable

Class configurations that map to the command line.

Description

Configurable allows the declaration of class configurations. Configurations are inheritable, delegate to methods, and have hash-like access. Configurable maps configurations to the command line through ConfigParser and is used by the Tap framework.

Check out these links for development, and bug tracking.

Usage

Use the config method to declare class configurations. A block may be provided to validate inputs, and many standard validations are available through the ‘c’ method (an alias for the Validation module).

class ConfigClass
  include Configurable

  config :key, 'default', :short => 'k'   # a simple config with short
  config :flag, false, &c.flag            # a flag config
  config :switch, false, &c.switch        # a --[no-]switch config
  config :num, 10, &c.integer             # integer only
  config :range, 1..10, &c.range          # range only
  config :upcase, 'default' do |value|    # custom transformation
    value.upcase
  end

  def initialize(overrides={})
    initialize_config(overrides)
  end
end

A ConfigParser can parse configurations from command line arguments, and turn them into a documented help string:

parser = ConfigParser.new
parser.add(ConfigClass.configurations)

parser.parse "one two --key=value --flag --no-switch --num 8 --range a..z three"  
# => ['one', 'two', 'three']

parser.config  
# => {
# :key => 'value',
# :flag => true,
# :switch => false,
# :num => '8',
# :range => 'a..z',
# :upcase => 'default'
# }

"\n" + parser.to_s
# => %Q{
#    -k, --key KEY                    a simple config with short
#        --flag                       a flag config
#        --[no-]switch                a --[no-]switch config
#        --num NUM                    integer only
#        --range RANGE                range only
#        --upcase UPCASE              custom transformation
# }

Configurable classes typically call initialize_config to set configurations during initialization. The validation/transformation blocks are called as configurations are set. Notice how the :range and :upcase values have been transformed from the input config.

c = ConfigClass.new(parser.config)
c.config.to_hash      
# => {
# :key => 'value',
# :flag => true,            
# :switch => false,         
# :num => 8,
# :range => 'a'..'z',       # notice these values
# :upcase => 'DEFAULT'      # have been transformed
# }

Configurations automatically generate accessors (the blocks are basically writer methods), but they are also accessible through the hash-like config object. Configurations are validated every time they are set, regardless of whether they are set through an accessor or config.

c.upcase                    # => 'DEFAULT'

c.config[:upcase] = 'neW valuE'
c.upcase                    # => 'NEW VALUE'

c.upcase = 'fiNal Value'
c.config[:upcase]           # => 'FINAL VALUE'

By default config treats string and symbol keys identically, making YAML an obvious choice for configuration files.

yaml_str = %Q{
key: a new value
flag: false
range: 1..100
}

c.reconfigure(YAML.load(yaml_str))
c.config.to_hash      
# => {
# :key => 'a new value',
# :flag => false,
# :switch => false,
# :num => 8,
# :range => 1..100,
# :upcase => 'FINAL VALUE'
# }

See the Configurable module for more details.

Installation

Configurable is available as a gem on RubyForge. Use:

% gem install configurable

Info

Copyright © 2008-2009, Regents of the University of Colorado.

Developer

Simon Chiang, Biomolecular Structure Program, Hansen Lab

Support

CU Denver School of Medicine Deans Academic Enrichment Fund

License

MIT-Style