feature_creep 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,24 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- feature_creep (0.2.0)
5
- redis
4
+ feature_creep (0.2.1)
6
5
 
7
6
  GEM
8
7
  remote: http://rubygems.org/
9
8
  specs:
10
9
  bourne (1.0)
11
10
  mocha (= 0.9.8)
12
- coderay (1.0.7)
11
+ coderay (1.0.8)
13
12
  diff-lcs (1.1.3)
13
+ feature_creep-redis (0.0.1)
14
+ redis
15
+ feature_creep-simple_strategy (0.0.2)
14
16
  git (1.2.5)
15
17
  jeweler (1.6.4)
16
18
  bundler (~> 1.0)
17
19
  git (>= 1.2.5)
18
20
  rake
19
- method_source (0.8)
21
+ method_source (0.8.1)
20
22
  mocha (0.9.8)
21
23
  rake
22
24
  pry (0.9.10)
@@ -42,6 +44,8 @@ DEPENDENCIES
42
44
  bourne (= 1.0)
43
45
  bundler (>= 1.0.0)
44
46
  feature_creep!
47
+ feature_creep-redis
48
+ feature_creep-simple_strategy (= 0.0.2)
45
49
  jeweler (~> 1.6.4)
46
50
  mocha (= 0.9.8)
47
51
  pry (= 0.9.10)
data/README.md CHANGED
@@ -11,6 +11,11 @@ This is not a drop in replacement. The API has aleadey changed.
11
11
  Namely, `groups` are now `scopes` and `users` are `agent_ids`.
12
12
  Agent_ids are expected to be uuids, not the object itself.
13
13
 
14
+ There are currently 3 gems in this ecosystem:
15
+ `gem 'feature_creep'`
16
+ `gem 'feature_creep-redis'`
17
+ `gem 'feature_creep-simple_strategy'`
18
+
14
19
  The class constructor now takes
15
20
 
16
21
  `datastore` -- FeatureCreep::RedisDatastore is provided with more to come.
@@ -25,8 +30,9 @@ The class constructor now takes
25
30
 
26
31
  `options[:features]` is an array of strings or symbols that will add to the list of all possible features.
27
32
 
