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.
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
extend YourConfigurationMethods inside the block passed to
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 is passed the current
SettingPath, for example for a call to
Config.foo.bar.baz? it gets a path with the items
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
yep. The workaround is to append
? to get the
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
A convenience base class changing the interface for implementers. It provides a basic
which just passes all parameters through to
The result of
#lookup_path is returned, unless it's
Configurate::SettingNotFoundError is raised. Subclasses are expected to implement
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
would look for a environment variable named
FOO_BAR_BAZ. Additionally it splits comma separated values
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
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