mbklein / confstruct

Yet another hash/struct-like configuration object for Ruby
190 stars 9 forks source link

confstruct Build Status Dependency Status

Confstruct is yet another configuration gem. Definable and configurable by hash, struct, or block, confstruct aims to provide the flexibility to do things your way, while keeping things simple and intuitive.

Usage

First, either create an empty ConfStruct::Configuration object:

config = Confstruct::Configuration.new

Or with some default values:

config = Confstruct::Configuration.new({ 
  :project => 'confstruct', 
  :github => { 
    :url => 'http://www.github.com/mbklein/confstruct',
    :branch => 'master'
  }
})

The above can also be done in block form:

config = Confstruct::Configuration.new do 
  project 'confstruct'
  github do
    url 'http://www.github.com/mbklein/confstruct'
    branch 'master'
  end
end

There are many ways to access and configure the resulting config object...

As a struct...

config.project = 'other-project'
config.github.url = 'http://www.github.com/somefork/other-project'
config.github.branch = 'pre-1.0'

As a block...

config.configure do
  project 'other-project'
  github.url 'http://www.github.com/somefork/other-project'
  github.branch 'pre-1.0'
end

As a hash...

config[:github][:url] = 'http://www.github.com/somefork/other-project'

Or even as a crazy struct/hash hybrid...

config.github[:url] = 'http://www.github.com/somefork/other-project'
config[:github].branch = 'pre-1.0'

Each sub-hash/struct is a configuration object in its own right, and can be treated as such. (Note the ability to leave the configure method off the inner call.)

config.configure do
  project 'other-project'
  github do
    url 'http://www.github.com/somefork/other-project'
    branch 'pre-1.0'
  end
end

You can even

config.project = 'other-project'
config.github = { :url => 'http://www.github.com/somefork/other-project', :branch => 'pre-1.0' }

The configure method will even perform a deep merge for you if you pass it a hash or hash-like object (anything that responds to each_pair)

config.configure({:project => 'other-project', :github => {:url => 'http://www.github.com/somefork/other-project', :branch => 'pre-1.0'}})

Because it's "hashes all the way down," you can store your defaults and/or configurations in YAML files, or in Ruby scripts if you need to evaluate expressions at config-time.

However you do it, the resulting configuration object can be accessed either as a hash or a struct:

config.project
 => "other-project" 
config[:project]
 => "other-project" 
config.github
 => {:url=>"http://www.github.com/somefork/other-project", :branch=>"pre-1.0"}
config.github.url
 => "http://www.github.com/somefork/other-project" 
config.github[:url]
 => "http://www.github.com/somefork/other-project" 
config[:github]
 => {:url=>"http://www.github.com/somefork/other-project", :branch=>"pre-1.0"}

Other Features

Deferred evaluation

Any configuration value of class Confstruct::Deferred will be evaluated on access, allowing you to define read-only, dynamic configuration attributes

config.app_name = "iWidgetCloud"
config.msgs.welcome = Confstruct::Deferred.new {|c| "Welcome to #{c.app_name}!"}    
config.msgs.welcome
 => "Welcome to iWidgetCloud!"
config.app_name = "Enterprisey-Webscale"
 => "Enterprisey-Webscale" 
config.welcome_msg
 => "Welcome to Enterprisey-Webscale"

As a convenience, Confstruct.deferred(&block) and Confstruct::HashWithStructAccess#deferred!(&block) will create a Confstruct::Deferred for you, making the following two assignments equivalent to the above:

config.welcome_msg = Confstruct.deferred { |c| "Welcome to #{c.app_name}!" }
config do
  welcome_msg deferred! { |c| RestClient::Resource.new(c.url) }
end

Push/Pop configurations

push! and pop! methods allow you to temporarily override some or all of your configuration values. This can be useful in spec tests where you need to change values but don't want to worry about messing up tests that depend on the same global configuration object.

config.github.url
 => "http://www.github.com/mbklein/confstruct"
config.push! { github.url 'http://www.github.com/somefork/other-project' }
 => {:project=>"confstruct", :github=>{:branch=>"master", :url=>"http://www.github.com/somefork/other-project"}} 
config.github.url
 => "http://www.github.com/somefork/other-project"
config.pop!
 => {:project=>"confstruct", :github=>{:branch=>"master", :url=>"http://www.github.com/mbklein/confstruct"}} 
config.github.url
 => "http://www.github.com/mbklein/confstruct"

lookup!

lookup! can be used to look up down a hieararchy without raising on missing values; and/or to look up with default value.

config = Confstruct::Configuration.new do 
  project 'confstruct'
  github do
    url 'http://www.github.com/mbklein/confstruct'
    branch 'master'
  end
end
config.lookup!("github.url")
=> "http://www.github.com/mbklein/confstruct"
config.lookup!("github.no_key")
=> nil # no raising
config.lookup!("not_there.really.not.there")
=> nil
config.lookup!("github.not_there", "default_value")
=> "default_value"

lists

The pattern add_$key! can be used to add to or create an array.

config = Confstruct::Configuration.new
config.add_color! "green"
=> ["green"]
config
=> {:color=>["green"]}
config.add_color! "red"
config.color
=> ["green", "red"]

Notes

Release History

Contributing to confstruct

License

confstruct is released under the MIT License.