StepByStep
This gem is largely inspired by the Railscast on rollouts and degrading, as well as the Rollout gem that is covered in aforementioned Railscast. While very comprehensive, it uses a Redis backend, that might not be desirable to everyone. Though there are some alternatives out there, most of them are either outdated or not as comprehensive as the rollout gem itself.
StepByStep uses ActiveRecord as backend instead and tries to cover as many use cases and features as the original rollout gem. It is easy to use since no additional backend needs to be set up, and adds some helpful methods that shall assist you in rolling out and degrading features reliably.
Installation
Add this line to your application's Gemfile:
gem 'step_by_step'
And then execute:
$ bundle
Or install it yourself as:
$ gem install step_by_step
Since StepByStep uses ActiveRecord, you need to create the following migration:
$ rails g migration create_rollouts name group user_id:integer percentage:integer failure_count:integer
Then migrate your database.
Usage
Let's say you have this new commenting feature that you would like to deploy to production, but you only want a subset of your users to be able to see it. Also, you may want to degrade a feature later, or disable it again altogether.
Rolling Out Features
Rolling Out To A Group Of Users
You can define groups with any custom logic like this:
StepByStep::Rollout.define_group :admins do |user|
user.admin?
end
Consider putting this in an initializer, such as config/initializers/step_by_step.rb
.
Roll out your feature to your group:
StepByStep::Rollout.activate_group(:comments, :admins)
Rolling Out To A Fraction Of Users
StepByStep::Rollout.activate_percentage(:comments, 20)
end
Now 20% of your users can see the comments feature. As in the original gem, this is based on the following algorithm:
CRC32(user.id) % 100 < percentage # pseudocode
So, for 20%, a feature will be rolled out to users with ids 0, 1, 10, 11, 20, 21, etc. These users also remain as the percentage increases.
Rolling Out To A Specific User
StepByStep::Rollout.activate_user(:comments, User.first)
Now your first user can see the comments feature.
Rolling Out To Everyone
StepByStep::Rollout.activate(:comments)
Now everyone can see the comments feature. This also includes users who are not authenticated. If you want to roll out a feature to all authenticated users, but not to the public, roll it out to a percentage of 100 instead.
Activating a feature for everyone is common after you have determined that your rollout phase was successful.
Deactivating Features
You can easily deactivate new features depending on your needs.
Deactivating A Feature For Everyone
StepByStep::Rollout.deactivate(:comments)
Nobody can see your new comments feature anymore.
Deactivating A Group Feature
Your admins shouldn't be able to see the comments anymore? Easy:
StepByStep::Rollout.deactivate_group(:comments, :admins)
Deactivating A Single User Feature
And there this one user who could see the comments. Let's hide them from him again:
StepByStep::Rollout.deactivate_user(:comments, User.first)
Deactivating A Feature For A Fraction Of Users
Remember those 20% who could see your new feature? Let's get rid of them, too:
StepByStep::Rollout.deactivate_percentage(:comments)
Displaying Features
StepByStep comes with a few helper methods, one of which is called rollout?
. It's available in your controllers as well as in your views. You just pass it the feature name to check if it has been rolled out to your current_user
.
View Example
It's as simple as:
<% if rollout?(:comments) %>
<%= # your awesome feature here %>
<% end %>
Controller Example
Sometimes, you may want to hide a view completely. You can either do this directly in a controller action:
def show
unless rollout?(:comments)
redirect_to root_path, notice: 'Access denied'
end
end
or preferably using before actions:
before_action :rollout
private
def rollout
unless rollout?(:comments)
redirect_to root_path, notice: 'Access denied'
end
end
Degrading A Feature
Every rollout comes with a failure_count
. A helper method is added to your application controller that allows you to track exceptions and increments the failure count for your feature. A failure count of 1 or higher disables your feature.
For instance, you could degrade a feature doing the following in your feature controller:
around_action :degrade
private
def degrade
degrade_feature(:comments) { yield }
end
Foolish Assumptions
- You have a
current_user
method in your application controller that returns the authenticated user or nil if not authenticated (standard behavior, used e.g. by Devise) - You are using Rails
- Your user model's primary key is
id
(Rails default)
Dependencies
StepByStep requires Rails 3.2 or higher.
Contributing
- Fork it ( https://github.com/[my-github-username]/step_by_step/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request