A flexible configuration system
Configurate allows you to specify a chain of configuration providers which are queried in order until one returns a value. This allows scenarios like overriding your default settings with a user configuration file and let those be overridden by environment variables. The query interface allows to group and nest your configuration options to a practically unlimited level.
Configurate works with Ruby 1.9.2 or later.
Just add
gem 'configurate'
to your Gemfile
.
A basic loader could look like this:
require 'configurate'
Config = Configurate::Settings.create do
add_provider Configurate::Provider::Env
add_provider Configurate::Provider::YAML, '/etc/app_settings.yml',
namespace: Rails.env, required: false
add_provider Configurate::Provider::YAML, 'config/default_settings.yml'
end
# Somewhere later
if Config.remote_assets.enable?
set_asset_host Config.remote_assets.host
end
You can add custom methods working with your settings to your Configurate::Settings
instance
by calling extend YourConfigurationMethods
inside the block passed to #create
.
Providers are called in the order they're added. You can already use the added providers to determine if further ones should be added:
require 'configurate'
Config = Configurate::Settings.create do
add_provider Configurate::Provider::Env
add_provider Configurate::Provider::YAML, 'config/settings.yml' unless heroku?
end
add_provider
can be called later on the created object to add more providers to the chain.
It takes a constant and parameters that should be passed to the initializer.
A providers only requirement is that it responds to the #lookup
method. #lookup
is passed the current
SettingPath
, for example for a call to Config.foo.bar.baz?
it gets a path with the items 'foo'
, 'bar'
, 'baz'
passed. SettingPath
behaves like Array
with some methods added.
The provider should raise Configurate::SettingNotFoundError
if it can't provide a value for the requested option.
Any additional parameters are passed along to the provider, thus a #lookup
method must be able to take
any number of additional parameters.
You're not limited to one instance of the configuration object.
Ruby does not allow to metaprogram false
, thus something like
puts "yep" if Config.enable_stuff
always outputs yep
. The workaround is to append .get
, or ?
to get the
real value:
puts "yep" if Config.enable_stuff?
Another thing you can't overwrite in Ruby is the ===
operator, rendering case statements useless
puts case Config.some.setting
when NilClass
"nil"
when String
"string"
else
"unknown"
end
will always output unknown
. Again use .get
A convenience base class changing the interface for implementers. It provides a basic #lookup
method
which just passes all parameters through to #lookup_path
.
The result of #lookup_path
is returned, unless it's nil
then Configurate::SettingNotFoundError
is raised. Subclasses are expected to implement #lookup_path
.
Do not use this class directly as a provider!
This class transforms a query string into a name for a environment variable and looks up this variable then.
The conversion scheme is the following: Convert to uppercase, join path with underscores. So for example Config.foo.bar.baz
would look for a environment variable named FOO_BAR_BAZ
. Additionally it splits comma separated values
into arrays.
This provider does not take any additional initialization parameters.
This provider reads settings from a given YAML file. It converts the sections of query string to a nested value. For a given YAML file
stuff:
enable: true
param: "foo"
nested:
param: "bar"
the following queries would be valid:
Config.stuff.enable? # => true
Config.stuff.param # => "foo"
Config.stuff.nested.param # => "bar"
The initializer takes a path to the configuration file as mandatory first argument and the following optional parameters, as a hash:
A provider which stores the first additional parameter if the query string ends with an equal sign and can return it later. This is mainly useful for testing but can be useful to temporarily override stuff too. To clarify a small example:
Config.foo.bar # => nil
Config.foo.bar = "baz"
Config.foo.bar # => "baz"
Config.reset_dynamic!
Config.foo.bar # => nil
...should be pretty easy. For example here is the Configurate::Provider::Env
provider:
class Configurate::Provider::Env < Configurate::Provider::Base
def lookup_path(setting_path, *args)
value = ENV[setting_path.join("_").upcase]
unless value.nil?
value = value.dup
value = value.split(",") if value.include?(",")
end
value
end
end
You can find the current documentation for the master branch here.
MIT, see LICENSE