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.
As mentioned above, Rollout uses Redis to store the state of feature flag. So let’s set that up.
dotenv gems to you
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
Create an env file and add the key for the Redis URL. Here’s what I did for local development.
Create the file.
Add this to the
.env.development file we just made.
Next, I added an initialization file for Redis
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.
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
gem 'rollout', '~> 2.4', '>= 2.4.5'
and install with
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
You should get something back like this.
Rollout is now ready to use!
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
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
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.