flipper 0.11.0.beta9 → 0.11.0.rc1

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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82cc5ffd7d40e3b8930038e06718a378e22d5798
4
- data.tar.gz: 5cbc699f683fa1ee88efc46aff9577220ff63ac1
3
+ metadata.gz: 7fe7a64b6dfb6cbefeb2f111e3ea777018016ff5
4
+ data.tar.gz: 3c8e8754b21fdc37f9f90772ca893a0e16931f33
5
5
  SHA512:
6
- metadata.gz: acebdb682fce4b45c99267ef345e9eec161b7421ac957248445e235a7ebde7d2fd3a6181f2d5e2cc362c69ecf5637cfede638cbba49233e8658895b801a5140f
7
- data.tar.gz: 239a7733640400443d7adb7c4d745257eadbe61dd791330235728296395ff365292f9570a15f1994d054c08374486fbc85cc7fe65ee5ba4c99e01ae0c4804b1d
6
+ metadata.gz: 63863f70f3b8499f2d6f802eb6cfe20e19c84fad799c8b27d92de31b0ffba968f623b2dad4c387b9fe55c974d83a82f58253e8d683badac9ab9a4c084cafc216
7
+ data.tar.gz: 27f0085cfd6865a80dcd2722f81e2b516d3cd67b9702999fb90737cce263f6dd2afe5e013cbf470a6522447e70df7748f692b28cb1b7ca3a2e2ccf7e4cea4e42
data/.rubocop.yml CHANGED
@@ -40,3 +40,6 @@ Style/TrailingCommaInLiteral:
40
40
 
41
41
  RSpec/InstanceVariable:
42
42
  Enabled: false
43
+
44
+ Style/AccessorMethodName:
45
+ Enabled: false
data/Gemfile CHANGED
@@ -13,7 +13,7 @@ gem 'statsd-ruby', '~> 1.2.1'
13
13
  gem 'rspec', '~> 3.0'
14
14
  gem 'rack-test', '~> 0.6.3'
15
15
  gem 'sqlite3', '~> 1.3.11'
16
- gem 'rails', "~> #{ENV['RAILS_VERSION'] || '4.2.5'}"
16
+ gem 'rails', "~> #{ENV['RAILS_VERSION'] || '5.1.4'}"
17
17
  gem 'minitest', '~> 5.8.0'
18
18
  gem 'rubocop', '~> 0.45.0'
19
19
  gem 'rubocop-rspec', '= 1.5.1'
@@ -1,17 +1,9 @@
1
1
  require File.expand_path('../example_setup', __FILE__)
2
-
2
+ require_relative 'active_record/ar_setup'
3
3
  require 'flipper'
4
4
  require 'flipper/adapters/redis'
5
5
  require 'flipper/adapters/active_record'
6
6
 
7
- # Active Record boiler plate, feel free to ignore.
8
- ActiveRecord::Base.establish_connection({
9
- adapter: 'sqlite3',
10
- database: ':memory:',
11
- })
12
- require 'generators/flipper/templates/migration'
13
- CreateFlipperTables.up
14
-
15
7
  # Say you are using redis...
16
8
  redis_adapter = Flipper::Adapters::Redis.new(Redis.new)
17
9
  redis_flipper = Flipper.new(redis_adapter)
@@ -9,6 +9,7 @@ module Flipper
9
9
  include ::Flipper::Adapter
10
10
 
11
11
  FeaturesKey = :flipper_features
12
+ GetAllKey = :all_memoized
12
13
 
13
14
  # Internal
14
15
  attr_reader :cache
@@ -19,6 +20,11 @@ module Flipper
19
20
  # Internal: The adapter this adapter is wrapping.
20
21
  attr_reader :adapter
21
22
 
23
+ # Private
24
+ def self.key_for(key)
25
+ "feature/#{key}"
26
+ end
27
+
22
28
  # Public
23
29
  def initialize(adapter, cache = nil)
24
30
  super(adapter)
@@ -26,7 +32,6 @@ module Flipper
26
32
  @name = :memoizable
27
33
  @cache = cache || {}
28
34
  @memoize = false
29
- @all_fetched = false
30
35
  end
31
36
 
32
37
  # Public
@@ -63,7 +68,7 @@ module Flipper
63
68
  # Public
64
69
  def get(feature)
