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 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