Skip to content
⚙ Settings for Ruby apps – simple, immutable, better.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Better Settings

Build Status Coverage Status Inline docs Gem Version License

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.


Add this line to your application's Gemfile:

gem 'better_settings'

And then execute:

$ bundle

Or install it yourself as:

$ gem install better_settings


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

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
  dynamic: <%= "Did you know you can use ERB inside the YML file? Env is #{ Rails.env }." %>

  <<: *defaults
  port: 3000

  <<: *defaults

  <<: *defaults

3. Access your settings

>> Rails.env
=> "development"

>> Settings.mailer
=> "#<Settings ... >"

>> Settings.mailer.root
=> "

>> 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

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 environments, 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 }/config/application.yml", namespace: Rails.env
  source "#{ Rails.root }/config/development.yml", namespace: Rails.env, optional: true if Rails.env.development?
  source "#{ Rails.root }/config/test.yml", namespace: Rails.env, optional: true if Rails.env.test?

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'] %>

  <<: *defaults
  host: 'localhost'

  <<: *defaults
  host: ''

  <<: *server_defaults
  host: ''

  <<: *server_defaults
  host: ''

A developer might want to override some settings by defining a development.yml such as:

  auto_logout: true

The main advantage is that those changes won't be tracked in source control 😃

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.
  • Fail-Fast: Settings are eagerly loaded when source is called.
  • 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.

You can read more about it in this blog post.

You can’t perform that action at this time.