feature_guard 0.1.2 → 0.2.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ac443b4c9e81abf91976dd0bc5ab802b7ea2b11f
4
+ data.tar.gz: 5e95d160aa879d4867bd33274f035c0690c1ff22
5
+ SHA512:
6
+ metadata.gz: 435e28575454290cc3da192e53a3a84c8f5c008ee504a11fe9d195774c1562e26ad3f1dee945191064d6b3c4e18ac5746c8b29813e6469aee76b6e59992005b2
7
+ data.tar.gz: 8d7898ad67a3b76ad8aa33767b12a1f3113114001a30798d6e5ed58a84a352fb4ad67bc60e5910170ad71f815a422d713ad352467a60e1a25bcd2869e691600e
data/README.md CHANGED
@@ -60,6 +60,25 @@ FeatureGuard.allow? :my_feature
60
60
 
61
61
  The optional second argument to`.allow?` can be of any type (e.g., user ID or name or even an object). It is hashed with the feature name to create a reproducible numeric value for checking whether to return true or false based on the current ramp-up value. With no second argument, `.allow?` uses a new random value on every call.
62
62
 
63
+ To retrieve information on all binary-enabled/disabled features, use `.all_flags`:
64
+
65
+ ```ruby
66
+ FeatureGuard.enable :my_feature
67
+ FeatureGuard.enable :another_feature
68
+ FeatureGuard.toggle :my_feature
69
+ FeatureGuard.all_flags
70
+ # {"my_feature"=>false, "another_feature"=>true}
71
+ ```
72
+
73
+ To retrieve information on all ramp values, use `.all_ramps`:
74
+
75
+ ```ruby
76
+ FeatureGuard.set_ramp :my_feature, 50
77
+ FeatureGuard.set_ramp :another_feature, 30
78
+ FeatureGuard.all_ramps
79
+ # {"my_feature"=>50.0, "another_feature"=>30.0}
80
+ ```
81
+
63
82
  ## Configuration
64
83
 
65
84
  Optionally change the Redis client with:
@@ -3,7 +3,7 @@ require File.expand_path('../lib/feature_guard/version', __FILE__)
3
3
 
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Ted Dumitrescu"]
6
- gem.email = ["miscmisc@cmme.org"]
6
+ gem.email = ["webdev@cmme.org"]
7
7
  gem.summary = %q{Simple Redis-based feature-flagging}
8
8
  gem.description = <<end
9
9
  Feature flags made simple: turn code on or off with Redis controls, allowing
@@ -22,5 +22,5 @@ end
22
22
  gem.add_dependency "redis", "~> 3.0"
23
23
 
24
24
  gem.add_development_dependency "fakeredis", "~> 0.4"
25
- gem.add_development_dependency "rspec", "~> 2.13"
25
+ gem.add_development_dependency "rspec", "~> 2.99"
26
26
  end
@@ -7,11 +7,30 @@ module FeatureGuard
7
7
  class << self
8
8
  attr_writer :redis
9
9
 
10
+ def all_flags
11
+ redis.hgetall(flags_hkey).keys.inject({}) { |h, f| h[f] = enabled? f; h }
12
+ end
13
+
14
+ def all_ramps
15
+ redis.hgetall(ramps_hkey).keys.inject({}) { |h, f| h[f] = ramp_val f; h }
16
+ end
17
+
18
+ def flags_hkey
19
+ "featureguard_flags"
20
+ end
21
+
22
+ def ramps_hkey
23
+ "featureguard_ramps"
24
+ end
25
+
10
26
  def redis
11
27
  @redis ||= Redis.new
12
28
  end
13
29
 
14
- [:allow?, :bump_ramp, :disable, :enable, :toggle, :enabled?, :ramp_val, :set_ramp].each do |mname|
30
+ [
31
+ :allow?, :bump_ramp, :disable, :enable, :toggle, :enabled?,
32
+ :ramp_val, :set_ramp
33
+ ].each do |mname|
15
34
  define_method(mname) do |key, *args|
16
35
  Guard.new(key).send(mname, *args)
17
36
  end
@@ -7,15 +7,15 @@ module FeatureGuard; class Guard
7
7
 
8
8
  # binary flag methods (enabled/disabled)
9
9
  def disable
