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.
Minimal Example
Include Configurable and declare configurations using the config method. Configs now have accessors and initialize with the default value.
class ConfigClass
include Configurable
config :key, 'default', :short => 'k' # a sample config
end
c = ConfigClass.new
c.key # => 'default'
c.key = 'new value'
c.config[:key] # => 'new value'
Use a ConfigParser to parse configurations from the command line. Non-class options may be defined with (mostly) the same syntax as OptionParser:
parser = ConfigParser.new
# add class configurations
parser.add(ConfigClass.configurations)
# define an option a-la OptionParser
parser.on '-s', '--long ARGUMENT', 'description' do |value|
parser[:long] = value
end
parser.parse "one two --key value -s VALUE three"
# => ['one', 'two', 'three']
parser.config
# => {
# :key => 'value',
# :long => 'VALUE'
# }
"\n" + parser.to_s
# => %Q{
# -k, --key KEY a sample config
# -s, --long ARGUMENT description
# }
Usage
The config method is used to declare class configurations. A block may be provided to validate/transform inputs; many standard validations are available through the ‘c’ method (an alias for the Validation module).
class ConfigClass
include Configurable
# basic #
config :key, 'default' # a simple config
config :flag, false, &c.flag # a flag config
config :switch, false, &c.switch # a --[no-]switch config
config :num, 10, &c.integer # integer only
# fancy #
config :range, 1..10, &c.range # specifies a range
config :select, 'a', &c.select('a','b') # value must be 'a' or 'b'
config :list, [], &c.list # allows a list of entries
# custom #
config :upcase, 'default' do |value| # custom transformation
value.upcase
end
config :alt, 'default', # alternative flags
:short => 's',
:long => 'long',
:arg_name => 'CUSTOM'
# Initializes a new instance, setting the overriding configs.
def initialize(config={})
initialize_config(config)
end
end
ConfigParser uses the config declarations to parse configurations and to make a documented help string:
parser = ConfigParser.new
parser.add(ConfigClass.configurations)
parser.parse "a b --key=value --flag --no-switch --num 8 c"
# => ['a', 'b', 'c']
parser.config
# => {
# :key => 'value',
# :flag => true,
# :switch => false,
# :num => '8',
# :range => 1..10,
# :select => 'a',
# :list => [],
# :upcase => 'default',
# :alt => 'default'
# }
"\n" + parser.to_s
# => %Q{
# --key KEY a simple config
# --flag a flag config
# --[no-]switch a --[no-]switch config
# --num NUM integer only
# --range RANGE specifies a range
# --select SELECT value must be 'a' or 'b'
# --list LIST allows a list of entries
# --upcase UPCASE custom transformation
# -s, --long CUSTOM alternative flags
# }
Configurable classes typically call initialize_config to set configurations during initialization. The validation/transformation blocks are called as configurations are set. Notice how the :num and :upcase configs are translated on the instance:
c = ConfigClass.new(parser.config)
c.config.to_hash
# => {
# :key => 'value',
# :flag => true,
# :switch => false,
# :num => 8, # no longer a string
# :range => 1..10,
# :select => 'a',
# :list => [],
# :upcase => 'DEFAULT', # no longer downcase
# :alt => 'default'
# }
Configurations automatically generate accessors (the blocks are basically writer methods), and may be accessed through the 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'
c.select = 'b' # ok
c.select = 'c' # !> ValidationError
c.config[:select] = 'c' # !> ValidationError
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,
# :select => 'b',
# :list => [],
# :upcase => 'FINAL VALUE',
# :alt => 'default'
# }
See the Configurable module for more details.
Installation
Configurable is available as a gem on Gemcutter.
% gem install configurable
Info
- Developer
- License