switches 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ *.gem
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Seamus Abshere
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,81 @@
1
+ = switches
2
+
3
+ Switches lets you turn on and off sections of your code with <tt>Switches.foobar?</tt> booleans.
4
+
5
+ == Quick start
6
+
7
+ Add 2 lines to <tt>config/environment.rb</tt>:
8
+
9
+ require File.join(File.dirname(__FILE__), 'boot')
10
+ [...]
11
+ require 'switches' # AFTER boot, BEFORE initializer
12
+ [...]
13
+ Rails::Initializer.run do |config|
14
+ [...]
15
+ config.gem 'switches', :lib => false # INSIDE initializer
16
+
17
+ Now run this:
18
+
19
+ my-macbook:~/my_app $ ./script/runner 'Switches.setup'
20
+
21
+ Add your defaults to <tt>config/switches/defaults.yml</tt>:
22
+
23
+ ---
24
+ ssl: true # ssl support is on by default
25
+ campaign_monitor: true # campaign monitor integration is on by default
26
+
27
+ == Rake tasks
28
+
29
+ rake s:c # show current switches
30
+ rake s:d # show difference between current and default switches
31
+ rake s:on[foobar] # turn on "foobar"
32
+ rake s:off[foobar] # turn off "foobar"
33
+
34
+ rake switches:clear[foobar] # clear any switch for "foobar"
35
+ rake switches:reset # go back to defaults
36
+ rake switches:backup # backup current switches
37
+ rake switches:restore # restore backed-up switches
38
+
39
+ == Usage
40
+
41
+ You can do stuff like (in <tt>app/models/user.rb</tt>):
42
+
43
+ after_create :subscribe_email if Switches.campaign_monitor?
44
+ def subscribe_email
45
+ CampaignMonitor.subscribe email
46
+ end
47
+
48
+ Uhh ohh! Campaign Monitor's API is down and you need to shut off those failing after_creates, like, NOW.
49
+
50
+ production-server:/var/www/apps/my_app $ rake s:off[campaign_monitor]
51
+ production-server:/var/www/apps/my_app $ sudo monit restart all -g my_app
52
+
53
+ Or let's say you're a developer who doesn't have a self-signed certificate:
54
+
55
+ my-macbook:~/my_app $ rake s:off[ssl]
56
+
57
+ Those changes get persisted in <tt>config/switches/current.yml</tt>.
58
+
59
+ If you want to see your switches vis-a-vis the defaults:
60
+
61
+ my-macbook:~/my_app $ rake s:d
62
+ ---
63
+ ssl: true => false
64
+
65
+ And if you want to go back to the defaults:
66
+
67
+ my-macbook:~/my_app $ rake switches:reset
68
+
69
+ Remember, you should version control <tt>config/switches/defaults.yml</tt> and ignore <tt>config/switches/current.yml</tt>.
70
+
71
+ == Rationale
72
+
73
+ Sometimes you just need an easy way to "turn off" code.
74
+
75
+ == Wishlist
76
+
77
+ * capistrano task like "cap production s:off[campaign_monitor]"
78
+
79
+ == Copyright
80
+
81
+ Copyright (c) 2009 Seamus Abshere. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,72 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "switches"
8
+ gem.summary = %Q{Turn on and off parts of your code based on yaml files.}
9
+ gem.description = %Q{
10
+ 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.
11
+
12
+ For example:
13
+ app/models/user.rb
14
+ after_create :subscribe_email if Switches.campaign_monitor?
15
+
16
+ >> Switches.campaign_monitor?
17
+ # => false
18
+
19
+ $ rake switches:on[campaign_monitor]
20
+
21
+ >> Switches.campaign_monitor?
22
+ # => true
23
+
24
+ $ rake switches:reset # goes back to default.yml
25
+ $ rake switches:diff # shows diff b/w current.yml and default.yml
26
+ $ rake s:d # alias for switches:diff
27
+ $ rake s:c # alias for switches:list_current
28
+
29
+ etc.
30
+
31
+ It's inspired by ActiveSupport's StringInquirer (e.g. Rails.development?) and traditional compile-time assertions.
32
+ }
33
+ gem.email = "seamus@abshere.net"
34
+ gem.homepage = "http://github.com/seamusabshere/switches"
35
+ gem.authors = ["Seamus Abshere"]
36
+ gem.rubyforge_project = "switches"
37
+ gem.add_development_dependency "rspec", ">= 1.2.9"
38
+ gem.add_dependency "activesupport"
39
+ end
40
+ Jeweler::GemcutterTasks.new
41
+ Jeweler::RubyforgeTasks.new do |rubyforge|
42
+ rubyforge.doc_task = "rdoc"
43
+ end
44
+ rescue LoadError
45
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
46
+ end
47
+
48
+ require 'spec/rake/spectask'
49
+ Spec::Rake::SpecTask.new(:spec) do |spec|
50
+ spec.libs << 'lib' << 'spec'
51
+ spec.spec_files = FileList['spec/**/*_spec.rb']
52
+ end
53
+
54
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
55
+ spec.libs << 'lib' << 'spec'
56
+ spec.pattern = 'spec/**/*_spec.rb'
57
+ spec.rcov = true
58
+ end
59
+
60
+ task :spec => :check_dependencies
61
+
62
+ task :default => :spec
63
+
64
+ require 'rake/rdoctask'
65
+ Rake::RDocTask.new do |rdoc|
66
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
67
+
68
+ rdoc.rdoc_dir = 'rdoc'
69
+ rdoc.title = "switches #{version}"
70
+ rdoc.rdoc_files.include('README*')
71
+ rdoc.rdoc_files.include('lib/**/*.rb')
72
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/switches.rb ADDED
@@ -0,0 +1,139 @@
1
+ require 'yaml'
2
+ require 'rubygems'
3
+ require 'activesupport'
4
+
5
+ # TODO not agnostic, expects RAILS_ROOT
6
+
7
+ module Switches
8
+ CONFIG_DIR = File.join RAILS_ROOT, 'config', 'switches'
9
+ TASKS_DIR = File.join RAILS_ROOT, 'lib', 'tasks'
10
+ CURRENT_PATH = File.join CONFIG_DIR, 'current.yml'
11
+ DEFAULT_PATH = File.join CONFIG_DIR, 'default.yml'
12
+ BACKUP_PATH = File.join CONFIG_DIR, 'backup.yml'
13
+
14
+ class << self
15
+ def say(str)
16
+ $stderr.puts "[SWITCHES GEM] #{str}"
17
+ end
18
+
19
+ def setup
20
+ require 'fileutils'
21
+
22
+ say "Making #{CONFIG_DIR}."
23
+ FileUtils.mkdir_p CONFIG_DIR
24
+
25
+ if File.exists? DEFAULT_PATH
26
+ say "Not putting an example default.yml into #{DEFAULT_PATH} because you already have one."
27
+ else
28
+ say "Putting an example default.yml into #{DEFAULT_PATH}."
29
+ File.open(DEFAULT_PATH, 'w') { |f| f.write({ 'quick_brown' => true, 'fox_jumps' => false }.to_yaml) }
30
+ end
31
+
32
+ say "Copying Rake tasks into #{TASKS_DIR}."
33
+ FileUtils.cp File.join(File.dirname(__FILE__), 'tasks', 'switches.rake'), TASKS_DIR
34
+
35
+ say "Don't forget to:"
36
+ say "* git add #{DEFAULT_PATH}"
37
+ say "* git add #{TASKS_DIR}/switches.rake"
38
+ say "* put 'config/switches/current.yml' to your .gitignore"
39
+ say "You can refresh the gem tasks with Switches.setup. It won't touch anything else."
40
+ end
41
+
42
+ # taken from ActiveSupport::StringInquirer
43
+ def method_missing(method_name, *args)
44
+ suffix = method_name.to_s[-1,1]
45
+ key = method_name.to_s[0..-2]
46
+
47
+ if suffix == "?" and current.has_key?(key)
48
+ current[key]
49
+ elsif suffix == "="
50
+ current[key] = args.first
51
+ # TEMPORARY since we're not doing a write_current here
52
+ else
53
+ super
54
+ end
55
+ end
56
+
57
+ def default
58
+ return @_default unless @_default.nil?
59
+ # say "file system read #{DEFAULT_PATH}"
60
+ @_default = YAML.load(File.read(DEFAULT_PATH))
61
+ @_default.stringify_keys!
62
+ rescue Errno::ENOENT
63
+ say "Couldn't read defaults from #{DEFAULT_PATH}."
64
+ say "You probably want to run \"./script/runner 'Switches.setup'\"."
65
+ raise $!
66
+ end
67
+
68
+ def current
69
+ return @_current unless @_current.nil?
70
+ if File.exist?(CURRENT_PATH)
71
+ # say "file system read #{CURRENT_PATH}"
72
+ @_current = YAML.load(File.read(CURRENT_PATH))
73
+ @_current.stringify_keys!
74
+ else
75
+ @_current = default.dup
76
+ end
77
+ @_current
78
+ end
79
+
80
+ def diff
81
+ retval = {}
82
+ current.inject(retval) do |memo, ary|
83
+ k, current_v = ary
84
+ default_v = default[k]
85
+ memo[k] = "#{default_v.nil? ? 'nil' : default_v} => #{current_v.nil? ? 'nil' : current_v}" if default_v != current_v
86
+ memo
87
+ end
88
+ default.inject(retval) do |memo, ary|
89
+ k, default_v = ary
90
+ current_v = current[k]
91
+ memo[k] = "#{default_v.nil? ? 'nil' : default_v} => #{current_v.nil? ? 'nil' : current_v}" if default_v != current_v
92
+ memo
93
+ end
94
+ retval
95
+ end
96
+
97
+ def turn_off(name)
98
+ name = name.to_s
99
+ current[name] = false
100
+ write_current
101
+ end
102
+
103
+ def turn_on(name)
104
+ name = name.to_s
105
+ current[name] = true
106
+ write_current
107
+ end
108
+
109
+ def clear(name)
110
+ name = name.to_s
111
+ current.delete name
112
+ write_current
113
+ end
114
+
115
+ def reset
116
+ FileUtils.rm_f CURRENT_PATH
117
+ @_current = nil
118
+ end
119
+
120
+ def backup
121
+ write_current
122
+ FileUtils.cp CURRENT_PATH, BACKUP_PATH
123
+ end
124
+
125
+ def restore
126
+ if File.exist?(BACKUP_PATH)
127
+ FileUtils.mv BACKUP_PATH, CURRENT_PATH
128
+ else
129
+ raise ArgumentError, "#{BACKUP_PATH} doesn't exist."
130
+ end
131
+ @_current = nil
132
+ end
133
+
134
+ def write_current
135
+ current # load it first!
136
+ File.open(CURRENT_PATH, 'w') { |f| f.write current.stringify_keys.to_yaml }
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,88 @@
1
+ require 'switches'
2
+
3
+ task :switches do
4
+ Rake::Task['switches:default'].execute
5
+ end
6
+
7
+ namespace :s do
8
+ task :c => 'switches:list_current'
9
+ task :d => 'switches:diff'
10
+ task :on, :name do |t, args|
11
+ Rake::Task['switches:turn_on'].execute args
12
+ end
13
+ task :off, :name do |t, args|
14
+ Rake::Task['switches:turn_off'].execute args
15
+ end
16
+ end
17
+
18
+ namespace :switches do
19
+ desc "List current and show instructions"
20
+ task :default do
21
+ puts <<-EOS
22
+
23
+ Here's a bunch of ugly instructions:
24
+
25
+ List current settings:
26
+ rake s:c
27
+ Show difference between current and default settings:
28
+ rake s:d
29
+ Clear with:
30
+ rake switches:clear[FOOBAR]
31
+
32
+ ... now listing current settings ...
33
+ EOS
34
+ Rake::Task['switches:list_current'].execute
35
+ end
36
+
37
+ # not called :default so it doesn't look like the default task
38
+ desc "List default"
39
+ task :list_default do
40
+ puts Switches.default.to_yaml
41
+ end
42
+
43
+ desc "List current"
44
+ task :list_current do
45
+ puts Switches.current.to_yaml
46
+ end
47
+
48
+ desc "Turn on switch"
49
+ task :turn_on, :name do |t, args|
50
+ Switches.turn_on args.name
51
+ puts Switches.current.to_yaml
52
+ end
53
+
54
+ desc "Turn off switch"
55
+ task :turn_off, :name do |t, args|
56
+ Switches.turn_off args.name
57
+ puts Switches.current.to_yaml
58
+ end
59
+
60
+ desc "Clear switch"
61
+ task :clear, :name do |t, args|
62
+ Switches.clear args.name
63
+ puts Switches.current.to_yaml
64
+ end
65
+
66
+ desc "Diff current vs. default switches"
67
+ task :diff do
68
+ puts Switches.diff.to_yaml
69
+ end
70
+
71
+ desc "Reset all switches to defaults"
72
+ task :reset do
73
+ Switches.reset
74
+ puts Switches.current.to_yaml
75
+ end
76
+
77
+ desc "Backup all switches to defaults"
78
+ task :backup do
79
+ Switches.backup
80
+ puts Switches.current.to_yaml
81
+ end
82
+
83
+ desc "Restore all switches to defaults"
84
+ task :restore do
85
+ Switches.restore
86
+ puts Switches.current.to_yaml
87
+ end
88
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'switches'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Switches" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
data/switches.gemspec ADDED
@@ -0,0 +1,83 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{switches}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Seamus Abshere"]
12
+ s.date = %q{2009-10-30}
13
+ s.description = %q{
14
+ 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.
15
+
16
+ For example:
17
+ app/models/user.rb
18
+ after_create :subscribe_email if Switches.campaign_monitor?
19
+
20
+ >> Switches.campaign_monitor?
21
+ # => false
22
+
23
+ $ rake switches:on[campaign_monitor]
24
+
25
+ >> Switches.campaign_monitor?
26
+ # => true
27
+
28
+ $ rake switches:reset # goes back to default.yml
29
+ $ rake switches:diff # shows diff b/w current.yml and default.yml
30
+ $ rake s:d # alias for switches:diff
31
+ $ rake s:c # alias for switches:list_current
32
+
33
+ etc.
34
+
35
+ It's inspired by ActiveSupport's StringInquirer (e.g. Rails.development?) and traditional compile-time assertions.
36
+ }
37
+ s.email = %q{seamus@abshere.net}
38
+ s.extra_rdoc_files = [
39
+ "LICENSE",
40
+ "README.rdoc"
41
+ ]
42
+ s.files = [
43
+ ".document",
44
+ ".gitignore",
45
+ "LICENSE",
46
+ "README.rdoc",
47
+ "Rakefile",
48
+ "VERSION",
49
+ "lib/switches.rb",
50
+ "lib/tasks/switches.rake",
51
+ "spec/spec.opts",
52
+ "spec/spec_helper.rb",
53
+ "spec/switches_spec.rb",
54
+ "switches.gemspec"
55
+ ]
56
+ s.homepage = %q{http://github.com/seamusabshere/switches}
57
+ s.rdoc_options = ["--charset=UTF-8"]
58
+ s.require_paths = ["lib"]
59
+ s.rubyforge_project = %q{switches}
60
+ s.rubygems_version = %q{1.3.5}
61
+ s.summary = %q{Turn on and off parts of your code based on yaml files.}
62
+ s.test_files = [
63
+ "spec/spec_helper.rb",
64
+ "spec/switches_spec.rb"
65
+ ]
66
+
67
+ if s.respond_to? :specification_version then
68
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
69
+ s.specification_version = 3
70
+
71
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
72
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
73
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
74
+ else
75
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
76
+ s.add_dependency(%q<activesupport>, [">= 0"])
77
+ end
78
+ else
79
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
80
+ s.add_dependency(%q<activesupport>, [">= 0"])
81
+ end
82
+ end
83
+
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: switches
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Seamus Abshere
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-30 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: "\n\
36
+ 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.\n\n\
37
+ For example:\n\
38
+ app/models/user.rb\n\
39
+ after_create :subscribe_email if Switches.campaign_monitor?\n\n\
40
+ >> Switches.campaign_monitor?\n\
41
+ # => false\n\n\
42
+ $ rake switches:on[campaign_monitor]\n\n\
43
+ >> Switches.campaign_monitor?\n\
44
+ # => true\n\n\
45
+ $ rake switches:reset # goes back to default.yml\n\
46
+ $ rake switches:diff # shows diff b/w current.yml and default.yml\n\
47
+ $ rake s:d # alias for switches:diff\n\
48
+ $ rake s:c # alias for switches:list_current\n\n\
49
+ etc.\n\n\
50
+ It's inspired by ActiveSupport's StringInquirer (e.g. Rails.development?) and traditional compile-time assertions.\n "
51
+ email: seamus@abshere.net
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files:
57
+ - LICENSE
58
+ - README.rdoc
59
+ files:
60
+ - .document
61
+ - .gitignore
62
+ - LICENSE
63
+ - README.rdoc
64
+ - Rakefile
65
+ - VERSION
66
+ - lib/switches.rb
67
+ - lib/tasks/switches.rake
68
+ - spec/spec.opts
69
+ - spec/spec_helper.rb
70
+ - spec/switches_spec.rb
71
+ - switches.gemspec
72
+ has_rdoc: true
73
+ homepage: http://github.com/seamusabshere/switches
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --charset=UTF-8
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ version:
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ version:
93
+ requirements: []
94
+
95
+ rubyforge_project: switches
96
+ rubygems_version: 1.3.5
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Turn on and off parts of your code based on yaml files.
100
+ test_files:
101
+ - spec/spec_helper.rb
102
+ - spec/switches_spec.rb