65
70
  if memoizing?
66
- cache.fetch(feature.key) { cache[feature.key] = @adapter.get(feature) }
71
+ cache.fetch(key_for(feature.key)) { cache[key_for(feature.key)] = @adapter.get(feature) }
67
72
  else
68
73
  @adapter.get(feature)
69
74
  end
@@ -72,18 +77,18 @@ module Flipper
72
77
  # Public
73
78
  def get_multi(features)
74
79
  if memoizing?
75
- uncached_features = features.reject { |feature| cache[feature.key] }
80
+ uncached_features = features.reject { |feature| cache[key_for(feature.key)] }
76
81
 
77
82
  if uncached_features.any?
78
83
  response = @adapter.get_multi(uncached_features)
79
84
  response.each do |key, hash|
80
- cache[key] = hash
85
+ cache[key_for(key)] = hash
81
86
  end
82
87
  end
83
88
 
84
89
  result = {}
85
90
  features.each do |feature|
86
- result[feature.key] = cache[feature.key]
91
+ result[feature.key] = cache[key_for(feature.key)]
87
92
  end
88
93
  result
89
94
  else
@@ -93,20 +98,25 @@ module Flipper
93
98
 
94
99
  def get_all
95
100
  if memoizing?
96
- unless @all_fetched
97
- result = @adapter.get_all
98
- result.each do |key, value|
99
- cache[key] = value
101
+ response = nil
102
+ if cache[GetAllKey]
103
+ response = {}
104
+ cache[FeaturesKey].each do |key|
105
+ response[key] = cache[key_for(key)]
100
106
  end
101
- cache[FeaturesKey] = result.keys.to_set
102
- @all_fetched = true
107
+ else
108
+ response = @adapter.get_all
109
+ response.each do |key, value|
110
+ cache[key_for(key)] = value
111
+ end
112
+ cache[FeaturesKey] = response.keys.to_set
113
+ cache[GetAllKey] = true
103
114
  end
104
115
 
105
- result = {}
106
- features.each do |key|
107
- result[key] = cache[key]
108
- end
109
- result
116
+ # Ensures that looking up other features that do not exist doesn't
117
+ # result in N+1 adapter calls.
118
+ response.default_proc = ->(memo, key) { memo[key] = default_config }
119
+ response
110
120
  else
111
121
  @adapter.get_all
112
122
  end
@@ -130,7 +140,6 @@ module Flipper
130
140
  #
131
141
  # value - The Boolean that decides if local caching is on.
132
142
  def memoize=(value)
133
- @all_fetched = false
134
143
  cache.clear
135
144
  @memoize = value
136
145
  end
@@ -142,8 +151,12 @@ module Flipper
142
151
 
143
152
  private
144
153
 
154
+ def key_for(key)
155
+ self.class.key_for(key)
156
+ end
157
+
145
158
  def expire_feature(feature)
146
- cache.delete(feature.key) if memoizing?
159
+ cache.delete(key_for(feature.key)) if memoizing?
147
160
  end
148
161
 
149
162
  def expire_features_set
@@ -7,7 +7,7 @@ module Flipper
7
7
  class Memory
8
8
  include ::Flipper::Adapter
9
9
 
10
- FeaturesKey = :flipper_features
10
+ FeaturesKey = :features
11
11
 
12
12
  # Public: The name of the adapter.
13
13
  attr_reader :name
@@ -20,7 +20,7 @@ module Flipper
20
20
 
21
21
  # Public: The set of known features.
22
22
  def features
23
- set_members(FeaturesKey)
23
+ read_feature_keys
24
24
  end
25
25
 
26
26
  # Public: Adds a feature to the set of known features.
@@ -47,21 +47,19 @@ module Flipper
47
47
 
48
48
  # Public
49
49
  def get(feature)
50
- result = {}
50
+ read_feature(feature)
51
+ end
51
52
 
52
- feature.gates.each do |gate|
53
- result[gate.key] =
54
- case gate.data_type
55
- when :boolean, :integer
56
- read key(feature, gate)
57
- when :set
58
- set_members key(feature, gate)
59
- else
60
- raise "#{gate} is not supported by this adapter yet"
61
- end
53
+ def get_multi(features)
54
+ read_many_features(features)
55
+ end
56
+
57
+ def get_all
58
+ features = read_feature_keys.map do |key|
59
+ Flipper::Feature.new(key, self)
62
60
  end