10
- redis.set(flag_key, 0)
10
+ redis.hset(FeatureGuard.flags_hkey, feature_name, 0)
11
11
  end
12
12
 
13
13
  def enable
14
- redis.set(flag_key, 1)
14
+ redis.hset(FeatureGuard.flags_hkey, feature_name, 1)
15
15
  end
16
16
 
17
17
  def enabled?
18
- redis.get(flag_key).tap { |v| return (!v.nil? && v.to_i > 0) }
18
+ redis.hget(FeatureGuard.flags_hkey, feature_name).tap { |v| return (!v.nil? && v.to_i > 0) }
19
19
  rescue
20
20
  false
21
21
  end
@@ -35,7 +35,7 @@ module FeatureGuard; class Guard
35
35
  end
36
36
 
37
37
  def ramp_val
38
- redis.get(ramp_key).to_f
38
+ redis.hget(FeatureGuard.ramps_hkey, feature_name).to_f
39
39
  end
40
40
 
41
41
  def set_ramp(new_val)
@@ -43,26 +43,14 @@ module FeatureGuard; class Guard
43
43
  new_val = 100.0 if new_val > 100.0
44
44
  new_val = 0.0 if new_val < 0.0
45
45
 
46
- redis.set(ramp_key, new_val)
46
+ redis.hset(FeatureGuard.ramps_hkey, feature_name, new_val)
47
47
  new_val
48
48
  end
49
49
 
50
50
  private
51
51
 
52
- def feature_key
53
- @feature_key ||= feature_name.to_s.split.join('_')
54
- end
55
-
56
- def flag_key
57
- @flag_key ||= "fgf_#{feature_key}"
58
- end
59
-
60
- def ramp_key
61
- @ramp_key ||= "fgr_#{feature_key}"
62
- end
63
-
64
52
  def hashed_val(s)
65
- (Digest::MD5.hexdigest("#{ramp_key}_#{s}").to_i(16) % 10000).to_f / 100.0
53
+ (Digest::MD5.hexdigest("#{feature_name}_#{s}").to_i(16) % 10000).to_f / 100.0
66
54
  end
67
55
 
68
56
  def random_val
@@ -1,3 +1,3 @@
1
1
  module FeatureGuard
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -12,7 +12,7 @@ describe FeatureGuard::Guard do
12
12
 
13
13
  it 'uses a random value' do
14
14
  expect(guard).to receive(:random_val).and_return(29.9)
15
- expect(subject).to be_true
15
+ expect(subject).to eq(true)
16
16
  end
17
17
  end
18
18
 
@@ -21,7 +21,7 @@ describe FeatureGuard::Guard do
21
21
 
22
22
  it 'hashes the value together with the feature name' do
23
23
  expect(guard).to receive(:hashed_val).and_return(30.1)
24
- expect(subject).to be_false
24
+ expect(subject).to eq(false)
25
25
  end
26
26
  end
27
27
  end
@@ -42,13 +42,13 @@ describe FeatureGuard::Guard do
42
42
  subject { guard.enabled? }
43
43
 
44
44
  context 'for a non-existent flag' do
45
- it { should be_false }
45
+ it { is_expected.to eq(false) }
46
46
  end
47
47
 
48
48
  context 'for an enabled flag' do
49
49
  before { guard.enable }
50
50
 
51
- it { should be_true }
51
+ it { is_expected.to eq(true) }
52
52
  end
53
53
  end
54
54
 
@@ -41,13 +41,53 @@ describe FeatureGuard do
41
41
  subject { FeatureGuard.enabled? feature }
42
42
 
43
43
  context 'for a non-existent flag' do
44
- it { should be_false }
44
+ it { is_expected.to eq(false) }
45
45
  end
46
46
 
47
47
  context 'when the Redis client blows up or is non-existent' do
48
48
  before { FeatureGuard.stub(redis: nil) }
49
49
 