28
- @feature_creep = FeatureCreep.new(@datastore,FeatureCreep::DefaultConfig.warden,
29
- FeatureCreep::DefaultConfig.info,
33
+ @feature_creep = FeatureCreep.new(FeatureCreep::RedisDataStore.new(Redis.new,"parent_namespace"),
34
+ FeatureCreep::SimpleStrategy.warden,
35
+ FeatureCreep::SimpleStrategy.info,
30
36
  {:scopes => {:some_scope_name => lambda { |agent_id| User.find(agent_id).can?(:some_scope) }}, :features => [:feature_1, :feature_2]})
31
37
 
32
38
  At this point it should be easy to extend.
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.add_development_dependency "bourne", "1.0"
28
28
  s.add_development_dependency "mocha", "0.9.8"
29
29
  s.add_development_dependency "pry", "0.9.10"
30
+ s.add_development_dependency "feature_creep-redis"
31
+ s.add_development_dependency "feature_creep-simple_strategy", "0.0.2"
30
32
 
31
- s.add_runtime_dependency "redis"
32
33
  end
@@ -1,3 +1,3 @@
1
1
  class FeatureCreep
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -3,12 +3,10 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe "FeatureCreep" do
4
4
  before do
5
5
  @datastore = FeatureCreep::RedisDataStore.new
6
- scopes = {
7
- :fivesonly => lambda { |agent_id| agent_id == 5 }
8
- }
9
- @feature_creep = FeatureCreep.new(@datastore,FeatureCreep::DefaultConfig.warden,
10
- FeatureCreep::DefaultConfig.info,
11
- {:scopes => scopes, :features => [:test1, :test2]})
6
+ @feature_creep = FeatureCreep.new(@datastore,FeatureCreep::SimpleStrategy.warden,
7
+ FeatureCreep::SimpleStrategy.info,
8
+ {:scopes => {:fivesonly => lambda { |agent_id| agent_id == 5 }},
9
+ :features => [:test1, :test2]})
12
10
  end
13
11
 
14
12
  describe ".new" do
@@ -1,14 +1,15 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- require 'feature_creep'
4
- require 'feature_creep/redis_datastore'
5
- require 'feature_creep/default_config'
3
+ require 'pry'
6
4
  require 'rspec'
7
5
  require 'bourne'
8
6
  require 'redis'
9
- require 'pry'
7
+ require 'feature_creep'
8
+ require 'feature_creep/redis_data_store'
9
+ require 'feature_creep/simple_strategy'
10
10
 
11
11
  RSpec.configure do |config|
12
12
  config.mock_with :mocha
13
+ # Redis Data Store
13
14
  config.before { Redis.new.flushdb }
14
15
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feature_creep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -108,14 +108,14 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: 0.9.10
110
110
  - !ruby/object:Gem::Dependency
111
- name: redis
111
+ name: feature_creep-redis
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements:
115
115
  - - ! '>='
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
- type: :runtime
118
+ type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  none: false
@@ -123,6 +123,22 @@ dependencies:
123
123
  - - ! '>='
124
124
  - !ruby/object:Gem::Version
125
125
  version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: feature_creep-simple_strategy
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - '='
132
+ - !ruby/object:Gem::Version
133
+ version: 0.0.2
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - '='
140
+ - !ruby/object:Gem::Version
141
+ version: 0.0.2
126
142
  description: Feature Flag implementation
127
143
  email:
128
144
  - xn@gotham.us
@@ -137,8 +153,6 @@ files:
137
153
  - README.md
138
154
  - feature_creep.gemspec
139
155
  - lib/feature_creep.rb
140
- - lib/feature_creep/default_config.rb
141
- - lib/feature_creep/redis_datastore.rb
142
156
  - lib/feature_creep/version.rb
143
157
  - spec/feature_creep_spec.rb
144
158
  - spec/spec.opts
@@ -1,36 +0,0 @@
1
- class FeatureCreep
2
- class DefaultConfig
3
- def self.info
4
- lambda { |creep,feature|
5
- if feature
6
- {
7
- :percentage => (creep.active_percentage(feature) || 0).to_i,
8
- :scopes => creep.active_scopes(feature).map { |g| g.to_sym },
9
- :agent_ids => creep.active_agent_ids(feature),
10
- :global => creep.active_global_features,
11
- :available_features => creep.features
12
- }
13
- else
14
- {
15
- :global => creep.active_global_features,
16
- :available_features => creep.features
17
- }
18
- end
19
- }
20
-
21
- end
22
-
23
- def self.warden
24
- lambda { |creep,feature,agent_id|
25
- if agent_id
26
- creep.active_globally?(feature) ||
27
- creep.agent_id_in_active_scope?(feature, agent_id) ||
28
- creep.agent_id_active?(feature, agent_id) ||
29
- creep.agent_id_within_active_percentage?(feature, agent_id)
30
- else
31
- creep.active_globally?(feature)
32
- end
33
- }
34
- end
35
- end
36
- end
@@ -1,116 +0,0 @@
1
- class FeatureCreep
2
- class RedisDataStore
3
-
4
- def initialize(datastore = nil, key_prefix = "feature_creep")
5
- @key_prefix = key_prefix
6
- @redis = datastore || Redis.new
7
- end
8
-
9
- # Activate Methods
10
- def activate_globally(feature)
11
- @redis.sadd(global_key, feature)
12
- end
13
-
14
- def activate_scope(feature, scope)
15
- @redis.sadd(scope_key(feature), scope)
16
- end
17
-
18
- def activate_agent_id(feature, agent_id)
19
- @redis.sadd(agent_id_key(feature), agent_id)
20
- end
21
-
22
- def activate_percentage(feature, percentage)
23
- @redis.set(percentage_key(feature), percentage)
24
- end
25
-
26
- # Deactivate Methods
27
- def deactivate_globally(feature)
28
- @redis.srem(global_key, feature)
29
- end
30
-
31
- def deactivate_scope(feature, scope)
32
- @redis.srem(scope_key(feature), scope)
33
- end
34
-
35
- def deactivate_agent_id(feature, agent_id)
36
- @redis.srem(agent_id_key(feature), agent_id)
37
- end
38
-
39
- def deactivate_percentage(feature)
40
- @redis.del(percentage_key(feature))
41
- end
42
-
43
- def deactivate_all(feature)
44
- @redis.del(scope_key(feature))
45
- @redis.del(agent_id_key(feature))
46
- @redis.del(percentage_key(feature))
47
- deactivate_globally(feature)
48
- end
49
-
50
- # Reporting Methods
51
- def active_global_features
52
- (@redis.smembers(global_key) || []).map(&:to_sym)
53
- end
54
-
55
- def active_scopes(feature)
56
- @redis.smembers(scope_key(feature)) || []
57
- end
58
-
59
- def active_agent_ids(feature)
60
- @redis.smembers(agent_id_key(feature))
61
- end
62
-
63
- def active_percentage(feature)
64
- @redis.get(percentage_key(feature))
65
- end
66
-
67
- # Boolean Methods
68
- def active_globally?(feature)
69
- @redis.sismember(global_key, feature)
70
- end
71
-
72
- def agent_id_active?(feature, agent_id)
73
- @redis.sismember(agent_id_key(feature), agent_id)
74
- end
75
-
76
- def agent_id_within_active_percentage?(feature, agent_id)
77
- percentage = active_percentage(feature)
78
- return false if percentage.nil?
79
- agent_id % 100 < percentage.to_i
80
- end
81
-
82
- # Utility Methods
83
- def features
84
- @redis.smembers(@key_prefix).map(&:to_sym)
85
- end
86
-
87
- def add_feature(feature)
88
- @redis.sadd(@key_prefix, feature)
89
- end
90
-
91
- def remove_feature(feature)
92
- @redis.srem(@key_prefix, feature)
93
- end
94
-
95
- private
96
- def key(name)
97
- "#{@key_prefix}:#{name}"
98
- end
99
-
100
- def scope_key(name)
101
- "#{key(name)}:scopes"
102
- end
103
-
104
- def agent_id_key(name)
105
- "#{key(name)}:agent_ids"
106
- end
107
-
108
- def percentage_key(name)
109
- "#{key(name)}:percentage"
110
- end
111
-
112
- def global_key
113
- "#{@key_prefix}:__global__"
114
- end
115
- end
116
- end