63
61
 
64
- result
62
+ read_many_features(features)
65
63
  end
66
64
 
67
65
  # Public
@@ -103,9 +101,41 @@ module Flipper
103
101
  "#<#{self.class.name}:#{object_id} #{attributes.join(', ')}>"
104
102
  end
105
103
 
104
+ private
105
+
106
+ def read_feature_keys
107
+ set_members(FeaturesKey)
108
+ end
109
+
106
110
  # Private
107
111
  def key(feature, gate)
108
- "#{feature.key}/#{gate.key}"
112
+ "feature/#{feature.key}/#{gate.key}"
113
+ end
114
+
115
+ def read_many_features(features)
116
+ result = {}
117
+ features.each do |feature|
118
+ result[feature.key] = read_feature(feature)
119
+ end
120
+ result
121
+ end
122
+
123
+ def read_feature(feature)
124
+ result = {}
125
+
126
+ feature.gates.each do |gate|
127
+ result[gate.key] =
128
+ case gate.data_type
129
+ when :boolean, :integer
130
+ read key(feature, gate)
131
+ when :set
132
+ set_members key(feature, gate)
133
+ else
134
+ raise "#{gate} is not supported by this adapter yet"
135
+ end
136
+ end
137
+
138
+ result
109
139
  end
110
140
 
111
141
  # Private
@@ -25,59 +25,68 @@ module Flipper
25
25
 
26
26
  # Public: The set of known features.
27
27
  def features
28
- set_members FeaturesKey
28
+ @store.transaction do
29
+ read_feature_keys
30
+ end
29
31
  end
30
32
 
31
33
  # Public: Adds a feature to the set of known features.
32
34
  def add(feature)
33
- set_add FeaturesKey, feature.key
35
+ @store.transaction do
36
+ set_add FeaturesKey, feature.key
37
+ end
34
38
  true
35
39
  end
36
40
 
37
41
  # Public: Removes a feature from the set of known features and clears
38
42
  # all the values for the feature.
39
43
  def remove(feature)
40
- set_delete FeaturesKey, feature.key
41
- clear(feature)
44
+ @store.transaction do
45
+ set_delete FeaturesKey, feature.key
46
+ clear_gates(feature)
47
+ end
42
48
  true
43
49
  end
44
50
 
45
51
  # Public: Clears all the gate values for a feature.
46
52
  def clear(feature)
47
- feature.gates.each do |gate|
48
- delete key(feature, gate)
53
+ @store.transaction do
54
+ clear_gates(feature)
49
55
  end
50
56
  true
51
57
  end
52
58
 
53
59
  # Public
54
60
  def get(feature)
55
- result = {}
61
+ @store.transaction do
62
+ result_for_feature(feature)
63
+ end
64
+ end
56
65
 
57
- feature.gates.each do |gate|
58
- result[gate.key] =
59
- case gate.data_type
60
- when :boolean, :integer
61
- read key(feature, gate)
62
- when :set
63
- set_members key(feature, gate)
64
- else
65
- raise "#{gate} is not supported by this adapter yet"
66
- end
66
+ def get_multi(features)
67
+ @store.transaction do
68
+ read_many_features(features)
67
69
  end
70
+ end
68
71
 
69
- result
72
+ def get_all
73
+ @store.transaction do
74
+ features = read_feature_keys.map { |key| Flipper::Feature.new(key, self) }
75
+ read_many_features(features)
76
+ end
70
77
  end
71
78
 
72
79
  # Public
73
80
  def enable(feature, gate, thing)
74
- case gate.data_type
75
- when :boolean, :integer
76
- write key(feature, gate), thing.value.to_s
77
- when :set
78
- set_add key(feature, gate), thing.value.to_s
79
- else
80
- raise "#{gate} is not supported by this adapter yet"
81
+ @store.transaction do
82
+ case gate.data_type
83
+ when :boolean, :integer
84
+ write key(feature, gate), thing.value.to_s
85
+ when :set
86
+ set_add key(feature, gate), thing.value.to_s
87
+ else
88
+ raise "#{gate} is not supported by this adapter yet"
89
+ end
81
90
  end
82
91
 
83
92
  true
@@ -89,9 +98,13 @@ module Flipper
89
98
  when :boolean
