flipflop 2.1.0 → 2.2.0
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.
- 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
|