Learnable uses feature flippers (so does Flickr) as a tool to help achieve continuous deployment.
Flip gives us a declarative, layered mechanism to enable and disable features. There's a configurable system-wide default (default: !Rails.env.production?
works nicely), plus three layers of strategies to determine status per-feature:
- The declared default, e.g.
feature :world_domination, default: true
, - A database-backed strategy, for flipping features site-wide for all users.
- A cookie-backed strategy, for privately previewing features in your own browser only.
(Hint: that last one is a a killer feature..)
Note: the alpha version number indicates Flip is currently being extracted from its host application. The process described here is currently fictional. But it does have a happy ending.
Rails 3.0 and 3.1+
# Gemfile
gem "flip"
# Generate the model and migration
> rails g flip:install
# Run the migration
> rake db:migrate
# They lived happily ever after.
# This is the model class generated by rails g flip:install
class Feature < ActiveRecord::Base
include Flip::Declarable
# The recommended Flip strategy stack.
strategy Flip::CookieStrategy
strategy Flip::DatabaseStrategy
strategy Flip::DefaultStrategy
default false
# A basic feature declaration.
feature :shiny_things
# Override the system-wide default.
feature :world_domination, default: true
# Enabled half the time..? Sure, we can do that.
feature :flakey,
default: proc { rand(2).zero? }
# Provide a description, normally derived from the feature name.
feature :something,
default: true,
description: "Ability to purchase enrollments in courses",
end
Feature status can be checked by any code using on?
or using the dynamic predicate methods:
Flip.on? :world_domination # true
Flip.world_domination? # true
Flip.on? :shiny_things # false
Flip.shiny_things? # false
Within view and controller methods, the FlipHelper
module provides a feature?(key)
method:
<div>
<% if feature? :world_domination %>
<%= link_to "Dominate World", world_dominations_path %>
<% end %>
</div>
The Flip::ControllerFilters
module is mixed into the base ApplicationController
class. The following controller will respond with 404 Page Not Found to all but the index
action unless the :new_stuff feature is enabled:
class SampleController < ApplicationController
require_feature :something, :except => :index
def show
end
def index
end
end
Note that conditionally declared routes require a server restart to notice changes to feature flags, so they're not a good idea; database/cookie feature flipping will be ignored.
A dashboard allows you to view the current state of the feature set, and flip any switchable strategies (database, cookie). Screenshot coming…
Created by Paul Annesley
Copyright © 2011 Learnable Pty Ltd, MIT Licence.