Introducing Configr, an elegant configuration interface in Ruby
2010/03/01 // Leeds // // Feed
I’ve never really been happy with my previous solution to making configuration easy and elegant. It still felt too clunky and lacked the syntactical sugar that I’ve become accustomed to within Ruby. So configr was born.
Configr aims to provide a clean interface for configuring and reading a set of configuration values. The idea evolved from using a standard hash as a configuration store into a more elegant way to declare and read values from within a hash.
I wanted a way to be able to declare my configurations in a simple format, whether that be inline (in the format of a block), from a YAML file or as a mixture of the two. I also wanted to be able to have a simple way of overriding values for certain environments (for frameworks such as Sinatra and Rails). The project is far from done but it’s the start of a more elegant solution to these problems over my previous method (simple hash based configuration).
Using Configr is simple:
configuration = Configr::Configuration.configure do |config|
config.example_one = "One"
config.example_two = "Two"
end
puts configuration.example_one
puts configuration.example_two
Declaring values inline is great, but its also useful to pull them in from a YAML file:
configuration = Configr::Configuration.configure("/path/to/file.yml")
puts configuration.value_one
puts configuration.value_two
Or as a YAML string:
yaml = <<YAML example_one: "Hello" example_two: "It loads from YAML too!" YAML configuration = Configr::Configuration.configure(yaml) puts configuration.example_one puts configuration.example_two
Or a mixture of both methods:
yaml = <<YAML
example_three: "three"
example_four: "four"
YAML
configuration = Configr::Configuration.configure(yaml) do |config|
config.example_one = "one"
config.example_two = "two"
end
puts configuration.example_one
puts configuration.example_two
puts configuration.example_three
puts configuration.example_four
The idea is for Configr to be quite flexible in how you declare your configurations. The end result being able to read them in a more natural format:
puts configuration.one.two.three
Sometimes when using configuration values you might want to assert whether the value exists before using it. Configr allows you to do this with the #key_name? syntax:
puts configuration.one.two.three? # => true
Configr is intended to be framework agnostic, but it’s easy to get it going inside of any of the latest frameworks. I don’t plan to provide any “out of the box” way to hook Configr into Rails but it’s easy to implement:
# In config/configuration.rb
yaml_file = Rails.root.join("config", "environments", "#{Rails.env}.yml")
Configuration = Configr::Configuration.configure(yaml_file) do |config|
config.my.configuration.value = "value"
end
# In config/initializers/configuration.rb
require Rails.root.join("config", "configuration.rb")
# Anywhere in your Rails app
Configuration.my.configuration.value
By requiring a different YAML file based on the environment it is easy to override global values with environment specific ones. For more examples of using Configr with other frameworks see the readme.
By design a configuration value is not meant to be edited or created after the configuration block has been run (if you do you will run into a Configr::ConfigurationLocked error). In my opinion configurations such as those created by Configr are meant to be read-only during the lifetime of the application.
The gem is now available on rubygems.org:
gem install configr
It’s still early days for the project but I’m already enjoying using it in a few personal and client projects, for me it certainly beats the previous method. If you use it and find any bugs please file an issue to help me wean out any problems.