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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YWY3YjRjMGU0YmZlNDljMWM5YTNjYTllZmQ3MDljZTU2NDE0NTVkZA==
4
+ MDk3OGYyZmJlYmFlNWMwM2EzOGE5YjY4MmI2ZGVhNTQ3N2JiM2E0Nw==
5
5
  data.tar.gz: !binary |-
6
- MjUzZTE3MjY4MDFmY2MxZjE0YWIwZmViYTk4NjNkZjUwMTlkYTE3NA==
6
+ Y2ZjNmQ0MGQ0NjllZTFiNjE3ZGQwYjZhNmUzMGYxNzg1NDU5ZWE4Yg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZTE1ZWM5ODgzZDM5NTA1MTllZGEyYTg3OWViYzAzOGE4YmZhMjFmYzg1NTZh
10
- ZTkwOWQ0ODhhMzE3ZTI0YzIxMWQyYjI1MmFhN2ZjZWZmYjZhYmVhZGE5N2Mx
11
- YWQzYWVkMzRkMTkxNTg1ODVhZDJmZGIzMWI3ODc0YmFjNjU2NTE=
9
+ ZWE3NTY1ZTk2YWQ5MmY5ZTMyMjE5YWM0ODg1NjYyYTU2ZjQ5M2JiMTI0ZWU5
10
+ Mzk4ZjBmZWY3YmU0YTQ5ZjQyMjI1ZWQ4NTA1NmE0M2U5ODkyZDQyMDFjNGFk
11
+ NjJmN2NiMjg4MTA1Y2M3MmNiYWUyZjI2MWRiZjY5Y2UyNTcxNDc=
12
12
  data.tar.gz: !binary |-
13
- ZWI4YTJhZTg5ZWQ4NWI0ZDRmNWU4MDVmYTc2MzYyN2NmZjA3Mjg5YjVmNGE0
14
- Nzg3YWJiMDY0MjBmMjljNjIyZDAzYzhlZmQwY2E2NTAxZDVlODJmNTMwZTY1
15
- MGJlNzVlYTE3ZmE1ZDc3MjhkY2E0ZGQ1YjgyNWRjY2MzMjgzOWI=
13
+ Mjk0MTBmYzVlNmQ2NWY5ZGM2MWY3ODkwOTYwYzMxMDIxN2FkMGRlOTQ0Nzg0
14
+ NzE3MjM3MzhlMmNiZmE4M2Y1MzA2ZTBhZWMyMTQ3MjI5YjI5YmMyNzdjZWNl
15
+ ZjczYWQ5ZGNlNTMwODY1N2M0ZmU3NjkwNzQ5ODk0NGFhOGI0ZGQ=
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Flipflop
2
- VERSION = "2.1.0"
2
+ VERSION = "2.2.0"
3
3
  end
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
@@ -27,7 +27,7 @@ describe Flipflop::Strategies::AbstractStrategy do
27
27
  end
28
28
 
29
29
  it "should have unique key" do
30
- assert_match /^\d+$/, subject.key
30
+ assert_match /^\w+$/, subject.key
31
31
  end
32
32
 
33
33
  describe "request" do
@@ -56,7 +56,7 @@ describe Flipflop::Strategies::ActiveRecordStrategy do
56
56
  end
57
57
 
58
58
  it "should have unique key" do
59
- assert_match /^\d+$/, subject.key
59
+ assert_match /^\w+$/, subject.key
60
60
  end
61
61
 
62
62
  describe "with enabled feature" do
@@ -28,7 +28,7 @@ describe Flipflop::Strategies::CookieStrategy do
28
28
  end
29
29
 
30
30
  it "should have unique key" do
31
- assert_match /^\d+$/, subject.key
31
+ assert_match /^\w+$/, subject.key
32
32
  end
33
33
 
34
34
  describe "with enabled feature" do
@@ -26,7 +26,7 @@ describe Flipflop::Strategies::DefaultStrategy do
26
26
  end
27
27
 
28
28
  it "should have unique key" do
29
- assert_match /^\d+$/, subject.key
29
+ assert_match /^\w+$/, subject.key
30
30
  end
31
31
 
32
32
  describe "with explicitly defaulted feature" do
@@ -20,7 +20,7 @@ describe Flipflop::Strategies::LambdaStrategy do
20
20
  end
21
21
 
22
22
  it "should have unique key" do
23
- assert_match /^\d+$/, subject.key
23
+ assert_match /^\w+$/, subject.key
24
24
  end
25
25
  end
26
26
 
@@ -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
@@ -28,7 +28,7 @@ describe Flipflop::Strategies::QueryStringStrategy do
28
28
  end
29
29
 
30
30
  it "should have unique key" do
31
- assert_match /^\d+$/, subject.key
31
+ assert_match /^\w+$/, subject.key
32
32
  end
33
33
 
34
34
  describe "with enabled feature" do
@@ -28,7 +28,7 @@ describe Flipflop::Strategies::SessionStrategy do
28
28
  end
29
29
 
30
30
  it "should have unique key" do
31
- assert_match /^\d+$/, subject.key
31
+ assert_match /^\w+$/, subject.key
32
32
  end
33
33
 
34
34
  describe "with enabled feature" do
@@ -19,7 +19,7 @@ describe Flipflop::Strategies::TestStrategy do
19
19
  end
20
20
 
21
21
  it "should have unique key" do
22
- assert_match /^\d+$/, subject.key
22
+ assert_match /^\w+$/, subject.key
23
23
  end
24
24
 
25
25
  describe "with enabled feature" do
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.1.0
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