Project

switches

0.0
No commit activity in last 3 years
No release in over 3 years
Switches lets you turn on and off parts of your code from the commandline. There's a defaults.yml and a current.yml in the background. For example: app/models/user.rb after_create :subscribe_email if Switches.campaign_monitor? >> Switches.campaign_monitor? # => false $ rake switches:on[campaign_monitor] >> Switches.campaign_monitor? # => true $ rake switches:reset # goes back to default.yml $ rake switches:diff # shows diff b/w current.yml and default.yml $ rake s:d # alias for switches:diff $ rake s:c # alias for switches:list_current etc. It's inspired by ActiveSupport's StringInquirer (e.g. Rails.development?) and traditional compile-time assertions.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 1.2.9

Runtime

 Project Readme

switches¶ ↑

Switches lets you turn on and off sections of your code with Switches.foobar? booleans.

It’s an extraction from brighterplanet.com, where we use it as an emergency button to turn on/off API integration with Facebook, Campaign Monitor, etc.

Quick start¶ ↑

Add 2 lines to config/environment.rb:

require File.join(File.dirname(__FILE__), 'boot')
[...]
require 'switches'                                  # AFTER boot, BEFORE initializer
[...]
Rails::Initializer.run do |config|
[...]
  config.gem 'switches', :lib => false              # INSIDE initializer

Now run this:

my-macbook:~/my_app $ ./script/runner 'Switches.setup'

Add your defaults to config/switches/defaults.yml:

--- 
ssl: true                   # ssl support is on by default
campaign_monitor: true      # campaign monitor integration is on by default

Tasks¶ ↑

RAKE TASK                 CAP TASK                         NOTES
rake s:c                  cap TARGET s:c                   show current switches
rake s:d                  cap TARGET s:d                   show difference between current and default switches
rake s:on[SWITCH]         cap TARGET s:on ARG=SWITCH       turn on SWITCH
rake s:off[SWITCH]        cap TARGET s:off ARG=SWITCH      turn off SWITCH
rake s:clear[SWITCH]      cap TARGET s:clear ARG=SWITCH    clear any switch for SWITCH
rake s:reset              cap TARGET s:reset               go back to defaults (deletes config/switches/current.yml)
rake s:backup             cap TARGET s:backup              backup current switches (copies to config/switches/backup.yml)
rake s:restore            cap TARGET s:restore             restore backed-up switches (copies backup.yml to current.yml)
rake s:default            cap TARGET s:default             list default settings

Throwing switches remotely with Capistrano¶ ↑

This is the minimum needed in the TARGET task:

task :production do
  role :app, 'ec2-88-77-66-55.compute-1.amazonaws.com'
  role :app, '177.133.33.144'

  set :rails_env, 'production'
  set :deploy_to, '/data/my_app'
  set :gfs, false
end

The switches will get applied to any role that matches /app/ (so :app_master, :app, etc.)

Throwing switches before you db:migrate¶ ↑

I like to use Switches to turn off %w{memoization caching facebook campaign_monitor delayed_job} before running rake db:migrate, so I put this in lib/tasks/zzz_rake_switches.rake:

namespace :rake_switches do
  task :turn_stuff_off do
    Rake::Task['s:backup'].execute
    %w{memoization caching facebook campaign_monitor delayed_job}.each do |switch|
      Rake::Task['s:off'].execute(Rake::TaskArguments.new([:name], [switch]))
    end
  end
  task :turn_stuff_back_on do
    Rake::Task['s:restore'].execute
    Rake::Task['cache:clear'].execute
  end
end

# modify what happens on db:migrate, etc.
[ 'db:migrate', 'your:task:if:it:needs:wrapping' ].each do |task_to_wrap|
  Rake::Task[task_to_wrap].enhance(['rake_switches:turn_stuff_off']) do
    Rake::Task['rake_switches:turn_stuff_back_on'].invoke
  end
end

Note that ‘s:backup’ and ‘s:restore’ are not thread safe or really GFS safe, either.

Usage¶ ↑

You can do stuff like (in app/models/user.rb):

after_create :subscribe_email if Switches.campaign_monitor?
def subscribe_email
  CampaignMonitor.subscribe email
end

Uhh ohh! Campaign Monitor’s API is down and you need to shut off those failing after_creates, like, NOW.

production-server-1:/var/www/apps/my_app $ rake s:off[campaign_monitor]
production-server-1:/var/www/apps/my_app $ sudo monit restart all -g my_app
[...]
production-server-2:/var/www/apps/my_app $ rake s:off[campaign_monitor]
production-server-2:/var/www/apps/my_app $ sudo monit restart all -g my_app

Or, even better, do it with cap:

my-macbook:~/my_app $ cap production s:off ARG=campaign_monitor
my-macbook:~/my_app $ cap production mongrel:restart

For another example, let’s say you’re a developer who doesn’t have a self-signed certificate:

my-macbook:~/my_app $ rake s:off[ssl]

Those changes get persisted in config/switches/current.yml.

If you want to see your switches vis-a-vis the defaults:

my-macbook:~/my_app $ rake s:d
--- 
ssl: true => false

And if you want to go back to the defaults:

my-macbook:~/my_app $ rake s:reset

Remember, you should version control config/switches/defaults.yml and ignore config/switches/current.yml.

Rationale¶ ↑

Sometimes you just need an easy way to “turn off” code.

Wishlist¶ ↑

+ ?

Copyright © 2009 Seamus Abshere. See LICENSE for details.