feature_release 0.0.1 → 0.0.2
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/feature_release.gemspec +1 -0
- data/lib/feature_release.rb +20 -1
- data/lib/feature_release/feature.rb +13 -1
- data/lib/feature_release/storage.rb +42 -0
- data/lib/feature_release/version.rb +1 -1
- data/spec/feature_release_spec.rb +34 -0
- data/spec/feature_spec.rb +16 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/storage_spec.rb +34 -0
- metadata +23 -4
data/feature_release.gemspec
CHANGED
data/lib/feature_release.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
require "feature_release/version"
|
2
2
|
require "feature_release/feature"
|
3
|
+
require "feature_release/storage"
|
3
4
|
|
4
5
|
class FeatureRelease
|
5
6
|
|
6
7
|
attr_reader :groups, :features
|
7
8
|
|
8
|
-
def initialize
|
9
|
+
def initialize(storage=nil)
|
9
10
|
@groups = {:all => lambda{|obj| true}}
|
10
11
|
@features = Hash.new do |hash, missing_key|
|
11
12
|
hash[missing_key] = Feature.new(missing_key)
|
12
13
|
end
|
14
|
+
set_storage(storage) if storage
|
13
15
|
end
|
14
16
|
|
15
17
|
def define_group(name, &block)
|
@@ -29,4 +31,21 @@ class FeatureRelease
|
|
29
31
|
@features[feature.to_sym].groups.all? {|group| groups[group].call(user)}
|
30
32
|
end
|
31
33
|
|
34
|
+
def persisted?(feature)
|
35
|
+
!(@storage.get(@features[feature.to_sym].name).nil?)
|
36
|
+
end
|
37
|
+
|
38
|
+
def save
|
39
|
+
@features.each{|key, value| @storage.save(value.name, value.to_string)}
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def set_storage(storage)
|
45
|
+
@storage = storage
|
46
|
+
@storage.get_all.each do |feature_name|
|
47
|
+
@features[feature_name.to_sym] = Feature.new(feature_name, @storage.get(feature_name))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
32
51
|
end
|
@@ -3,10 +3,12 @@ class FeatureRelease
|
|
3
3
|
class Feature
|
4
4
|
|
5
5
|
attr_accessor :groups
|
6
|
+
attr_reader :name
|
6
7
|
|
7
|
-
def initialize(name)
|
8
|
+
def initialize(name, groups_string=nil)
|
8
9
|
@name = name
|
9
10
|
@groups = []
|
11
|
+
parse_groups(groups_string)
|
10
12
|
end
|
11
13
|
|
12
14
|
def add_group(group)
|
@@ -17,6 +19,16 @@ class FeatureRelease
|
|
17
19
|
@groups.delete(group.to_sym)
|
18
20
|
end
|
19
21
|
|
22
|
+
def to_string
|
23
|
+
@groups.join(",")
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def parse_groups(string)
|
28
|
+
return unless string
|
29
|
+
@groups = string.split(",").map(&:to_sym)
|
30
|
+
end
|
31
|
+
|
20
32
|
end
|
21
33
|
|
22
34
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
class FeatureRelease
|
3
|
+
class Storage
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@store = options.fetch(:store)
|
7
|
+
end
|
8
|
+
|
9
|
+
def save(feature, data)
|
10
|
+
persist(feature, data)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(feature)
|
14
|
+
retrieve(feature_key(feature))
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_all
|
18
|
+
(retrieve(global_key) || "").split(",").map(&:to_sym)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def feature_key(feature)
|
25
|
+
"feature:#{feature}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def global_key
|
29
|
+
"features:all"
|
30
|
+
end
|
31
|
+
|
32
|
+
def persist(feature, data)
|
33
|
+
@store.set(feature_key(feature), data)
|
34
|
+
@store.set(global_key, (get_all | [feature]).join(","))
|
35
|
+
end
|
36
|
+
|
37
|
+
def retrieve(key)
|
38
|
+
@store.get(key)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -57,4 +57,38 @@ describe FeatureRelease do
|
|
57
57
|
|
58
58
|
end
|
59
59
|
|
60
|
+
context "persistence" do
|
61
|
+
let(:tester) {double("user", :new? => true, :admin? => false)}
|
62
|
+
let(:admin) {double("user", :admin? => true, :new? => false)}
|
63
|
+
|
64
|
+
before(:each) do
|
65
|
+
@redis = MockRedis.new
|
66
|
+
@storage = FeatureRelease::Storage.new(store:@redis)
|
67
|
+
@fr = FeatureRelease.new(@storage)
|
68
|
+
@fr.define_group(:testers) do |user|
|
69
|
+
user.new?
|
70
|
+
end
|
71
|
+
@fr.activate_feature(:test_feature, :testers)
|
72
|
+
@fr.define_group(:admins) do |user|
|
73
|
+
user.admin?
|
74
|
+
end
|
75
|
+
@fr.activate_feature(:new_feature, :admins)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "commands its storage object to save the features" do
|
79
|
+
@fr.save
|
80
|
+
@fr.persisted?(:test_feature).should be_true
|
81
|
+
end
|
82
|
+
|
83
|
+
it "can build itself from persisted date" do
|
84
|
+
@fr.save
|
85
|
+
@new_fr = FeatureRelease.new(@storage)
|
86
|
+
@new_fr.define_group(:admins) do |user|
|
87
|
+
user.admin?
|
88
|
+
end
|
89
|
+
@new_fr.active?(:new_feature, admin).should be_true
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
60
94
|
end
|
data/spec/feature_spec.rb
CHANGED
@@ -23,5 +23,21 @@ describe FeatureRelease::Feature do
|
|
23
23
|
f.remove_group(:testers)
|
24
24
|
f.groups.should_not include(:testers)
|
25
25
|
end
|
26
|
+
|
27
|
+
it "can be to_string into a string" do
|
28
|
+
f = FeatureRelease::Feature.new(:test_feature)
|
29
|
+
f.add_group(:testers)
|
30
|
+
f.add_group(:admins)
|
31
|
+
f.to_string.should eq("testers,admins")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can be built from a string" do
|
35
|
+
f = FeatureRelease::Feature.new(:test_feature)
|
36
|
+
f.add_group(:testers)
|
37
|
+
f.add_group(:admins)
|
38
|
+
string = f.to_string
|
39
|
+
from_s = FeatureRelease::Feature.new(:test_feature, string)
|
40
|
+
from_s.groups.should eq([:testers, :admins])
|
41
|
+
end
|
26
42
|
|
27
43
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FeatureRelease::Storage do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@redis = MockRedis.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should initialize with a store" do
|
10
|
+
expect{FeatureRelease::Storage.new()}.to raise_error
|
11
|
+
expect{FeatureRelease::Storage.new(store: @redis)}.to_not raise_error
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'saving features' do
|
15
|
+
|
16
|
+
before(:each) do
|
17
|
+
@storage = FeatureRelease::Storage.new(store: @redis)
|
18
|
+
@feature = double 'Feature', name: :test_feature, to_string: "test_users, new_users, admin_users"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should save a feature to the store" do
|
22
|
+
@storage.save(@feature.name, @feature.to_string)
|
23
|
+
@storage.get(@feature.name).should eq(@feature.to_string)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should add a feature to the collection of features" do
|
27
|
+
@storage = FeatureRelease::Storage.new(store: @redis)
|
28
|
+
@storage.save(@feature.name, @feature.to_string)
|
29
|
+
@storage.get_all.should eq([:test_feature])
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feature_release
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-05-
|
12
|
+
date: 2014-05-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -59,6 +59,22 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: mock_redis
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
62
78
|
description: Allows you to restrict access of portions of an app to certain users
|
63
79
|
email:
|
64
80
|
- kavinderd@gmail.com
|
@@ -75,10 +91,12 @@ files:
|
|
75
91
|
- feature_release.gemspec
|
76
92
|
- lib/feature_release.rb
|
77
93
|
- lib/feature_release/feature.rb
|
94
|
+
- lib/feature_release/storage.rb
|
78
95
|
- lib/feature_release/version.rb
|
79
96
|
- spec/feature_release_spec.rb
|
80
97
|
- spec/feature_spec.rb
|
81
98
|
- spec/spec_helper.rb
|
99
|
+
- spec/storage_spec.rb
|
82
100
|
homepage: ''
|
83
101
|
licenses:
|
84
102
|
- MIT
|
@@ -94,7 +112,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
112
|
version: '0'
|
95
113
|
segments:
|
96
114
|
- 0
|
97
|
-
hash:
|
115
|
+
hash: -1008631629134333472
|
98
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
117
|
none: false
|
100
118
|
requirements:
|
@@ -103,7 +121,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
121
|
version: '0'
|
104
122
|
segments:
|
105
123
|
- 0
|
106
|
-
hash:
|
124
|
+
hash: -1008631629134333472
|
107
125
|
requirements: []
|
108
126
|
rubyforge_project:
|
109
127
|
rubygems_version: 1.8.25
|
@@ -114,3 +132,4 @@ test_files:
|
|
114
132
|
- spec/feature_release_spec.rb
|
115
133
|
- spec/feature_spec.rb
|
116
134
|
- spec/spec_helper.rb
|
135
|
+
- spec/storage_spec.rb
|