#315 Rollout and Degrade pro
Jan 09, 2012 | 13 minutes | Plugins, Deployment
Learn how to use the Rollout gem to deploy a feature to a select group of users and the Degrade gem to automatically disable it upon failure. Also included is a way of doing this from scratch.
- Download:
- source codeProject Files in Zip (146 KB)
- mp4Full Size H.264 Video (28.9 MB)
- m4vSmaller H.264 Video (14.9 MB)
- webmFull Size VP8 Video (17.1 MB)
- ogvFull Size Theora Video (31.8 MB)
Resources
Rollout Gem
Gemfile
gem 'redis' gem 'rollout' gem 'degrade'
config/initializers/rollout_setup.rb
$redis = Redis.new $rollout = Rollout.new($redis) $rollout.define_group(:admin) do |user| user.admin? end $degrade_phone = Degrade.new($redis, name: :phone, minimum: 1, failure_strategy: lambda { $rollout.deactivate_all(:phone) } )
index.html.erb
<% if rollout? :phone %> <p><%= link_to "Send to Phone", new_phone_request_path %></p> <% end %>
application_controller.rb
def rollout?(name) $rollout.active? name, current_user end helper_method :rollout?
phone_requests_controller.rb
before_filter :rollout around_filter :degrade private def rollout unless rollout? :phone redirect_to root_url, alert: "Access denied" end end def degrade $degrade_phone.perform { yield } end
rails console
$rollout.activate_group(:phone, :admin) $rollout.activate_group(:phone, :all) $rollout.activate_user(:phone, User.find_by_name("ryan")) $rollout.activate_percentage(:phone, 20) $rollout.deactivate_all(:phone)
From Scratch
models/rollout.rb
# Generated with: # rails g model rollout name:string group:string user_id:integer percentage:integer failure_count:integer class Rollout < ActiveRecord::Base def match?(user) enabled? && match_group?(user) && match_user?(user) && match_percentage?(user) end def enabled? failure_count.to_i < 1 end def match_group?(user) case group when "admin" then user.admin? else true end end def match_user?(user) user_id ? user_id == user.id : true end def match_percentage?(user) percentage ? user.id % 100 < percentage : true end end
application_controller.rb
def rollout?(name) Rollout.where(name: name).any? do |rollout| rollout.match?(current_user) end end helper_method :rollout? def degrade_feature(name) yield rescue StandardError => e Rollout.where(name: name).each do |rollout| rollout.increment!(:failure_count) end raise e end
phone_requests_controller.rb
before_filter :rollout around_filter :degrade private def rollout redirect_to root_url, alert: "Feature unavailable" unless rollout? :phone end def degrade degrade_feature(:phone) { yield } end
rails console
Rollout.create! name: "phone", group: "admin"