BetterSettings
A robust settings library that can read YML files and provide an immutable object allowing to access settings through method calls. Can be used in any Ruby app, not just Rails.
Installation
Add this line to your application's Gemfile:
gem 'better_settings'
And then execute:
$ bundle
Or install it yourself as:
$ gem install better_settings
Usage
1. Define a class
Instead of defining a Settings constant for you, that task is left to you. Simply create a class in your application that looks like:
# app/models/settings.rb
class Settings < BetterSettings
source Rails.root.join('config', 'application.yml'), namespace: Rails.env
end
2. Create your settings
Notice above we specified an absolute path to our settings file called application.yml
. This is just a typical YAML file.
Also notice above that we specified a namespace for our environment. A namespace is just an optional string that corresponds to a key in the YAML file.
Using a namespace allows us to change our configuration depending on our environment:
# config/application.yml
defaults: &defaults
port: 80
mailer:
root: www.example.com
dynamic: <%= "Did you know you can use ERB inside the YML file? Env is #{ Rails.env }." %>
development:
<<: *defaults
port: 3000
test:
<<: *defaults
production:
<<: *defaults
3. Access your settings
Rails.env => "development"
Settings.mailer => "#
" Settings.mailer.root => "www.example.com
Settings.port => 3000
Settings.dynamic => "Did you know you can use ERB inside the YML file? Env is development."
You can use these settings anywhere, for example in a model:
class Post < ActiveRecord::Base self.per_page = Settings.pagination.posts_per_page end
Advanced Setup ⚙
Name it Settings
, name it Config
, name it whatever you want. Add as many or as few as you like, read from as many files as necessary (nested keys will be merged).
We usually read a few optional files for the development
and test
environment, which allows each developer to override some settings in their own local environment (we git ignore development.yml
and test.yml
).
# app/models/settings.rb
class Settings < BetterSettings
source Rails.root.join('config', 'application.yml'), namespace: Rails.env
source Rails.root.join('config', 'development.yml'), namespace: Rails.env, optional: true if Rails.env.development?
source Rails.root.join('config', 'test.yml'), namespace: Rails.env, optional: true if Rails.env.test?
end
Our application.yml
looks like this:
# application.yml
defaults: &defaults
auto_logout: false
secret_key_base: 'fake_secret_key_base'
server_defaults: &server_defaults
<<: *defaults
auto_logout: true
secret_key: <%= ENV['SECRET_KEY'] %>
development:
<<: *defaults
host: 'localhost'
test:
<<: *defaults
host: '127.0.0.1'
staging:
<<: *server_defaults
host: 'staging.example.com'
production:
<<: *server_defaults
host: 'example.com'
A developer might want to override some settings by defining a development.yml
such as:
development:
auto_logout: true
The main advantage is that those changes won't be tracked by source control :smiley:
Opinionated Design
After using settingslogic for a long time, we learned some lessons, which are distilled in the following decisions:
- Immutability: Once created settings can't be modified.
- No Optional Setings: Any optional setting can be modeled in a safer way, this library doesn't allow them.
- Not Tied to a Source File: Useful to create multiple environment-specific files.