bastet 0.1.1 → 0.1.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/README.markdown +16 -4
- data/bastet.gemspec +2 -2
- data/lib/bastet/base.rb +13 -3
- data/lib/bastet/group.rb +2 -4
- data/lib/bastet/version.rb +1 -1
- data/spec/bastet/base_spec.rb +24 -0
- data/spec/bastet/group_spec.rb +8 -0
- metadata +14 -14
data/README.markdown
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Bastet - The
|
|
1
|
+
# Bastet - The criteria based feature rollout beast [](http://travis-ci.org/itsmeduncan/bastet)
|
|
2
2
|
|
|
3
3
|
## Gemfile
|
|
4
4
|
|
|
@@ -11,16 +11,30 @@
|
|
|
11
11
|
|
|
12
12
|
## Usage
|
|
13
13
|
|
|
14
|
+
### Activate
|
|
15
|
+
|
|
14
16
|
group = Bastet::Group.new('admin_users') { |user| user.admin? }
|
|
15
17
|
bastet.activate("admin_only_feature", group)
|
|
16
18
|
|
|
19
|
+
### Test
|
|
20
|
+
|
|
17
21
|
user = User.new(admin: true)
|
|
18
22
|
bastet.active?("admin_only_feature", user) #=> true
|
|
19
23
|
|
|
24
|
+
|
|
25
|
+
### Deactivate
|
|
26
|
+
|
|
20
27
|
bastet.deactivate("admin_only_feature", group)
|
|
21
28
|
bastet.inactive?("admin_only_feature", user) #=> true
|
|
22
29
|
|
|
23
|
-
|
|
30
|
+
### Criteria
|
|
31
|
+
|
|
32
|
+
Bastet::Group.new('all') { true } # true for everyone
|
|
33
|
+
Bastet::Group.new('none') { false } # false for everyone
|
|
34
|
+
Bastet::Group.new('admins') { |user| user.admin? } # True for entities that respond to #admin? with true
|
|
35
|
+
Bastet::Group.new('10_percent') { |user| (entity.id % 10) < (20 / 10) } # True for 20% of entities based on the id
|
|
36
|
+
|
|
37
|
+
## To Do
|
|
24
38
|
|
|
25
39
|
1. Support activating/deactivating for multiple users/groups at once
|
|
26
40
|
2. Percentage support
|
|
@@ -28,8 +42,6 @@
|
|
|
28
42
|
|
|
29
43
|
## Contibuting
|
|
30
44
|
|
|
31
|
-
[](http://travis-ci.org/itsmeduncan/bastet)
|
|
32
|
-
|
|
33
45
|
1. Fork Basteet
|
|
34
46
|
2. Create a topic branch - `git checkout -b my_branch`
|
|
35
47
|
3. Push to your branch - `git push origin my_branch`
|
data/bastet.gemspec
CHANGED
|
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
|
8
8
|
s.authors = ["Duncan Grazier"]
|
|
9
9
|
s.email = ["itsmeduncan@gmail.com"]
|
|
10
10
|
s.homepage = "https://github.com/itsmeduncan/bastet"
|
|
11
|
-
s.summary = %q{Simple feature rollout for
|
|
12
|
-
s.description = %q{Simple feature rollout for
|
|
11
|
+
s.summary = %q{Simple feature rollout for criteria based groups}
|
|
12
|
+
s.description = %q{Simple feature rollout for criteria based groups}
|
|
13
13
|
|
|
14
14
|
s.rubyforge_project = "bastet"
|
|
15
15
|
|
data/lib/bastet/base.rb
CHANGED
|
@@ -4,15 +4,15 @@ class Bastet::Base
|
|
|
4
4
|
include Singleton
|
|
5
5
|
|
|
6
6
|
def activate feature, group
|
|
7
|
-
|
|
7
|
+
act(:sadd, feature, group)
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def deactivate feature, group
|
|
11
|
-
|
|
11
|
+
act(:srem, feature, group)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def active? feature, entity
|
|
15
|
-
group_names = Bastet.redis.smembers(
|
|
15
|
+
group_names = Bastet.redis.smembers(feature_key(feature))
|
|
16
16
|
groups = Bastet.groups.select { |group| group_names.include?(group.name) }
|
|
17
17
|
groups.any? { |group| group.criteria.call(entity) }
|
|
18
18
|
end
|
|
@@ -20,4 +20,14 @@ class Bastet::Base
|
|
|
20
20
|
def inactive? feature, entity
|
|
21
21
|
!active? feature, entity
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def act method, feature, group
|
|
27
|
+
Bastet.redis.send(method, feature_key(feature), group.name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def feature_key feature
|
|
31
|
+
"feature_#{feature}"
|
|
32
|
+
end
|
|
23
33
|
end
|
data/lib/bastet/group.rb
CHANGED
|
@@ -16,16 +16,14 @@ class Bastet::Group
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def contains? entity
|
|
19
|
-
criteria.call(entity)
|
|
19
|
+
criteria.call(entity) rescue false
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
private
|
|
23
23
|
|
|
24
24
|
def validate_name! name
|
|
25
|
-
if Bastet.
|
|
25
|
+
if Bastet::Group.find(name)
|
|
26
26
|
raise ArgumentError.new("#{name} is already initialized as a group.")
|
|
27
|
-
else
|
|
28
|
-
Bastet.redis.sadd('bastet_groups', name)
|
|
29
27
|
end
|
|
30
28
|
end
|
|
31
29
|
|
data/lib/bastet/version.rb
CHANGED
data/spec/bastet/base_spec.rb
CHANGED
|
@@ -13,6 +13,23 @@ describe Bastet::Base do
|
|
|
13
13
|
@bastet.activate(:banana, group)
|
|
14
14
|
@bastet.active?(:banana, user).should be_true
|
|
15
15
|
end
|
|
16
|
+
|
|
17
|
+
describe "complex criteria" do
|
|
18
|
+
before do
|
|
19
|
+
@group = Bastet::Group.new("20_percent") { |entity| (entity.id % 10) < (20 / 10) }
|
|
20
|
+
@bastet.activate(:secret_feature, @group)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should be true for the user" do
|
|
24
|
+
user = mock('user', id: 20)
|
|
25
|
+
@bastet.active?(:secret_feature, user).should be_true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should be false for the user" do
|
|
29
|
+
user = mock('user', id: 19)
|
|
30
|
+
@bastet.active?(:secret_feature, user).should be_false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
16
33
|
end
|
|
17
34
|
|
|
18
35
|
describe "deactivate" do
|
|
@@ -27,4 +44,11 @@ describe Bastet::Base do
|
|
|
27
44
|
@bastet.inactive?(:banana, user).should be_true
|
|
28
45
|
end
|
|
29
46
|
end
|
|
47
|
+
|
|
48
|
+
describe "default to inactive" do
|
|
49
|
+
it "should default to inactive for new features" do
|
|
50
|
+
user = mock('user')
|
|
51
|
+
@bastet.active?(:unknown_feature, user).should be_false
|
|
52
|
+
end
|
|
53
|
+
end
|
|
30
54
|
end
|
data/spec/bastet/group_spec.rb
CHANGED
|
@@ -72,5 +72,13 @@ describe Bastet::Group do
|
|
|
72
72
|
group = Bastet::Group.new('none') { |entity| false }
|
|
73
73
|
group.contains?(mock).should be_false
|
|
74
74
|
end
|
|
75
|
+
|
|
76
|
+
it "should be false if the object doesn't respond to that criteria" do
|
|
77
|
+
fake = stub
|
|
78
|
+
fake.expects(:foo?).raises(NoMethodError)
|
|
79
|
+
|
|
80
|
+
group = Bastet::Group.new('foo') { |entity| entity.foo? }
|
|
81
|
+
group.contains?(fake).should be_false
|
|
82
|
+
end
|
|
75
83
|
end
|
|
76
84
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bastet
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2011-12-
|
|
12
|
+
date: 2011-12-07 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: rake
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &70284937960540 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ~>
|
|
@@ -21,10 +21,10 @@ dependencies:
|
|
|
21
21
|
version: 0.9.2.2
|
|
22
22
|
type: :development
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *70284937960540
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: rspec
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &70284937960040 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - ~>
|
|
@@ -32,10 +32,10 @@ dependencies:
|
|
|
32
32
|
version: 2.7.0
|
|
33
33
|
type: :development
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *70284937960040
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: mocha
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &70284937959580 !ruby/object:Gem::Requirement
|
|
39
39
|
none: false
|
|
40
40
|
requirements:
|
|
41
41
|
- - ~>
|
|
@@ -43,10 +43,10 @@ dependencies:
|
|
|
43
43
|
version: 0.10.0
|
|
44
44
|
type: :development
|
|
45
45
|
prerelease: false
|
|
46
|
-
version_requirements: *
|
|
46
|
+
version_requirements: *70284937959580
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: redis
|
|
49
|
-
requirement: &
|
|
49
|
+
requirement: &70284937959120 !ruby/object:Gem::Requirement
|
|
50
50
|
none: false
|
|
51
51
|
requirements:
|
|
52
52
|
- - ~>
|
|
@@ -54,10 +54,10 @@ dependencies:
|
|
|
54
54
|
version: 2.2.2
|
|
55
55
|
type: :development
|
|
56
56
|
prerelease: false
|
|
57
|
-
version_requirements: *
|
|
57
|
+
version_requirements: *70284937959120
|
|
58
58
|
- !ruby/object:Gem::Dependency
|
|
59
59
|
name: simplecov
|
|
60
|
-
requirement: &
|
|
60
|
+
requirement: &70284937958660 !ruby/object:Gem::Requirement
|
|
61
61
|
none: false
|
|
62
62
|
requirements:
|
|
63
63
|
- - ! '>='
|
|
@@ -65,8 +65,8 @@ dependencies:
|
|
|
65
65
|
version: '0'
|
|
66
66
|
type: :development
|
|
67
67
|
prerelease: false
|
|
68
|
-
version_requirements: *
|
|
69
|
-
description: Simple feature rollout for
|
|
68
|
+
version_requirements: *70284937958660
|
|
69
|
+
description: Simple feature rollout for criteria based groups
|
|
70
70
|
email:
|
|
71
71
|
- itsmeduncan@gmail.com
|
|
72
72
|
executables: []
|
|
@@ -113,7 +113,7 @@ rubyforge_project: bastet
|
|
|
113
113
|
rubygems_version: 1.8.10
|
|
114
114
|
signing_key:
|
|
115
115
|
specification_version: 3
|
|
116
|
-
summary: Simple feature rollout for
|
|
116
|
+
summary: Simple feature rollout for criteria based groups
|
|
117
117
|
test_files:
|
|
118
118
|
- spec/bastet/base_spec.rb
|
|
119
119
|
- spec/bastet/group_spec.rb
|