90
99
  clear(feature)
91
100
  when :integer
92
- write key(feature, gate), thing.value.to_s
101
+ @store.transaction do
102
+ write key(feature, gate), thing.value.to_s
103
+ end
93
104
  when :set
94
- set_delete key(feature, gate), thing.value.to_s
105
+ @store.transaction do
106
+ set_delete key(feature, gate), thing.value.to_s
107
+ end
95
108
  else
96
109
  raise "#{gate} is not supported by this adapter yet"
97
110
  end
@@ -111,6 +124,42 @@ module Flipper
111
124
 
112
125
  private
113
126
 
127
+ def clear_gates(feature)
128
+ feature.gates.each do |gate|
129
+ delete key(feature, gate)
130
+ end
131
+ end
132
+
133
+ def read_feature_keys
134
+ set_members FeaturesKey
135
+ end
136
+
137
+ def read_many_features(features)
138
+ result = {}
139
+ features.each do |feature|
140
+ result[feature.key] = result_for_feature(feature)
141
+ end
142
+ result
143
+ end
144
+
145
+ def result_for_feature(feature)
146
+ result = {}
147
+
148
+ feature.gates.each do |gate|
149
+ result[gate.key] =
150
+ case gate.data_type
151
+ when :boolean, :integer
152
+ read key(feature, gate)
153
+ when :set
154
+ set_members key(feature, gate)
155
+ else
156
+ raise "#{gate} is not supported by this adapter yet"
157
+ end
158
+ end
159
+
160
+ result
161
+ end
162
+
114
163
  # Private
115
164
  def key(feature, gate)
116
165
  "#{feature.key}/#{gate.key}"
@@ -118,23 +167,17 @@ module Flipper
118
167
 
119
168
  # Private
120
169
  def read(key)
121
- @store.transaction do
122
- @store[key.to_s]
123
- end
170
+ @store[key.to_s]
124
171
  end
125
172
 
126
173
  # Private
127
174
  def write(key, value)
128
- @store.transaction do
129
- @store[key.to_s] = value.to_s
130
- end
175
+ @store[key.to_s] = value.to_s
131
176
  end
132
177
 
133
178
  # Private
134
179
  def delete(key)
135
- @store.transaction do
136
- @store.delete(key.to_s)
137
- end
180
+ @store.delete(key.to_s)
138
181
  end
139
182
 
140
183
  # Private
@@ -154,14 +197,13 @@ module Flipper
154
197
  # Private
155
198
  def set_members(key)
156
199
  key = key.to_s
157
- @store.transaction do
158
- @store[key] ||= Set.new
159
200
 
160
- if block_given?
161
- yield @store[key]
162
- else
163
- @store[key]
164
- end
201
+ @store[key] ||= Set.new
202
+
203
+ if block_given?
204
+ yield @store[key]
205
+ else
206
+ @store[key]
165
207
  end
166
208
  end
167
209
  end
@@ -27,6 +27,14 @@ module Flipper
27
27
  @adapter.get(feature)
28
28
  end
29
29
 
30
+ def get_multi(features)
31
+ @adapter.get_multi(features)
32
+ end
33
+
34
+ def get_all
35
+ @adapter.get_all
36
+ end
37
+
30
38
  def add(_feature)
31
39
  raise WriteAttempted
32
40
  end
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = '0.11.0.beta9'.freeze
2
+ VERSION = '0.11.0.rc1'.freeze
3
3
  end
@@ -1,6 +1,7 @@
1
1
  require 'helper'
2
2
  require 'flipper/adapters/memoizable'
3
3
  require 'flipper/adapters/memory'
4
+ require 'flipper/adapters/operation_logger'
4
5
  require 'flipper/spec/shared_adapter_specs'
5
6
 
6
7
  RSpec.describe Flipper::Adapters::Memoizable do
@@ -66,7 +67,7 @@ RSpec.describe Flipper::Adapters::Memoizable do
66
67
  it 'memoizes feature' do
67
68
  feature = flipper[:stats]
68
69
  result = subject.get(feature)
69
- expect(cache[feature.key]).to be(result)
70
+ expect(cache[described_class.key_for(feature.key)]).to be(result)
70
71
  end
71
72
  end
72
73
 
@@ -95,8 +96,8 @@ RSpec.describe Flipper::Adapters::Memoizable do
95
96
  features = names.map { |name| flipper[name] }
96
97
  results = subject.get_multi(features)
97
98
  features.each do |feature|
98
- expect(cache[feature.key]).not_to be(nil)
99
- expect(cache[feature.key]).to be(results[feature.key])
99
+ expect(cache[described_class.key_for(feature.key)]).not_to be(nil)
100
+ expect(cache[described_class.key_for(feature.key)]).to be(results[feature.key])
100
101
  end
101
102
  end
102
103
  end
@@ -127,11 +128,32 @@ RSpec.describe Flipper::Adapters::Memoizable do
127
128
  features = names.map { |name| flipper[name].tap(&:enable) }
128
129
  results = subject.get_all
129
130
  features.each do |feature|
130
- expect(cache[feature.key]).not_to be(nil)
131
- expect(cache[feature.key]).to be(results[feature.key])
131
+ expect(cache[described_class.key_for(feature.key)]).not_to be(nil)
132
+ expect(cache[described_class.key_for(feature.key)]).to be(results[feature.key])
132
133
  end
133
134
  expect(cache[subject.class::FeaturesKey]).to eq(names.map(&:to_s).to_set)
134
135
  end
136
+
137
+ it 'only calls get_all once for memoized adapter' do
138
+ adapter = Flipper::Adapters::OperationLogger.new(Flipper::Adapters::Memory.new)
139
+ cache = {}
140
+ instance = described_class.new(adapter, cache)
141
+ instance.memoize = true
142
+
143
+ instance.get_all
144
+ expect(adapter.count(:get_all)).to be(1)
145
+
146
+ instance.get_all
147
+ expect(adapter.count(:get_all)).to be(1)
148
+ end
149
+
150
+ it 'returns default_config for unknown feature keys' do
151
+ first = subject.get_all
152
+ expect(first['doesntexist']).to eq(subject.default_config)
153
+
154
+ second = subject.get_all
155
+ expect(second['doesntexist']).to eq(subject.default_config)
156
+ end
135
157
  end
136
158
 
137
159
  context "with memoization disabled" do
@@ -146,6 +168,27 @@ RSpec.describe Flipper::Adapters::Memoizable do
146
168
  adapter_result = adapter.get_all
147
169
  expect(result).to eq(adapter_result)
148
170
  end
171
+
172
+ it 'calls get_all every time for memoized adapter' do
173
+ adapter = Flipper::Adapters::OperationLogger.new(Flipper::Adapters::Memory.new)
174
+ cache = {}
175
+ instance = described_class.new(adapter, cache)
176
+ instance.memoize = false
177
+
178
+ instance.get_all
179
+ expect(adapter.count(:get_all)).to be(1)
180
+
181
+ instance.get_all
182
+ expect(adapter.count(:get_all)).to be(2)
183
+ end
184
+
185
+ it 'returns nil for unknown feature keys' do
186
+ first = subject.get_all
187
+ expect(first['doesntexist']).to be(nil)
188
+
189
+ second = subject.get_all
190
+ expect(second['doesntexist']).to be(nil)
191
+ end
149
192
  end
150
193
  end
151
194
 
@@ -158,9 +201,9 @@ RSpec.describe Flipper::Adapters::Memoizable do
158
201
  it 'unmemoizes feature' do
159
202
  feature = flipper[:stats]
160
203
  gate = feature.gate(:boolean)
161
- cache[feature.key] = { some: 'thing' }
204
+ cache[described_class.key_for(feature.key)] = { some: 'thing' }
162
205
  subject.enable(feature, gate, flipper.bool)
163
- expect(cache[feature.key]).to be_nil
206
+ expect(cache[described_class.key_for(feature.key)]).to be_nil
164
207
  end
165
208
  end
166
209
 
@@ -188,9 +231,9 @@ RSpec.describe Flipper::Adapters::Memoizable do
188
231
  it 'unmemoizes feature' do
189
232
  feature = flipper[:stats]
190
233
  gate = feature.gate(:boolean)
191
- cache[feature.key] = { some: 'thing' }
234
+ cache[described_class.key_for(feature.key)] = { some: 'thing' }
192
235
  subject.disable(feature, gate, flipper.bool)
193
- expect(cache[feature.key]).to be_nil
236
+ expect(cache[described_class.key_for(feature.key)]).to be_nil
194
237
  end