50
- it { should be_false }
50
+ it { is_expected.to eq(false) }
51
+ end
52
+ end
53
+
54
+ describe '.all_flags' do
55
+ subject { FeatureGuard.all_flags }
56
+
57
+ it 'returns information on enabled flags' do
58
+ expect {
59
+ FeatureGuard.enable feature
60
+ }.to change {
61
+ FeatureGuard.all_flags
62
+ }.from({}).to({feature.to_s => true})
63
+ end
64
+
65
+ it 'returns information on multiple flags' do
66
+ FeatureGuard.enable feature
67
+ FeatureGuard.enable 'another feature'
68
+ expect(subject.keys.size).to eq(2)
69
+ expect(subject.keys).to include(feature.to_s)
70
+ expect(subject.keys).to include('another feature')
71
+ end
72
+ end
73
+
74
+ describe '.all_ramps' do
75
+ subject { FeatureGuard.all_ramps }
76
+
77
+ it 'returns information on ramped flags' do
78
+ expect {
79
+ FeatureGuard.set_ramp feature, 50
80
+ }.to change {
81
+ FeatureGuard.all_ramps
82
+ }.from({}).to({feature.to_s => 50.0})
83
+ end
84
+
85
+ it 'returns information on multiple flags' do
86
+ FeatureGuard.set_ramp feature, 99
87
+ FeatureGuard.set_ramp 'another feature', 33
88
+ expect(subject.keys.size).to eq(2)
89
+ expect(subject.keys).to include(feature.to_s)
90
+ expect(subject.keys).to include('another feature')
51
91
  end
52
92
  end
53
93
  end
metadata CHANGED
@@ -1,57 +1,62 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feature_guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
5
- prerelease:
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Ted Dumitrescu
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-11-01 00:00:00.000000000 Z
11
+ date: 2015-02-03 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: redis
16
- requirement: &2164445320 !ruby/object:Gem::Requirement
17
- none: false
15
+ requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
21
19
  version: '3.0'
22
20
  type: :runtime
23
21
  prerelease: false
24
- version_requirements: *2164445320
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
25
27
  - !ruby/object:Gem::Dependency
26
28
  name: fakeredis
27
- requirement: &2164444580 !ruby/object:Gem::Requirement
28
- none: false
29
+ requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - ~>
31
32
  - !ruby/object:Gem::Version
32
33
  version: '0.4'
33
34
  type: :development
34
35
  prerelease: false
35
- version_requirements: *2164444580
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.4'
36
41
  - !ruby/object:Gem::Dependency
37
42
  name: rspec
38
- requirement: &2164444120 !ruby/object:Gem::Requirement
39
- none: false
43
+ requirement: !ruby/object:Gem::Requirement
40
44
  requirements:
41
45
  - - ~>
42
46
  - !ruby/object:Gem::Version
43
- version: '2.13'
47
+ version: '2.99'
44
48
  type: :development
45
49
  prerelease: false
46
- version_requirements: *2164444120
47
- description: ! 'Feature flags made simple: turn code on or off with Redis controls,
48
- allowing
49
-
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.99'
55
+ description: |
56
+ Feature flags made simple: turn code on or off with Redis controls, allowing
50
57
  plain enabled/disabled states as well as finer-grained percentage-based control.
51
-
52
- '
53
58
  email:
54
- - miscmisc@cmme.org
59
+ - webdev@cmme.org
55
60
  executables: []
56
61
  extensions: []
57
62
  extra_rdoc_files: []
@@ -72,30 +77,28 @@ files:
72
77
  homepage: https://github.com/tdumitrescu/feature_guard
73
78
  licenses:
74
79
  - MIT
80
+ metadata: {}
75
81
  post_install_message:
76
82
  rdoc_options: []
77
83
  require_paths:
78
84
  - lib
79
85
  required_ruby_version: !ruby/object:Gem::Requirement
80
- none: false
81
86
  requirements:
82
- - - ! '>='
87
+ - - '>='
83
88
  - !ruby/object:Gem::Version
84
89
  version: '0'
85
90
  required_rubygems_version: !ruby/object:Gem::Requirement
86
- none: false
87
91
  requirements:
88
- - - ! '>='
92
+ - - '>='
89
93
  - !ruby/object:Gem::Version
90
94
  version: '0'
91
95
  requirements: []
92
96
  rubyforge_project:
93
- rubygems_version: 1.8.10
97
+ rubygems_version: 2.0.14
94
98
  signing_key:
95
- specification_version: 3
99
+ specification_version: 4
96
100
  summary: Simple Redis-based feature-flagging
97
101
  test_files:
98
102
  - spec/feature_guard/guard_spec.rb
99
103
  - spec/feature_guard_spec.rb
100
104
  - spec/spec_helper.rb
101
- has_rdoc: