flipper 0.19.1 → 0.20.1
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 +4 -4
- data/Changelog.md +12 -0
- data/Gemfile +1 -0
- data/docs/Optimization.md +7 -7
- data/lib/flipper.rb +2 -1
- data/lib/flipper/adapters/dual_write.rb +67 -0
- data/lib/flipper/adapters/operation_logger.rb +5 -0
- data/lib/flipper/adapters/sync.rb +7 -7
- data/lib/flipper/adapters/sync/synchronizer.rb +1 -0
- data/lib/flipper/dsl.rb +8 -0
- data/lib/flipper/middleware/setup_env.rb +13 -3
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapters/dual_write_spec.rb +71 -0
- data/spec/flipper/adapters/operation_logger_spec.rb +9 -0
- data/spec/flipper/adapters/sync_spec.rb +4 -4
- data/spec/flipper/middleware/setup_env_spec.rb +39 -3
- data/spec/flipper_spec.rb +27 -0
- data/spec/support/spec_helpers.rb +5 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3419ab68fa52334e5a6f71463c213a039f819439dc71c836c8c3b70b4c80270b
|
4
|
+
data.tar.gz: d6ade104432d5f5eaab36f00ccd0b559ee9bd9af4772a224cb9f70d26f578062
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48bc857cb049418b020bc1216de81238df104321b62c7ff3b3967dfdc8dfedf18a1779d58c84db233cc67d9058a1b7beb295e671739a232f8384cf324879b950
|
7
|
+
data.tar.gz: b5e0c90341f3b0a4f61a72ee26810ccdec216f32bd7e07b022f15ca04b075eb44a53bd392afdb91d7a868d3c724c96b2a962a37ed54fd5614a3a5f385e0ac147
|
data/Changelog.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## 0.20.1
|
2
|
+
|
3
|
+
### Additions/Changes
|
4
|
+
|
5
|
+
* Just a minor tweak to cloud webhook middleware to provide more debugging information about why a hook wasn't successful.
|
6
|
+
|
7
|
+
## 0.20.0
|
8
|
+
|
9
|
+
### Additions/Changes
|
10
|
+
|
11
|
+
* Add support for webhooks to `Flipper::Cloud` (https://github.com/jnunemaker/flipper/pull/489).
|
12
|
+
|
1
13
|
## 0.19.1
|
2
14
|
|
3
15
|
### Additions/Changes
|
data/Gemfile
CHANGED
data/docs/Optimization.md
CHANGED
@@ -7,7 +7,7 @@ One optimization that flipper provides is a memoizing middleware. The memoizing
|
|
7
7
|
You can use the middleware like so for Rails:
|
8
8
|
|
9
9
|
```ruby
|
10
|
-
# setup default instance (perhaps in config/
|
10
|
+
# setup default instance (perhaps in config/initializers/flipper.rb)
|
11
11
|
Flipper.configure do |config|
|
12
12
|
config.default do
|
13
13
|
Flipper.new(...)
|
@@ -15,7 +15,7 @@ Flipper.configure do |config|
|
|
15
15
|
end
|
16
16
|
|
17
17
|
# This assumes you setup a default flipper instance using configure.
|
18
|
-
|
18
|
+
Rails.configuration.middleware.use Flipper::Middleware::Memoizer
|
19
19
|
```
|
20
20
|
|
21
21
|
**Note**: Be sure that the middleware is high enough up in your stack that all feature checks are wrapped.
|
@@ -23,8 +23,8 @@ config.middleware.use Flipper::Middleware::Memoizer
|
|
23
23
|
**Also Note**: If you haven't setup a default instance, you can pass the instance to `SetupEnv` as `Memoizer` uses whatever is setup in the `env`:
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
|
27
|
-
|
26
|
+
Rails.configuration.middleware.use Flipper::Middleware::SetupEnv, -> { Flipper.new(...) }
|
27
|
+
Rails.configuration.middleware.use Flipper::Middleware::Memoizer
|
28
28
|
```
|
29
29
|
|
30
30
|
### Options
|
@@ -33,18 +33,18 @@ The Memoizer middleware also supports a few options. Use either `preload` or `pr
|
|
33
33
|
|
34
34
|
* **`:preload`** - An `Array` of feature names (`Symbol`) to preload for every request. Useful if you have features that are used on every endpoint. `preload` uses `Adapter#get_multi` to attempt to load the features in one network call instead of N+1 network calls.
|
35
35
|
```ruby
|
36
|
-
|
36
|
+
Rails.configuration.middleware.use Flipper::Middleware::Memoizer,
|
37
37
|
preload: [:stats, :search, :some_feature]
|
38
38
|
```
|
39
39
|
* **`:preload_all`** - A Boolean value (default: false) of whether or not all features should be preloaded. Using this results in a `preload_all` call with the result of `Adapter#get_all`. Any subsequent feature checks will be memoized and perform no network calls. I wouldn't recommend using this unless you have few features (< 100?) and nearly all of them are used on every request.
|
40
40
|
```ruby
|
41
|
-
|
41
|
+
Rails.configuration.middleware.use Flipper::Middleware::Memoizer,
|
42
42
|
preload_all: true
|
43
43
|
```
|
44
44
|
* **`:unless`** - A block that prevents preloading and memoization if it evaluates to true.
|
45
45
|
```ruby
|
46
46
|
# skip preloading and memoizing if path starts with /assets
|
47
|
-
|
47
|
+
Rails.configuration.middleware.use Flipper::Middleware::Memoizer,
|
48
48
|
unless: ->(request) { request.path.start_with?("/assets") }
|
49
49
|
```
|
50
50
|
|
data/lib/flipper.rb
CHANGED
@@ -65,7 +65,8 @@ module Flipper
|
|
65
65
|
:time, :percentage_of_time,
|
66
66
|
:features, :feature, :[], :preload, :preload_all,
|
67
67
|
:adapter, :add, :exist?, :remove, :import,
|
68
|
-
:memoize=, :memoizing
|
68
|
+
:memoize=, :memoizing?,
|
69
|
+
:sync, :sync_secret # For Flipper::Cloud. Will error for OSS Flipper.
|
69
70
|
|
70
71
|
# Public: Use this to register a group by name.
|
71
72
|
#
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Flipper
|
2
|
+
module Adapters
|
3
|
+
class DualWrite
|
4
|
+
include ::Flipper::Adapter
|
5
|
+
|
6
|
+
# Public: The name of the adapter.
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
# Public: Build a new sync instance.
|
10
|
+
#
|
11
|
+
# local - The local flipper adapter that should serve reads.
|
12
|
+
# remote - The remote flipper adapter that writes should go to first (in
|
13
|
+
# addition to the local adapter).
|
14
|
+
def initialize(local, remote, options = {})
|
15
|
+
@name = :dual_write
|
16
|
+
@local = local
|
17
|
+
@remote = remote
|
18
|
+
end
|
19
|
+
|
20
|
+
def features
|
21
|
+
@local.features
|
22
|
+
end
|
23
|
+
|
24
|
+
def get(feature)
|
25
|
+
@local.get(feature)
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_multi(features)
|
29
|
+
@local.get_multi(features)
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_all
|
33
|
+
@local.get_all
|
34
|
+
end
|
35
|
+
|
36
|
+
def add(feature)
|
37
|
+
result = @remote.add(feature)
|
38
|
+
@local.add(feature)
|
39
|
+
result
|
40
|
+
end
|
41
|
+
|
42
|
+
def remove(feature)
|
43
|
+
result = @remote.remove(feature)
|
44
|
+
@local.remove(feature)
|
45
|
+
result
|
46
|
+
end
|
47
|
+
|
48
|
+
def clear(feature)
|
49
|
+
result = @remote.clear(feature)
|
50
|
+
@local.clear(feature)
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
def enable(feature, gate, thing)
|
55
|
+
result = @remote.enable(feature, gate, thing)
|
56
|
+
@local.enable(feature, gate, thing)
|
57
|
+
result
|
58
|
+
end
|
59
|
+
|
60
|
+
def disable(feature, gate, thing)
|
61
|
+
result = @remote.disable(feature, gate, thing)
|
62
|
+
@local.disable(feature, gate, thing)
|
63
|
+
result
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -117,6 +117,11 @@ module Flipper
|
|
117
117
|
def reset
|
118
118
|
@operations.clear
|
119
119
|
end
|
120
|
+
|
121
|
+
def inspect
|
122
|
+
inspect_id = ::Kernel::format "%x", (object_id * 2)
|
123
|
+
%(#<#{self.class}:0x#{inspect_id} @name=#{name.inspect}, @operations=#{@operations.inspect}, @adapter=#{@adapter.inspect}>)
|
124
|
+
end
|
120
125
|
end
|
121
126
|
end
|
122
127
|
end
|
@@ -17,7 +17,7 @@ module Flipper
|
|
17
17
|
# Public: Build a new sync instance.
|
18
18
|
#
|
19
19
|
# local - The local flipper adapter that should serve reads.
|
20
|
-
# remote - The remote flipper
|
20
|
+
# remote - The remote flipper adapter that should serve writes and update
|
21
21
|
# the local on an interval.
|
22
22
|
# interval - The Float or Integer number of seconds between syncs from
|
23
23
|
# remote to local. Default value is set in IntervalSynchronizer.
|
@@ -34,26 +34,26 @@ module Flipper
|
|
34
34
|
synchronizer = Synchronizer.new(@local, @remote, sync_options)
|
35
35
|
IntervalSynchronizer.new(synchronizer, interval: options[:interval])
|
36
36
|
end
|
37
|
-
|
37
|
+
synchronize
|
38
38
|
end
|
39
39
|
|
40
40
|
def features
|
41
|
-
|
41
|
+
synchronize
|
42
42
|
@local.features
|
43
43
|
end
|
44
44
|
|
45
45
|
def get(feature)
|
46
|
-
|
46
|
+
synchronize
|
47
47
|
@local.get(feature)
|
48
48
|
end
|
49
49
|
|
50
50
|
def get_multi(features)
|
51
|
-
|
51
|
+
synchronize
|
52
52
|
@local.get_multi(features)
|
53
53
|
end
|
54
54
|
|
55
55
|
def get_all
|
56
|
-
|
56
|
+
synchronize
|
57
57
|
@local.get_all
|
58
58
|
end
|
59
59
|
|
@@ -89,7 +89,7 @@ module Flipper
|
|
89
89
|
|
90
90
|
private
|
91
91
|
|
92
|
-
def
|
92
|
+
def synchronize
|
93
93
|
@synchronizer.call
|
94
94
|
end
|
95
95
|
end
|
@@ -15,6 +15,7 @@ module Flipper
|
|
15
15
|
# adapter should be brought in line with.
|
16
16
|
# options - The Hash of options.
|
17
17
|
# :instrumenter - The instrumenter used to instrument.
|
18
|
+
# :raise - Should errors be raised (default: true).
|
18
19
|
def initialize(local, remote, options = {})
|
19
20
|
@local = local
|
20
21
|
@remote = remote
|
data/lib/flipper/dsl.rb
CHANGED
@@ -273,5 +273,13 @@ module Flipper
|
|
273
273
|
def import(flipper)
|
274
274
|
adapter.import(flipper.adapter)
|
275
275
|
end
|
276
|
+
|
277
|
+
# Cloud DSL method that does nothing for open source version.
|
278
|
+
def sync
|
279
|
+
end
|
280
|
+
|
281
|
+
# Cloud DSL method that does nothing for open source version.
|
282
|
+
def sync_secret
|
283
|
+
end
|
276
284
|
end
|
277
285
|
end
|
@@ -7,7 +7,8 @@ module Flipper
|
|
7
7
|
#
|
8
8
|
# app - The app this middleware is included in.
|
9
9
|
# flipper_or_block - The Flipper::DSL instance or a block that yields a
|
10
|
-
# Flipper::DSL instance to use for all operations
|
10
|
+
# Flipper::DSL instance to use for all operations
|
11
|
+
# (optional, default: Flipper).
|
11
12
|
#
|
12
13
|
# Examples
|
13
14
|
#
|
@@ -19,18 +20,27 @@ module Flipper
|
|
19
20
|
# # using with a block that yields a flipper instance
|
20
21
|
# use Flipper::Middleware::SetupEnv, lambda { Flipper.new(...) }
|
21
22
|
#
|
22
|
-
|
23
|
+
# # using default configured Flipper instance
|
24
|
+
# Flipper.configure do |config|
|
25
|
+
# config.default { Flipper.new(...) }
|
26
|
+
# end
|
27
|
+
# use Flipper::Middleware::SetupEnv
|
28
|
+
def initialize(app, flipper_or_block = nil, options = {})
|
23
29
|
@app = app
|
24
30
|
@env_key = options.fetch(:env_key, 'flipper')
|
25
31
|
|
26
32
|
if flipper_or_block.respond_to?(:call)
|
27
33
|
@flipper_block = flipper_or_block
|
28
34
|
else
|
29
|
-
@flipper = flipper_or_block
|
35
|
+
@flipper = flipper_or_block || Flipper
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
33
39
|
def call(env)
|
40
|
+
dup.call!(env)
|
41
|
+
end
|
42
|
+
|
43
|
+
def call!(env)
|
34
44
|
env[@env_key] ||= flipper
|
35
45
|
@app.call(env)
|
36
46
|
end
|
data/lib/flipper/version.rb
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'flipper/adapters/dual_write'
|
3
|
+
require 'flipper/adapters/operation_logger'
|
4
|
+
require 'flipper/spec/shared_adapter_specs'
|
5
|
+
require 'active_support/notifications'
|
6
|
+
|
7
|
+
RSpec.describe Flipper::Adapters::DualWrite do
|
8
|
+
let(:local_adapter) do
|
9
|
+
Flipper::Adapters::OperationLogger.new Flipper::Adapters::Memory.new
|
10
|
+
end
|
11
|
+
let(:remote_adapter) do
|
12
|
+
Flipper::Adapters::OperationLogger.new Flipper::Adapters::Memory.new
|
13
|
+
end
|
14
|
+
let(:local) { Flipper.new(local_adapter) }
|
15
|
+
let(:remote) { Flipper.new(remote_adapter) }
|
16
|
+
let(:sync) { Flipper.new(subject) }
|
17
|
+
|
18
|
+
subject do
|
19
|
+
described_class.new(local_adapter, remote_adapter)
|
20
|
+
end
|
21
|
+
|
22
|
+
it_should_behave_like 'a flipper adapter'
|
23
|
+
|
24
|
+
it 'only uses local for #features' do
|
25
|
+
subject.features
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'only uses local for #get' do
|
29
|
+
subject.get sync[:search]
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'only uses local for #get_multi' do
|
33
|
+
subject.get_multi [sync[:search]]
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'only uses local for #get_all' do
|
37
|
+
subject.get_all
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'updates remote and local for #add' do
|
41
|
+
subject.add sync[:search]
|
42
|
+
expect(remote_adapter.count(:add)).to be(1)
|
43
|
+
expect(local_adapter.count(:add)).to be(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'updates remote and local for #remove' do
|
47
|
+
subject.remove sync[:search]
|
48
|
+
expect(remote_adapter.count(:remove)).to be(1)
|
49
|
+
expect(local_adapter.count(:remove)).to be(1)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'updates remote and local for #clear' do
|
53
|
+
subject.clear sync[:search]
|
54
|
+
expect(remote_adapter.count(:clear)).to be(1)
|
55
|
+
expect(local_adapter.count(:clear)).to be(1)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'updates remote and local for #enable' do
|
59
|
+
feature = sync[:search]
|
60
|
+
subject.enable feature, feature.gate(:boolean), local.boolean
|
61
|
+
expect(remote_adapter.count(:enable)).to be(1)
|
62
|
+
expect(local_adapter.count(:enable)).to be(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'updates remote and local for #disable' do
|
66
|
+
feature = sync[:search]
|
67
|
+
subject.disable feature, feature.gate(:boolean), local.boolean(false)
|
68
|
+
expect(remote_adapter.count(:disable)).to be(1)
|
69
|
+
expect(local_adapter.count(:disable)).to be(1)
|
70
|
+
end
|
71
|
+
end
|
@@ -11,6 +11,15 @@ RSpec.describe Flipper::Adapters::OperationLogger do
|
|
11
11
|
|
12
12
|
it_should_behave_like 'a flipper adapter'
|
13
13
|
|
14
|
+
it 'shows itself when inspect' do
|
15
|
+
subject.features
|
16
|
+
output = subject.inspect
|
17
|
+
expect(output).to match(/OperationLogger/)
|
18
|
+
expect(output).to match(/operation_logger/)
|
19
|
+
expect(output).to match(/@type=:features/)
|
20
|
+
expect(output).to match(/@adapter=#<Flipper::Adapters::Memory/)
|
21
|
+
end
|
22
|
+
|
14
23
|
it 'forwards missing methods to underlying adapter' do
|
15
24
|
adapter = Class.new do
|
16
25
|
def foo
|
@@ -175,22 +175,22 @@ RSpec.describe Flipper::Adapters::Sync do
|
|
175
175
|
end
|
176
176
|
|
177
177
|
it 'synchronizes for #features' do
|
178
|
-
expect(subject).to receive(:
|
178
|
+
expect(subject).to receive(:synchronize)
|
179
179
|
subject.features
|
180
180
|
end
|
181
181
|
|
182
182
|
it 'synchronizes for #get' do
|
183
|
-
expect(subject).to receive(:
|
183
|
+
expect(subject).to receive(:synchronize)
|
184
184
|
subject.get sync[:search]
|
185
185
|
end
|
186
186
|
|
187
187
|
it 'synchronizes for #get_multi' do
|
188
|
-
expect(subject).to receive(:
|
188
|
+
expect(subject).to receive(:synchronize)
|
189
189
|
subject.get_multi [sync[:search]]
|
190
190
|
end
|
191
191
|
|
192
192
|
it 'synchronizes for #get_all' do
|
193
|
-
expect(subject).to receive(:
|
193
|
+
expect(subject).to receive(:synchronize)
|
194
194
|
subject.get_all
|
195
195
|
end
|
196
196
|
|
@@ -56,21 +56,57 @@ RSpec.describe Flipper::Middleware::SetupEnv do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
context 'when flipper instance is
|
59
|
+
context 'when flipper instance or block are nil but env flipper is configured' do
|
60
60
|
let(:app) do
|
61
61
|
app = lambda do |env|
|
62
62
|
[200, { 'Content-Type' => 'text/html' }, [env['flipper'].object_id.to_s]]
|
63
63
|
end
|
64
64
|
builder = Rack::Builder.new
|
65
|
-
builder.use described_class
|
65
|
+
builder.use described_class
|
66
66
|
builder.run app
|
67
67
|
builder
|
68
68
|
end
|
69
69
|
|
70
|
-
it '
|
70
|
+
it 'can use env flipper' do
|
71
71
|
env_flipper = build_flipper
|
72
72
|
get '/', {}, 'flipper' => env_flipper
|
73
73
|
expect(last_response.body).to eq(env_flipper.object_id.to_s)
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
context 'when flipper instance or block are nil and default Flipper is configured' do
|
78
|
+
let(:app) do
|
79
|
+
Flipper.configure do |config|
|
80
|
+
config.default { flipper }
|
81
|
+
end
|
82
|
+
app = lambda do |env|
|
83
|
+
[200, { 'Content-Type' => 'text/html' }, [env['flipper'].object_id.to_s]]
|
84
|
+
end
|
85
|
+
builder = Rack::Builder.new
|
86
|
+
builder.use described_class
|
87
|
+
builder.run app
|
88
|
+
builder
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'can use env flipper' do
|
92
|
+
get '/', {}, {}
|
93
|
+
expect(last_response.body).to eq(Flipper.object_id.to_s)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'when flipper instance or block are nil and default Flipper is NOT configured' do
|
98
|
+
let(:app) do
|
99
|
+
app = lambda do |env|
|
100
|
+
[200, { 'Content-Type' => 'text/html' }, [env['flipper'].enabled?(:search)]]
|
101
|
+
end
|
102
|
+
builder = Rack::Builder.new
|
103
|
+
builder.use described_class
|
104
|
+
builder.run app
|
105
|
+
builder
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'can use env flipper' do
|
109
|
+
expect { get '/' }.to raise_error(Flipper::DefaultNotSet)
|
110
|
+
end
|
111
|
+
end
|
76
112
|
end
|
data/spec/flipper_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'flipper/cloud'
|
2
3
|
|
3
4
|
RSpec.describe Flipper do
|
4
5
|
describe '.new' do
|
@@ -215,6 +216,32 @@ RSpec.describe Flipper do
|
|
215
216
|
it 'delegates memoizing? to instance' do
|
216
217
|
expect(described_class.memoizing?).to eq(described_class.adapter.memoizing?)
|
217
218
|
end
|
219
|
+
|
220
|
+
it 'delegates sync stuff to instance and does nothing' do
|
221
|
+
expect(described_class.sync).to be(nil)
|
222
|
+
expect(described_class.sync_secret).to be(nil)
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'delegates sync stuff to instance for Flipper::Cloud' do
|
226
|
+
stub = stub_request(:get, "https://www.flippercloud.io/adapter/features").
|
227
|
+
with({
|
228
|
+
headers: {
|
229
|
+
'Flipper-Cloud-Token'=>'asdf',
|
230
|
+
},
|
231
|
+
}).to_return(status: 200, body: '{"features": {}}', headers: {})
|
232
|
+
cloud_configuration = Flipper::Cloud::Configuration.new({
|
233
|
+
token: "asdf",
|
234
|
+
sync_secret: "tasty",
|
235
|
+
sync_method: :webhook,
|
236
|
+
})
|
237
|
+
|
238
|
+
described_class.configure do |config|
|
239
|
+
config.default { Flipper::Cloud::DSL.new(cloud_configuration) }
|
240
|
+
end
|
241
|
+
described_class.sync
|
242
|
+
expect(described_class.sync_secret).to eq("tasty")
|
243
|
+
expect(stub).to have_been_requested
|
244
|
+
end
|
218
245
|
end
|
219
246
|
|
220
247
|
describe '.register' do
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'climate_control'
|
1
2
|
require 'json'
|
2
3
|
require 'rack/test'
|
3
4
|
|
@@ -56,6 +57,10 @@ module SpecHelpers
|
|
56
57
|
'more_info' => api_error_code_reference_url,
|
57
58
|
}
|
58
59
|
end
|
60
|
+
|
61
|
+
def with_modified_env(options, &block)
|
62
|
+
ClimateControl.modify(options, &block)
|
63
|
+
end
|
59
64
|
end
|
60
65
|
|
61
66
|
RSpec.configure do |config|
|
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.
|
4
|
+
version: 0.20.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-12-
|
11
|
+
date: 2020-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -55,6 +55,7 @@ files:
|
|
55
55
|
- lib/flipper.rb
|
56
56
|
- lib/flipper/actor.rb
|
57
57
|
- lib/flipper/adapter.rb
|
58
|
+
- lib/flipper/adapters/dual_write.rb
|
58
59
|
- lib/flipper/adapters/http.rb
|
59
60
|
- lib/flipper/adapters/http/client.rb
|
60
61
|
- lib/flipper/adapters/http/error.rb
|
@@ -104,6 +105,7 @@ files:
|
|
104
105
|
- spec/fixtures/feature.json
|
105
106
|
- spec/flipper/actor_spec.rb
|
106
107
|
- spec/flipper/adapter_spec.rb
|
108
|
+
- spec/flipper/adapters/dual_write_spec.rb
|
107
109
|
- spec/flipper/adapters/http_spec.rb
|
108
110
|
- spec/flipper/adapters/instrumented_spec.rb
|
109
111
|
- spec/flipper/adapters/memoizable_spec.rb
|
@@ -178,6 +180,7 @@ test_files:
|
|
178
180
|
- spec/fixtures/feature.json
|
179
181
|
- spec/flipper/actor_spec.rb
|
180
182
|
- spec/flipper/adapter_spec.rb
|
183
|
+
- spec/flipper/adapters/dual_write_spec.rb
|
181
184
|
- spec/flipper/adapters/http_spec.rb
|
182
185
|
- spec/flipper/adapters/instrumented_spec.rb
|
183
186
|
- spec/flipper/adapters/memoizable_spec.rb
|