195
238
  end
196
239
 
@@ -272,9 +315,9 @@ RSpec.describe Flipper::Adapters::Memoizable do
272
315
 
273
316
  it 'unmemoizes the feature' do
274
317
  feature = flipper[:stats]
275
- cache[feature.key] = { some: 'thing' }
318
+ cache[described_class.key_for(feature.key)] = { some: 'thing' }
276
319
  subject.remove(feature)
277
- expect(cache[feature.key]).to be_nil
320
+ expect(cache[described_class.key_for(feature.key)]).to be_nil
278
321
  end
279
322
  end
280
323
 
@@ -297,9 +340,9 @@ RSpec.describe Flipper::Adapters::Memoizable do
297
340
 
298
341
  it 'unmemoizes feature' do
299
342
  feature = flipper[:stats]
300
- cache[feature.key] = { some: 'thing' }
343
+ cache[described_class.key_for(feature.key)] = { some: 'thing' }
301
344
  subject.clear(feature)
302
- expect(cache[feature.key]).to be_nil
345
+ expect(cache[described_class.key_for(feature.key)]).to be_nil
303
346
  end
304
347
  end
305
348
 
@@ -1,6 +1,9 @@
1
1
  require 'helper'
2
2
  require 'rack/test'
3
+ require 'active_support/cache'
4
+ require 'active_support/cache/dalli_store'
3
5
  require 'flipper/middleware/memoizer'
6
+ require 'flipper/adapters/active_support_cache_store'
4
7
  require 'flipper/adapters/operation_logger'
5
8
  require 'flipper/adapters/memory'
6
9
 
@@ -141,6 +144,7 @@ RSpec.describe Flipper::Middleware::Memoizer do
141
144
  middleware = described_class.new(app, preload_all: true)
142
145
  middleware.call(env)
143
146
 
147
+ expect(adapter.operations.size).to be(1)
144
148
  expect(adapter.count(:get_all)).to be(1)
145
149
  end
146
150
 
@@ -335,4 +339,45 @@ RSpec.describe Flipper::Middleware::Memoizer do
335
339
  get '/some/other/path', {}, 'flipper' => flipper
336
340
  end
337
341
  end
342
+
343
+ context 'with preload_all and caching adapter' do
344
+ it 'eagerly caches known features for duration of request' do
345
+ memory = Flipper::Adapters::Memory.new
346
+ logged_memory = Flipper::Adapters::OperationLogger.new(memory)
347
+ cache = ActiveSupport::Cache::DalliStore.new
348
+ cache.clear
349
+ cached = Flipper::Adapters::ActiveSupportCacheStore.new(logged_memory, cache, expires_in: 10)
350
+ logged_cached = Flipper::Adapters::OperationLogger.new(cached)
351
+ memo = {}
352
+ flipper = Flipper.new(logged_cached)
353
+ flipper[:stats].enable
354
+ flipper[:shiny].enable
355
+
356
+ # clear the log of operations
357
+ logged_memory.reset
358
+ logged_cached.reset
359
+
360
+ app = lambda do |_env|
361
+ flipper[:stats].enabled?
362
+ flipper[:stats].enabled?
363
+ flipper[:shiny].enabled?
364
+ flipper[:shiny].enabled?
365
+ [200, {}, []]
366
+ end
367
+
368
+ middleware = described_class.new(app, preload_all: true)
369
+
370
+ middleware.call('flipper' => flipper)
371
+ expect(logged_cached.count(:get_all)).to be(1)
372
+ expect(logged_memory.count(:get_all)).to be(1)
373
+
374
+ middleware.call('flipper' => flipper)
375
+ expect(logged_cached.count(:get_all)).to be(2)
376
+ expect(logged_memory.count(:get_all)).to be(1)
377
+
378
+ middleware.call('flipper' => flipper)
379
+ expect(logged_cached.count(:get_all)).to be(3)
380
+ expect(logged_memory.count(:get_all)).to be(1)
381
+ end
382
+ end
338
383
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flipper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0.beta9
4
+ version: 0.11.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-28 00:00:00.000000000 Z
11
+ date: 2017-11-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Feature flipper is the act of enabling/disabling features in your application,
14
14
  ideally without re-deploying or changing anything in your code base. Flipper makes