flipflop 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/flipflop/feature_set.rb +6 -0
- data/lib/flipflop/strategies/abstract_strategy.rb +6 -7
- data/lib/flipflop/strategies/options_hasher.rb +21 -0
- data/lib/flipflop/version.rb +1 -1
- data/lib/flipflop.rb +2 -0
- data/test/unit/feature_set_test.rb +28 -0
- data/test/unit/strategies/abstract_strategy_test.rb +1 -1
- data/test/unit/strategies/active_record_strategy_test.rb +1 -1
- data/test/unit/strategies/cookie_strategy_test.rb +1 -1
- data/test/unit/strategies/default_strategy_test.rb +1 -1
- data/test/unit/strategies/lambda_strategy_test.rb +1 -1
- data/test/unit/strategies/options_hasher_test.rb +85 -0
- data/test/unit/strategies/query_string_strategy_test.rb +1 -1
- data/test/unit/strategies/session_strategy_test.rb +1 -1
- data/test/unit/strategies/test_strategy_test.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDk3OGYyZmJlYmFlNWMwM2EzOGE5YjY4MmI2ZGVhNTQ3N2JiM2E0Nw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
Y2ZjNmQ0MGQ0NjllZTFiNjE3ZGQwYjZhNmUzMGYxNzg1NDU5ZWE4Yg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZWE3NTY1ZTk2YWQ5MmY5ZTMyMjE5YWM0ODg1NjYyYTU2ZjQ5M2JiMTI0ZWU5
|
10
|
+
Mzk4ZjBmZWY3YmU0YTQ5ZjQyMjI1ZWQ4NTA1NmE0M2U5ODkyZDQyMDFjNGFk
|
11
|
+
NjJmN2NiMjg4MTA1Y2M3MmNiYWUyZjI2MWRiZjY5Y2UyNTcxNDc=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Mjk0MTBmYzVlNmQ2NWY5ZGM2MWY3ODkwOTYwYzMxMDIxN2FkMGRlOTQ0Nzg0
|
14
|
+
NzE3MjM3MzhlMmNiZmE4M2Y1MzA2ZTBhZWMyMTQ3MjI5YjI5YmMyNzdjZWNl
|
15
|
+
ZjczYWQ5ZGNlNTMwODY1N2M0ZmU3NjkwNzQ5ODk0NGFhOGI0ZGQ=
|
data/lib/flipflop/feature_set.rb
CHANGED
@@ -56,12 +56,18 @@ module Flipflop
|
|
56
56
|
|
57
57
|
def add(feature)
|
58
58
|
@@lock.synchronize do
|
59
|
+
if @features.has_key?(feature.key)
|
60
|
+
raise FeatureError.new(feature.key, "already defined")
|
61
|
+
end
|
59
62
|
@features[feature.key] = feature.freeze
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
63
66
|
def use(strategy)
|
64
67
|
@@lock.synchronize do
|
68
|
+
if @strategies.has_key?(strategy.key)
|
69
|
+
raise StrategyError.new(strategy.name, "(#{strategy.class}) already defined with identical options")
|
70
|
+
end
|
65
71
|
@strategies[strategy.key] = strategy.freeze
|
66
72
|
end
|
67
73
|
end
|
@@ -35,12 +35,17 @@ module Flipflop
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
attr_reader :name, :description
|
38
|
+
attr_reader :key, :name, :description
|
39
39
|
|
40
40
|
def initialize(**options)
|
41
|
+
# Generate key before setting instance that should be excluded from
|
42
|
+
# unique key generation.
|
43
|
+
@key = OptionsHasher.new(self).generate
|
44
|
+
|
41
45
|
@name = (options.delete(:name) || self.class.default_name).freeze
|
42
46
|
@description = (options.delete(:description) || self.class.default_description).freeze
|
43
47
|
@hidden = !!options.delete(:hidden) || false
|
48
|
+
|
44
49
|
if options.any?
|
45
50
|
raise StrategyError.new(name, "did not understand option #{options.keys.map(&:inspect) * ', '}")
|
46
51
|
end
|
@@ -50,12 +55,6 @@ module Flipflop
|
|
50
55
|
@hidden
|
51
56
|
end
|
52
57
|
|
53
|
-
def key
|
54
|
-
# TODO: Object ID changes if the feature definitions are reloaded. Maybe
|
55
|
-
# we can use the index instead?
|
56
|
-
object_id.to_s
|
57
|
-
end
|
58
|
-
|
59
58
|
# Return true iff this strategy is able to switch features on/off.
|
60
59
|
# Return false otherwise.
|
61
60
|
def switchable?
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
|
3
|
+
module Flipflop
|
4
|
+
module Strategies
|
5
|
+
class OptionsHasher
|
6
|
+
def initialize(value)
|
7
|
+
@hasher = Digest::MD5.new
|
8
|
+
@value = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def generate
|
12
|
+
@hasher << begin
|
13
|
+
Marshal.dump(@value)
|
14
|
+
rescue TypeError
|
15
|
+
@value.object_id.to_s
|
16
|
+
end
|
17
|
+
@hasher.hexdigest
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/flipflop/version.rb
CHANGED
data/lib/flipflop.rb
CHANGED
@@ -11,6 +11,8 @@ require "flipflop/feature_definition"
|
|
11
11
|
require "flipflop/feature_set"
|
12
12
|
|
13
13
|
require "flipflop/strategies/abstract_strategy"
|
14
|
+
require "flipflop/strategies/options_hasher"
|
15
|
+
|
14
16
|
require "flipflop/strategies/active_record_strategy"
|
15
17
|
require "flipflop/strategies/cookie_strategy"
|
16
18
|
require "flipflop/strategies/default_strategy"
|
@@ -104,6 +104,20 @@ describe Flipflop::FeatureSet do
|
|
104
104
|
subject.add(feature = Flipflop::FeatureDefinition.new(:feature))
|
105
105
|
assert subject.feature(feature.key).frozen?
|
106
106
|
end
|
107
|
+
|
108
|
+
it "should raise if feature with same key is added" do
|
109
|
+
subject.add(Flipflop::FeatureDefinition.new(:feature))
|
110
|
+
assert_raises Flipflop::FeatureError do
|
111
|
+
subject.add(Flipflop::FeatureDefinition.new(:feature))
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should raise with message if feature with same key is added" do
|
116
|
+
subject.add(Flipflop::FeatureDefinition.new(:feature))
|
117
|
+
assert_raises Flipflop::FeatureError do
|
118
|
+
subject.add(Flipflop::FeatureDefinition.new(:feature))
|
119
|
+
end
|
120
|
+
end
|
107
121
|
end
|
108
122
|
|
109
123
|
describe "use" do
|
@@ -116,6 +130,20 @@ describe Flipflop::FeatureSet do
|
|
116
130
|
subject.use(strategy = NullStrategy.new)
|
117
131
|
assert subject.strategy(strategy.key).frozen?
|
118
132
|
end
|
133
|
+
|
134
|
+
it "should raise if strategy with same key is added" do
|
135
|
+
subject.use(NullStrategy.new)
|
136
|
+
assert_raises Flipflop::StrategyError do
|
137
|
+
subject.use(NullStrategy.new)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should raise with message if strategy with same key is added" do
|
142
|
+
subject.use(NullStrategy.new)
|
143
|
+
assert_raises Flipflop::StrategyError do
|
144
|
+
subject.use(NullStrategy.new)
|
145
|
+
end
|
146
|
+
end
|
119
147
|
end
|
120
148
|
|
121
149
|
describe "feature" do
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.expand_path("../../../test_helper", __FILE__)
|
2
|
+
|
3
|
+
class Test
|
4
|
+
def initialize(value)
|
5
|
+
@value = value
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Test2
|
10
|
+
def initialize(value)
|
11
|
+
@value = value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Flipflop::Strategies::OptionsHasher do
|
16
|
+
subject do
|
17
|
+
Flipflop::Strategies::OptionsHasher
|
18
|
+
end
|
19
|
+
|
20
|
+
def hash(value)
|
21
|
+
subject.new(value).generate
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "with nil" do
|
25
|
+
it "should generate stable hash" do
|
26
|
+
assert_equal hash(nil), hash(nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "with boolean" do
|
31
|
+
it "should generate unique hash" do
|
32
|
+
refute_equal hash(true), hash(false)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should generate stable hash" do
|
36
|
+
assert_equal hash(false), hash(false)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "with fixnum" do
|
41
|
+
it "should generate unique hash" do
|
42
|
+
refute_equal hash(1), hash(2)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should generate stable hash" do
|
46
|
+
assert_equal hash(2), hash(2)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "with hash" do
|
51
|
+
it "should generate unique hash" do
|
52
|
+
refute_equal hash(foo: 3), hash(bar: 3)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should generate stable hash" do
|
56
|
+
assert_equal hash(foo: 3), hash(foo: 3)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "with array" do
|
61
|
+
it "should generate unique hash" do
|
62
|
+
refute_equal hash([1, 2]), hash([1, 2, 3])
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should generate stable hash" do
|
66
|
+
assert_equal hash([1, 2, 3]), hash([1, 2, 3])
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "with object" do
|
71
|
+
it "should generate unique hash" do
|
72
|
+
refute_equal hash(Test.new([1, 2])), hash(Test.new([1, 2, 3]))
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should generate stable hash" do
|
76
|
+
assert_equal hash(Test.new([1, 2, 3])), hash(Test.new([1, 2, 3]))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "with similar object of different class" do
|
81
|
+
it "should generate unique hash" do
|
82
|
+
refute_equal hash(Test.new([1, 2, 3])), hash(Test2.new([1, 2, 3]))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipflop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Annesley
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- lib/flipflop/strategies/cookie_strategy.rb
|
64
64
|
- lib/flipflop/strategies/default_strategy.rb
|
65
65
|
- lib/flipflop/strategies/lambda_strategy.rb
|
66
|
+
- lib/flipflop/strategies/options_hasher.rb
|
66
67
|
- lib/flipflop/strategies/query_string_strategy.rb
|
67
68
|
- lib/flipflop/strategies/session_strategy.rb
|
68
69
|
- lib/flipflop/strategies/test_strategy.rb
|
@@ -90,6 +91,7 @@ files:
|
|
90
91
|
- test/unit/strategies/cookie_strategy_test.rb
|
91
92
|
- test/unit/strategies/default_strategy_test.rb
|
92
93
|
- test/unit/strategies/lambda_strategy_test.rb
|
94
|
+
- test/unit/strategies/options_hasher_test.rb
|
93
95
|
- test/unit/strategies/query_string_strategy_test.rb
|
94
96
|
- test/unit/strategies/session_strategy_test.rb
|
95
97
|
- test/unit/strategies/test_strategy_test.rb
|