Last month the Sittercity tech team released Flagon, a simple gem that you can use to quickly set up feature flags in your project without worrying about how you might need to store these flags in different environments.

Feature flags you say…

Okay, let’s make sure we’re all reading the same page.

Imagine you are developing a particularly risky piece of code. Your client has asked for the ability to turn the risky feature off at the snap of a finger if anything goes wrong in the wild, and you need a way to flick that switch.

This is a common scenario that many software engineers have encountered before and many more will encounter in the future, these switches we use to turn features on and off are often called feature flags.

Okay, but there are other feature flag gems. What’s so special about Flagon?

Before developing a new gem, it would be silly not to check if the problem had already been solved by some other nice person. However, upon looking for something to fill our gap, we discovered that there were not a lot of choices out there that deal with this problem in a flexible way. Most are tied to active record or another single type of storage, and while this may be convenient because you’re already in the database most of the time, it doesn’t comply with the ideals of the 12 Factor App by storing settings in environment variables, and lets face it, for development and testing something a lot simpler could be used to define flags that doesn’t involve database migrations, like a hash.

Having said that, I’m not going to waggle my finger at you and tell you you’re doing it wrong. If you want to use the database for feature flags in some cases, so be it! You can. Flagon allows any storage mechanism if you care to extend it.

Using Flagon, the simplest example

In it’s simplest form, Flagon can be set up to use environment variables in one line:

Flagon.init

Flagon expects environment variables to be set to “on”. If they are not “on” then they are considered off. So to set up your first flag you could set an environment variable like so:

export DAILY_EMAILS=on

Then, you would check the flag in your project by calling:

Flagon.enabled?(:daily_emails)

Alternative ways of defining flags

You might not want to use environment variables all the time, maybe you want something even simpler, like a hash? You can do this by initializing a hash loader and passing it into the init method of Flagon:

loader = Flagon.hash_loader { daily_emails: "on" }
Flagon.init loader

Other than that change (and not needing to set environment variables), you use Flagon in exactly the same way as before. To keep things consistent with the environment variables, we stuck with “on” to define an enabled flag.

In addition to the hash loader, Flagon also provides the file loader which will read from a yaml file:

loader = Flagon.file_loader "/path/to/my/file.yaml"
Flagon.init loader

The yaml file is simple too:

daily_emails: on
automatic_happy_face_emoji: off

Extending Flagon

If environment variables, hashes and yaml aren’t your thing you can create your own loaders too. You just need to implement the loader interface on a custom object and pass it in instead of one of the provided loaders. Here’s the loader interface:

# returns true or false, depending on whether the flag has been defined.
exists?(:flag_name)

# returns true or false, depending on whether the flag is "on".
get_flag(:flag_name)

Flagon will call those two methods to work out whether a flag is on or off and your application can be blissfully ignorant about how or where the flags are defined in development, test or production.

For example, if you created a new rails project and an active record model with two attributes “name” and “value”, you could implement the two interface methods like so:

# app/models/flag.rb
class Flag < ::ActiveRecord::Base
end

# lib/flag_loader.rb
class FlagLoader
  def exists?(flag_name)
    Flag.exists?(name: flag_name)
  end

  def get_flag(flag_name)
    flag = Flag.where(name: flag_name).first
    !!flag && flag.value == "on"
  end
end

Then you could simply pass it into Flagon to have all your flags load from your database rather than environment variables:

# config/initializers/flagon.rb
require 'flag_loader'
Flagon.init FlagLoader.new

Telling, rather than asking

If you’re the type of person that likes to tell your programs what to do rather than ask them, you can use this smashing alternative syntax:

Flagon.when_enabled(:game_changer) do
  # change the world for the better
end

It’s basically the same thing… but you might enjoy the small power rush it gives you.

Crossing your Ts and dotting your Is

If you haven’t set a flag, it will be considered to be off. There’s nothing wrong with a flag being off of course, but you may want to make sure that the flag is in fact, supposed to be off. Flagon provides a method that can be used to check if flags have been set as expected.

Flagon.init
Flagon.ensure_flags_exist(:game_changer, :automatic_happy_face_emoji)

If either flag hasn’t been set, ensure_flags_exist will raise a Flagon::Inspector::FlagMissing exception. We like to call it immediately after initializing Flagon so that we know about possible problems as early as possible.

Anything else?

Maybe! This post is unlikely to change over time, but we will certainly keep the readme of the project up to date with changes and improvements so visit the Flagon project page for the latest details on the gem.