-
-
Notifications
You must be signed in to change notification settings - Fork 419
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #763 from flippercloud/adapter_builder
Configure Strict adapter, introduce AdapterBuilder
- Loading branch information
Showing
7 changed files
with
228 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
module Flipper | ||
# Builds an adapter from a stack of adapters. | ||
# | ||
# adapter = Flipper::AdapterBuilder.new do | ||
# use Flipper::Adapters::Strict | ||
# use Flipper::Adapters::Memoizer | ||
# store Flipper::Adapters::Memory | ||
# end.to_adapter | ||
# | ||
class AdapterBuilder | ||
def initialize(&block) | ||
@stack = [] | ||
|
||
# Default to memory adapter | ||
store Flipper::Adapters::Memory | ||
|
||
block.arity == 0 ? instance_eval(&block) : block.call(self) if block | ||
end | ||
|
||
if RUBY_VERSION >= '3.0' | ||
def use(klass, *args, **kwargs, &block) | ||
@stack.push ->(adapter) { klass.new(adapter, *args, **kwargs, &block) } | ||
end | ||
else | ||
def use(klass, *args, &block) | ||
@stack.push ->(adapter) { klass.new(adapter, *args, &block) } | ||
end | ||
end | ||
|
||
if RUBY_VERSION >= '3.0' | ||
def store(adapter, *args, **kwargs, &block) | ||
@store = adapter.respond_to?(:call) ? adapter : -> { adapter.new(*args, **kwargs, &block) } | ||
end | ||
else | ||
def store(adapter, *args, &block) | ||
@store = adapter.respond_to?(:call) ? adapter : -> { adapter.new(*args, &block) } | ||
end | ||
end | ||
|
||
def to_adapter | ||
@stack.reverse.inject(@store.call) { |adapter, wrapper| wrapper.call(adapter) } | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
RSpec.describe Flipper::AdapterBuilder do | ||
describe "#initialize" do | ||
it "instance_eval's block with no arg" do | ||
called = false | ||
self_in_block = nil | ||
|
||
described_class.new do | ||
called = true | ||
self_in_block = self | ||
end | ||
|
||
expect(self_in_block).to be_instance_of(described_class) | ||
expect(called).to be(true) | ||
end | ||
|
||
it "evals block with arg" do | ||
called = false | ||
self_outside_block = self | ||
self_in_block = nil | ||
|
||
described_class.new do |arg| | ||
called = true | ||
self_in_block = self | ||
expect(arg).to be_instance_of(described_class) | ||
end | ||
|
||
expect(self_in_block).to be(self_outside_block) | ||
expect(called).to be(true) | ||
end | ||
end | ||
|
||
describe "#use" do | ||
it "wraps the store adapter with the given adapter" do | ||
subject.use(Flipper::Adapters::Memoizable) | ||
subject.use(Flipper::Adapters::Strict, :warn) | ||
|
||
memoizable_adapter = subject.to_adapter | ||
strict_adapter = memoizable_adapter.adapter | ||
memory_adapter = strict_adapter.adapter | ||
|
||
|
||
expect(memoizable_adapter).to be_instance_of(Flipper::Adapters::Memoizable) | ||
expect(strict_adapter).to be_instance_of(Flipper::Adapters::Strict) | ||
expect(strict_adapter.handler).to be(Flipper::Adapters::Strict::HANDLERS.fetch(:warn)) | ||
expect(memory_adapter).to be_instance_of(Flipper::Adapters::Memory) | ||
end | ||
|
||
it "passes block to adapter initializer" do | ||
expected_block = lambda {} | ||
adapter_class = double('adapter class') | ||
|
||
subject.use(adapter_class, &expected_block) | ||
|
||
expect(adapter_class).to receive(:new) { |&block| expect(block).to be(expected_block) }.and_return(:adapter) | ||
expect(subject.to_adapter).to be(:adapter) | ||
end | ||
end | ||
|
||
describe "#store" do | ||
it "defaults to memory adapter" do | ||
expect(subject.to_adapter).to be_instance_of(Flipper::Adapters::Memory) | ||
end | ||
|
||
it "only saves one store" do | ||
require "flipper/adapters/pstore" | ||
subject.store(Flipper::Adapters::PStore) | ||
expect(subject.to_adapter).to be_instance_of(Flipper::Adapters::PStore) | ||
|
||
subject.store(Flipper::Adapters::Memory) | ||
expect(subject.to_adapter).to be_instance_of(Flipper::Adapters::Memory) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters