redis_feature_control 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.gemspec
2
+ pkg
3
+ nbproject
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 Ben VandenBos
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.
21
+
data/README.md ADDED
@@ -0,0 +1,63 @@
1
+ redis_feature_control
2
+ =====================
3
+
4
+ Redis_feature_control is a module to mark features/services as enabled or disabled
5
+ so jobs can take appropriate action.
6
+
7
+
8
+ ### Why?
9
+
10
+ Sometimes you depend on services. Sometimes these services go down. Sometimes
11
+ you want to explicitly turn off services and have your app know the service is
12
+ turned off. That way your app can display a pretty message to a user
13
+ rather than trying a service and waiting for it to time out. Maybe your backend
14
+ job depends on a service. When it notices it's disabled, it can sleep or delay
15
+ that job to sometime in the future without having to test the service.
16
+
17
+
18
+
19
+ ### Usage
20
+
21
+ First configure it:
22
+
23
+ require 'rubygems'
24
+ require 'redis/feature_control'
25
+ Redis::FeatureControl.connection_string = "redis_server:6379"
26
+
27
+ Then add your features/services to it:
28
+
29
+ Redis::FeatureControl.features << :data_warehouse
30
+ Redis::FeatureControl.features << :cc_gateway
31
+ Redis::FeatureControl.features << :hulu
32
+
33
+ Then see if they are enabled and toggle them:
34
+
35
+ # on by default
36
+ Redis::FeatureControl.enabled?(:cc_gateway) # => true
37
+
38
+ # disabling...
39
+ Redis::FeatureControl.disable!(:cc_gateway)
40
+ Redis::FeatureControl.enabled?(:cc_gateway) # => false
41
+ Redis::FeatureControl.status(:cc_gateway) # => "disabled"
42
+
43
+ # enabling...
44
+ Redis::FeatureControl.enable!(:cc_gateway)
45
+ Redis::FeatureControl.enabled?(:cc_gateway) # => true
46
+ Redis::FeatureControl.disabled?(:cc_gateway) # => false
47
+ Redis::FeatureControl.status(:cc_gateway) # => "enabled"
48
+
49
+ ### Mocking for Test/Development
50
+
51
+ Since you don't always have redis available in development and test, sometimes
52
+ it's nice to just keep the state of features in memory. You can enable the mock
53
+ behavior like so:
54
+
55
+ Redis::FeatureControl.mock!
56
+
57
+ It will work exactly the same as when it's using redis, but it will only store
58
+ the states of features in memory.
59
+
60
+ To stop mocking:
61
+
62
+ Redis::FeatureControl.unmock!
63
+
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+
3
+ task :default => :test
4
+
5
+ desc "Run tests"
6
+ task :test do
7
+ Dir['test/*_test.rb'].each do |f|
8
+ require f
9
+ end
10
+ end
11
+
12
+ desc "Build a gem"
13
+ task :gem => [ :test, :gemspec, :build ]
14
+
15
+ begin
16
+ begin
17
+ require 'jeweler'
18
+ rescue LoadError
19
+ puts "Jeweler not available. Install it with: "
20
+ puts "gem install jeweler"
21
+ end
22
+
23
+ require 'redis/feature_control'
24
+
25
+ Jeweler::Tasks.new do |gemspec|
26
+ gemspec.name = "redis_feature_control"
27
+ gemspec.summary = "Feature enable/disable library on top of Redis"
28
+ gemspec.description = gemspec.summary
29
+ gemspec.email = "bvandenbos@gmail.com"
30
+ gemspec.homepage = "http://github.com/bvandenbos/redis_feature_control"
31
+ gemspec.authors = ["Ben VandenBos"]
32
+ gemspec.version = Redis::FeatureControl::Version
33
+
34
+ gemspec.add_dependency "redis", ">= 0.1.1"
35
+ gemspec.add_dependency "redis-namespace", ">= 0.2.0"
36
+ gemspec.add_development_dependency "jeweler"
37
+ gemspec.add_development_dependency "mocha"
38
+ end
39
+ end
40
+
41
+
42
+ desc "Push a new version to Gemcutter"
43
+ task :publish => [ :test, :gemspec, :build ] do
44
+ require 'redis/feature_control'
45
+ system "git tag v#{Redis::FeatureControl::Version}"
46
+ system "git push origin v#{Redis::FeatureControl::Version}"
47
+ system "git push origin master"
48
+ system "gem push pkg/redis_feature_control-#{Redis::FeatureControl::Version}.gem"
49
+ system "git clean -fd"
50
+ end
@@ -0,0 +1,141 @@
1
+ require 'rubygems'
2
+ require 'redis'
3
+ require 'redis/namespace'
4
+
5
+ #
6
+ # Redis::FeatureControl
7
+ #
8
+ # The point of this is to have a very simple way to turn pieces of the site on
9
+ # and off without having to load your entire Rails stack (models, etc).
10
+ #
11
+ # How it stores stuff in Redis:
12
+ # Features default on, so if the value in redis is nil, it's considered
13
+ # enabled. The value is "1" when explicitly turned on and "0" when off.
14
+ #
15
+ class Redis
16
+
17
+ module FeatureControl
18
+
19
+ Version = '0.0.1'
20
+
21
+ class Redis::FeatureControl::UnknownFeatureError < RuntimeError; end;
22
+
23
+ class << self
24
+
25
+ attr_accessor :features
26
+
27
+ def features
28
+ @features ||= []
29
+ end
30
+
31
+ def host
32
+ @host ||= 'localhost'
33
+ end
34
+
35
+ def port
36
+ @port ||= 6379
37
+ end
38
+
39
+ # Redis::FeatureControl
40
+ def connection_string=(value)
41
+ @host, @port = value.split(":", 2)
42
+ redis_connect!
43
+ end
44
+
45
+ # Connects to redis on the current host/port and sets the redis object
46
+ def redis_connect!
47
+ redis = Redis.new(:host => host, :port => port, :thread_safe => true)
48
+ @redis = Redis::Namespace.new(:feature_control, :redis => redis)
49
+ end
50
+
51
+ def redis
52
+ if @redis.nil?
53
+ begin
54
+ redis_connect!
55
+ rescue Errno::ECONNREFUSED
56
+ end
57
+ end
58
+ @redis
59
+ end
60
+
61
+ def disabled?(feature)
62
+ check_feature!(feature)
63
+ !enabled?(feature)
64
+ end
65
+
66
+ def enabled?(feature)
67
+ check_feature!(feature)
68
+ if mock?
69
+ mock_feature_hash[feature.to_s].nil? || true == mock_feature_hash[feature.to_s]
70
+ else
71
+ (redis.get(feature.to_s) || 1).to_i == 1
72
+ end
73
+ rescue Errno::ECONNREFUSED
74
+ true # default to enabled if we can't connect to redis
75
+ end
76
+
77
+ def enable!(feature)
78
+ check_feature!(feature)
79
+ if mock?
80
+ mock_feature_hash[feature.to_s] = true
81
+ else
82
+ redis.set(feature.to_s, 1)
83
+ end
84
+ rescue Errno::ECONNREFUSED
85
+ # Ignore
86
+ end
87
+
88
+ def disable!(feature)
89
+ check_feature!(feature)
90
+ if mock?
91
+ mock_feature_hash[feature.to_s] = false
92
+ else
93
+ redis.set(feature.to_s, 0)
94
+ end
95
+ rescue Errno::ECONNREFUSED
96
+ # Ignore
97
+ end
98
+
99
+ # value >=1 enable the feature
100
+ # value <1 disable the feature
101
+ def set_status(feature, value)
102
+ value = value.to_i
103
+ if value >= 1
104
+ enable!(feature)
105
+ else
106
+ disable!(feature)
107
+ end
108
+ end
109
+
110
+ # Returns a string for the state of the feature
111
+ def state(feature)
112
+ enabled?(feature) ? 'enabled' : 'disabled'
113
+ end
114
+
115
+ def check_feature!(feature)
116
+ raise Redis::FeatureControl::UnknownFeatureError unless features.include?(feature.to_sym)
117
+ end
118
+
119
+ # This redfines enabled/disabled to only use class variables instead of connecting
120
+ # to redis. This allows you to run tests w/out a connection to redis
121
+ def mock!
122
+ @mock = true
123
+ end
124
+
125
+ def unmock!
126
+ @mock = false
127
+ end
128
+
129
+ def mock?
130
+ @mock
131
+ end
132
+
133
+ def mock_feature_hash
134
+ @feature_hash ||= {}
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+ end
@@ -0,0 +1,117 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class Redis::FeatureControlTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ Redis::FeatureControl.connection_string = 'localhost:9736'
7
+ Redis::FeatureControl.unmock!
8
+ Redis::FeatureControl.features = [:enabled_feature]
9
+ Redis::FeatureControl.redis.flushall
10
+ end
11
+
12
+ def test_connection_string_works
13
+ Redis::FeatureControl.connection_string = "redis:1234"
14
+ assert_equal('redis', Redis::FeatureControl.host)
15
+ assert_equal('1234', Redis::FeatureControl.port)
16
+ end
17
+
18
+ def test_redis
19
+ assert(Redis::FeatureControl.redis.is_a?(Redis::Namespace))
20
+ end
21
+
22
+ def test_unknown_features_raise_errors
23
+ assert_raises(Redis::FeatureControl::UnknownFeatureError) do
24
+ Redis::FeatureControl.enabled?(:some_feature)
25
+ end
26
+ end
27
+
28
+ def test_enable_disable
29
+ Redis::FeatureControl.features << :cool_service # add a feature
30
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should be enabled by default
31
+ assert(!Redis::FeatureControl.disabled?(:cool_service)) # should be enabled by default
32
+
33
+ Redis::FeatureControl.enable!(:cool_service)
34
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
35
+
36
+ Redis::FeatureControl.disable!(:cool_service)
37
+ assert(!Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
38
+ assert(Redis::FeatureControl.disabled?(:cool_service)) # should still be enabled
39
+
40
+ Redis::FeatureControl.enable!(:cool_service)
41
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
42
+ end
43
+
44
+ def test_set_status
45
+
46
+ Redis::FeatureControl.features << :cool_service # add a feature
47
+
48
+ Redis::FeatureControl.set_status(:cool_service, 0.9) # <1
49
+ assert(Redis::FeatureControl.disabled?(:cool_service)) # should still be enabled
50
+
51
+ Redis::FeatureControl.set_status(:cool_service, 1.0)
52
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
53
+
54
+ Redis::FeatureControl.set_status(:cool_service, -1)
55
+ assert(Redis::FeatureControl.disabled?(:cool_service)) # should still be enabled
56
+
57
+ Redis::FeatureControl.set_status(:cool_service, -1.0)
58
+ assert(Redis::FeatureControl.disabled?(:cool_service)) # should still be enabled
59
+
60
+ Redis::FeatureControl.set_status(:cool_service, 42)
61
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
62
+
63
+ Redis::FeatureControl.set_status(:cool_service, -42)
64
+ assert(Redis::FeatureControl.disabled?(:cool_service)) # should still be enabled
65
+
66
+ end
67
+
68
+ def test_state_string
69
+ Redis::FeatureControl.features << :cool_service # add a feature
70
+
71
+ Redis::FeatureControl.enable!(:cool_service)
72
+ assert_equal('enabled', Redis::FeatureControl.state(:cool_service))
73
+
74
+ Redis::FeatureControl.disable!(:cool_service)
75
+ assert_equal('disabled', Redis::FeatureControl.state(:cool_service))
76
+ end
77
+
78
+ def test_check_feature
79
+ assert_raises(Redis::FeatureControl::UnknownFeatureError) do
80
+ Redis::FeatureControl.enabled?(:some_feature)
81
+ end
82
+
83
+ assert_nothing_raised do
84
+ Redis::FeatureControl.enabled?(:enabled_feature)
85
+ end
86
+ end
87
+
88
+ def test_mock
89
+
90
+ Redis::FeatureControl.mock!
91
+ assert(Redis::FeatureControl.mock?)
92
+
93
+ Redis::FeatureControl.unmock!
94
+ assert(!Redis::FeatureControl.mock?)
95
+ end
96
+
97
+ def test_mock_enable_disable
98
+ Redis::FeatureControl.mock!
99
+
100
+ Redis::FeatureControl.expects(:redis).never # It's mocked, so it shouldn't use redis
101
+
102
+ Redis::FeatureControl.features << :cool_service # add a feature
103
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should be enabled by default
104
+ assert(!Redis::FeatureControl.disabled?(:cool_service)) # should be enabled by default
105
+
106
+ Redis::FeatureControl.enable!(:cool_service)
107
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
108
+
109
+ Redis::FeatureControl.disable!(:cool_service)
110
+ assert(!Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
111
+ assert(Redis::FeatureControl.disabled?(:cool_service)) # should still be enabled
112
+
113
+ Redis::FeatureControl.enable!(:cool_service)
114
+ assert(Redis::FeatureControl.enabled?(:cool_service)) # should still be enabled
115
+ end
116
+
117
+ end
@@ -0,0 +1,132 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile ./test/redis-test.pid
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port 9736
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Save the DB on disk:
23
+ #
24
+ # save <seconds> <changes>
25
+ #
26
+ # Will save the DB if both the given number of seconds and the given
27
+ # number of write operations against the DB occurred.
28
+ #
29
+ # In the example below the behaviour will be to save:
30
+ # after 900 sec (15 min) if at least 1 key changed
31
+ # after 300 sec (5 min) if at least 10 keys changed
32
+ # after 60 sec if at least 10000 keys changed
33
+ save 900 1
34
+ save 300 10
35
+ save 60 10000
36
+
37
+ # The filename where to dump the DB
38
+ dbfilename dump.rdb
39
+
40
+ # For default save/load DB in/from the working directory
41
+ # Note that you must specify a directory not a file name.
42
+ dir ./test/
43
+
44
+ # Set server verbosity to 'debug'
45
+ # it can be one of:
46
+ # debug (a lot of information, useful for development/testing)
47
+ # notice (moderately verbose, what you want in production probably)
48
+ # warning (only very important / critical messages are logged)
49
+ loglevel debug
50
+
51
+ # Specify the log file name. Also 'stdout' can be used to force
52
+ # the demon to log on the standard output. Note that if you use standard
53
+ # output for logging but daemonize, logs will be sent to /dev/null
54
+ logfile stdout
55
+
56
+ # Set the number of databases. The default database is DB 0, you can select
57
+ # a different one on a per-connection basis using SELECT <dbid> where
58
+ # dbid is a number between 0 and 'databases'-1
59
+ databases 16
60
+
61
+ ################################# REPLICATION #################################
62
+
63
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
64
+ # another Redis server. Note that the configuration is local to the slave
65
+ # so for example it is possible to configure the slave to save the DB with a
66
+ # different interval, or to listen to another port, and so on.
67
+
68
+ # slaveof <masterip> <masterport>
69
+
70
+ ################################## SECURITY ###################################
71
+
72
+ # Require clients to issue AUTH <PASSWORD> before processing any other
73
+ # commands. This might be useful in environments in which you do not trust
74
+ # others with access to the host running redis-server.
75
+ #
76
+ # This should stay commented out for backward compatibility and because most
77
+ # people do not need auth (e.g. they run their own servers).
78
+
79
+ # requirepass foobared
80
+
81
+ ################################### LIMITS ####################################
82
+
83
+ # Set the max number of connected clients at the same time. By default there
84
+ # is no limit, and it's up to the number of file descriptors the Redis process
85
+ # is able to open. The special value '0' means no limts.
86
+ # Once the limit is reached Redis will close all the new connections sending
87
+ # an error 'max number of clients reached'.
88
+
89
+ # maxclients 128
90
+
91
+ # Don't use more memory than the specified amount of bytes.
92
+ # When the memory limit is reached Redis will try to remove keys with an
93
+ # EXPIRE set. It will try to start freeing keys that are going to expire
94
+ # in little time and preserve keys with a longer time to live.
95
+ # Redis will also try to remove objects from free lists if possible.
96
+ #
97
+ # If all this fails, Redis will start to reply with errors to commands
98
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
99
+ # to reply to most read-only commands like GET.
100
+ #
101
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
102
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
103
+ # database the memory usage will grow over the weeks, it will be obvious if
104
+ # it is going to use too much memory in the long run, and you'll have the time
105
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
106
+ # errors for write operations, and this may even lead to DB inconsistency.
107
+
108
+ # maxmemory <bytes>
109
+
110
+ ############################### ADVANCED CONFIG ###############################
111
+
112
+ # Glue small output buffers together in order to send small replies in a
113
+ # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
+ # in terms of number of queries per second. Use 'yes' if unsure.
115
+ glueoutputbuf yes
116
+
117
+ # Use object sharing. Can save a lot of memory if you have many common
118
+ # string in your dataset, but performs lookups against the shared objects
119
+ # pool so it uses more CPU and can be a bit slower. Usually it's a good
120
+ # idea.
121
+ #
122
+ # When object sharing is enabled (shareobjects yes) you can use
123
+ # shareobjectspoolsize to control the size of the pool used in order to try
124
+ # object sharing. A bigger pool size will lead to better sharing capabilities.
125
+ # In general you want this value to be at least the double of the number of
126
+ # very common strings you have in your dataset.
127
+ #
128
+ # WARNING: object sharing is experimental, don't enable this feature
129
+ # in production before of Redis 1.0-stable. Still please try this feature in
130
+ # your development environment so that we can test it better.
131
+ shareobjects no
132
+ shareobjectspoolsize 1024
@@ -0,0 +1,40 @@
1
+ dir = File.dirname(File.expand_path(__FILE__))
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'mocha'
6
+ require 'redis'
7
+ $LOAD_PATH.unshift File.dirname(File.expand_path(__FILE__)) + '/../lib'
8
+ require 'redis/feature_control'
9
+
10
+ #
11
+ # make sure we can run redis
12
+ #
13
+
14
+ if !system("which redis-server")
15
+ puts '', "** can't find `redis-server` in your path"
16
+ puts "** try running `sudo rake install`"
17
+ abort ''
18
+ end
19
+
20
+
21
+ #
22
+ # start our own redis when the tests start,
23
+ # kill it when they end
24
+ #
25
+
26
+ at_exit do
27
+ next if $!
28
+
29
+ exit_code = Test::Unit::AutoRunner.run
30
+
31
+ pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
32
+ puts "Killing test redis server..."
33
+ `rm -f #{dir}/dump.rdb`
34
+ Process.kill("KILL", pid.to_i)
35
+ exit exit_code
36
+ end
37
+
38
+ puts "Starting redis for testing at localhost:9736..."
39
+ `redis-server #{dir}/redis-test.conf`
40
+ Redis::FeatureControl.connection_string = 'localhost:9736'
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redis_feature_control
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ben VandenBos
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-03-10 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: redis
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.1.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: redis-namespace
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.0
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: jeweler
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: mocha
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ description: Feature enable/disable library on top of Redis
56
+ email: bvandenbos@gmail.com
57
+ executables: []
58
+
59
+ extensions: []
60
+
61
+ extra_rdoc_files:
62
+ - LICENSE
63
+ - README.md
64
+ files:
65
+ - .gitignore
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - lib/redis/feature_control.rb
70
+ - test/feature_control_test.rb
71
+ - test/redis-test.conf
72
+ - test/test_helper.rb
73
+ has_rdoc: true
74
+ homepage: http://github.com/bvandenbos/redis_feature_control
75
+ licenses: []
76
+
77
+ post_install_message:
78
+ rdoc_options:
79
+ - --charset=UTF-8
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ version:
94
+ requirements: []
95
+
96
+ rubyforge_project:
97
+ rubygems_version: 1.3.5
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Feature enable/disable library on top of Redis
101
+ test_files:
102
+ - test/feature_control_test.rb
103
+ - test/test_helper.rb