Back

Feature Flipping with Rails and Rollout

Gabriel Martin
Gabriel Martin
March 24, 2020
Feature Flipping with Rails and Rollout

Photo by Cameron Venti on Unsplash

Sometimes you want the ability to flip a feature on or off, or only give certain users access to new features in your application. Maybe you want to get user feedback before the final release? Maybe you want the ability to revert to the previous functionality with a single command.

With the Rollout Gem, this type of functionality is extremely easy and straight forward to set up in a Rails application.

Rollout allows you to enable or disable features without having to revert changes in the repository or promote different branches to production.

It does this by saving a “feature flag” in Redis which is either on or off. You can enable this feature flag globally, on a per-user basis or toggle the feature on and off for specific groups of users.

In order for Rollout to work, we need to have a Redis client set up in our application. I’ll walk through how I set up Redis for the demo app I created for this write-up. But first, let me show you what the app is.

The demo app is a very simple to-do app. A user can create and delete todos, and mark them as complete.

Setting up Redis

As mentioned above, Rollout uses Redis to store the state of feature flag. So let’s set that up.

Add the redis-rails and dotenv gems to you Gemfile.

gem 'redis', '~> 4.1', '>= 4.1.3' gem 'dotenv-rails', '~> 2.7', '>= 2.7.5', groups: [:development]

Make sure to install these new gems with bundle install.

Create an env file and add the key for the Redis URL. Here’s what I did for local development.

Create the file.

touch .env.development

Add this to the .env.development file we just made.

REDIS_URL=redis://localhost:6379

Next, I added an initialization file for Redis

touch config/initializers/redis.rb

and add this to that file.

require "redis" Redis.current = Redis.new(url: ENV['REDIS_URL'])

You can check that this is working by opening up the Rails console and typing Redis.current. You should see something like this in the console.

=> #<Redis client v4.1.3 for redis://localhost:6379/0>

Right on. Now that Redis is set up, let’s see how you can implement and use Rollout.

Adding Rollout

I’m going to add a feature that allows a user to mark a todo as important. The only thing here is that I’m going to “wrap” this feature markup in Rollout so I can turn it on or off extremely. Let’s set up Rollout first.

Add the rollout gem to your Gemfile

gem 'rollout', '~> 2.4', '>= 2.4.5'

and install with bundle install.

Now we need to update config/initializers/redis.rb to get rollout working.

require "redis" Redis.current = Redis.new(url: ENV['REDIS_URL']) # add this line $rollout = Rollout.new(Redis.current)

Make sure you restart your rails server. You can check if this worked by starting up the rails console and running $rollout.

You should get something back like this.

pre>

Rollout is now ready to use!

Wrapping Features

I’ve added the column important to the todos table and updated the view and controller. Here is what the view file looks like.

<% @todos.each do |todo| %> <div class="todo <%= 'important' if $rollout.active?(:important_todos) && todo.important? %> <%= 'complete' if todo.complete? %>"> <div class="todo-text"><%= todo.text %></div> <div class="todo-actions"> <% if $rollout.active? :important_todos %> <span><%= link_to todo.important? ? '!Important' : 'Important', todo_toggle_important_path(todo), method: :put, remote: true, class: 'important' %></span> <% end %> <span><%= link_to todo.complete? ? 'Incomplete' : 'Complete', todo_toggle_complete_url(todo), method: :put, remote: true %></span> <span><%= link_to 'Remove', todo, method: :delete, class: 'remove' %></span> </div> </div> <% end %>

You can see that I’ve wrapped the toggle important link in an if statement.

if $rollout.active? :important_todos

The active? method checks Redis to see if the `important_todos` feature is…active. If it’s not, this will return false and nothing will be rendered.

Without this feature enabled, the app looks and performs the same as before the new code was added.

If we want to activate this feature, all we have to do is open up the rails console and run

$rollout.activate :important_todos

This will save the important_todos feature in Redis and set it to active. The next time a user visits the todos page, they will see the link to toggle important todos.

The great thing about this is that everything happens in a live environment. We don’t need to push a different branch if, for whatever reason, this new feature needs to be disabled, or restart any dynos to see the changes take effect.

All we have to do is start up the rails console and run $rollout.deactivate :important_todos and boom! No more important todos feature.

Here is a short clip of all this in action.

There’s more to Rollout than just flipping a single feature on or off. Like I said before, you can enable features for specific users or place a bunch of users into groups (user testing) and enable features for the whole group. Be sure to check out the Rollout Docs to see how this additional functionality works.

Share this post

Interested in working with us?

Give us some details about your project, and our team will be in touch within a day or two.