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.
@@ -21,4 +21,5 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.5"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "mock_redis"
24
25
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  class FeatureRelease
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  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
@@ -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
@@ -1,6 +1,7 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'feature_release.rb'
4
+ require 'mock_redis'
4
5
 
5
6
  RSpec.configure do |config|
6
7
  config.treat_symbols_as_metadata_keys_with_true_values = true
@@ -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.1
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-07 00:00:00.000000000 Z
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: 4375904973404869369
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: 4375904973404869369
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