A coconfiguration tool for your Ruby projects.
Installation
Add this line to your application's Gemfile:
gem 'coconut'
And then execute:
$ bundle
Or install it yourself as:
$ gem install coconut
Overview
Coconut provides a simple DSL that allows you to configure your application's assets on different environments.
require 'coconut'
Coconut.configure MyApp do
twitter do
environments :development, :test do
consumer_key 'development_key'
consumer_secret 'development_secret'
end
environment :production do
consumer_key 'production_key'
consumer_secret 'production_secret'
end
end
end
You only need to require the config file from your app. Coconut will define a
config
method on your application's namespace that you can use to query it.
ENV['RACK_ENV'] = :development
MyApp.config.twitter.consumer_key # => development_key
ENV['RACK_ENV'] = :production
MyApp.config.twitter.consumer_key # => production_key
You don't have to specify the environment when querying for configuration values. Coconut will only run the configuration for the environment it's running on.
How is the environment detected?
Coconut uses the RACK_ENV
environment variable by default to detect the
environment the app is running on. If this variable is not set or is empty it
will default to :development
.
If your ecosystem uses something that is not RACK based you can specify how
Coconut should find out the environment with the take_environment_from
method
on the Application level
(See the Specifying how the environment should be found section on
Application under Coconut Anatomy).
Coconut Anatomy
Coconut is composed of 3 different parts:
1) Application
Application is the top level block of Coconut. It's composed of the configuration of the Assets your application has. It may also contain information about where Coconut should look for Asset configuration files and how it should find out which environment the application is running on.
You will enter this block when you call the Coconut.configure
method passing
in your application's namespace.
require 'coconut'
Coconut.configure MyApp do
# your application configuration
end
Coconut will then detect the environment,
run the configuration and create a Coconut::Config
object with the assets
and it's properties for the current environment. A config
method will be
defined in the namespace passed to configure
. That method will return the
Coconut::Config
object with your application's configuration.
That means:
- You only need to make sure that you require the config file that includes the Application block for your configuration to be run.
- Your configuration will be run just once (unless you use
Kernel::load
) - If there is a
config
method on your namespace it will be overriden. - You will be able to access the configuration from anywhere by calling
Namespace::config
.
Specifying how the environment should be found
If your application should not use the RACK_ENV environment variable to determine which configuration to use you can tell Coconut how to find out:
Coconut.configure MyApp do
take_environment_from { MyApp::find_out_environment }
# ...
end
Coconut will call the block passed to the environment
method to find out
what environment the application is running on. Therefore the environment
will be the return value of that block.
Coconut flavours (how to structure your configuration).
You can structure the configuration in several ways with coconut. See coconut flavours in the wiki.
2) Asset
Each of this blocks represent one of the assets of your application. Inside each one of them you will include the Asset properties on each of the environments your application will run on.
An Asset block consist of the asset name and a Ruby block containing it's configuration in each of the environments:
asset_name do
environment(:production) { property 'value on production' }
environment(:development, :test) { property 'value on test and development' }
end
You can specify one or more environments at the same time. You can also use any
of the aliases the environment
method has:
env(:development, :test) { property 'value' }
envs(:development, :test) { property 'value' }
environment(:development, :test) { property 'value' }
environments(:development, :test) { property 'value' }
An Asset can have almost any name. There are some restrictions that apply to the names. This restrictions apply to both asset names and property names and are explained in the Environment section of this README.
3) Environment
Environments are the lowest level of a Coconut configuration. Its composed of the configuration properties an asset will have on that environment. So, essentially, it's a series of key-value pairs.
Properties can have almost any name you can think of. It only has to be a valid
Ruby method name and you have to avoid those that will collide with calls on
the Config
object. Coconut will raise an error if you use one of the reserved
names:
environment(:development) { object_id 11 }
# => Coconut::Dsl::InvalidName: object_id can't be used as property name: it will collide with Coconut::Config methods
You can find out the forbidden property (and asset) names by calling the method:
Coconut::Dsl::BlankSlate.__forbidden_names
# => [:respond_to?, :to_hash, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup,
# :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze,
# :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods,
# :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set,
# :instance_variable_defined?, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send,
# :respond_to_missing?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id,
# :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__,
# :instance_eval, :__send__, :object_id, :__taken?, :__taken_error_message]
If you want to use the methods from Kernel
that are widely available
on Ruby objects you will need to prepend the module to the method call:
environment(:development) do
puts 'here' # declaring a property named "puts"
Kernel::puts 'here' # printing "here" to STDOUT
end
Values can be any Ruby object, from a simple integer or string to a lambda. You can even use constant or expressions. Keep in mind that the block passed to environment will be evaluated in a different context: you won't be able to call methods without specifying their receiver.
environment :development do
four 2 + 2
arguments ARGV
encodings Encoding.list
setup -> do
enable :sessions, :logging
disable :dump_errors, :some_custom_option
end
end
Why coconut?
TODO
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request