switches 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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