Skip to content

Commit

Permalink
Add Strict adapter to ensure feature exists on get
Browse files Browse the repository at this point in the history
  • Loading branch information
bkeepers committed Sep 16, 2023
1 parent 43d2d7c commit 6f8f0f6
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/flipper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ def groups_registry=(registry)
require 'flipper/adapter'
require 'flipper/adapters/memoizable'
require 'flipper/adapters/memory'
require 'flipper/adapters/strict'
require 'flipper/adapters/instrumented'
require 'flipper/configuration'
require 'flipper/dsl'
Expand Down
44 changes: 44 additions & 0 deletions lib/flipper/adapters/strict.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module Flipper
module Adapters
# An adapter that ensures a feature exists before checking it.
class Strict
extend Forwardable
include ::Flipper::Adapter
attr_reader :name, :adapter

class NotFound < ::Flipper::Error
def initialize(name)
super "Could not find feature #{name.inspect}. Call `Flipper.add(#{name.inspect})` to create it."
end
end

HANDLERS = {
raise: ->(feature) { raise NotFound.new(feature.key) },
warn: ->(feature) { warn NotFound.new(feature.key).message },
noop: ->(_) { },
}

DEFAULT_NOT_FOUND =

def_delegators :@adapter, :features, :get, :get_multi, :get_all, :add, :remove, :clear, :enable, :disable

def initialize(adapter, name: :strict, handler: :raise)
@name = name
@adapter = adapter
@handler = handler.is_a?(Symbol) ? HANDLERS.fetch(handler) : handler
end

def get(feature)
assert_feature_exists(feature)
@adapter.get(feature)
end

private

def assert_feature_exists(feature)
@handler.call(feature) unless @adapter.features.include?(feature.key)
end

end
end
end
28 changes: 28 additions & 0 deletions spec/flipper/adapters/strict_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
RSpec.describe Flipper::Adapters::Strict do
let(:flipper) { Flipper.new(subject) }
let(:feature) { flipper[:unknown] }

it_should_behave_like 'a flipper adapter' do
subject { described_class.new(Flipper::Adapters::Memory.new, handler: :noop) }
end

context "handler: :raise" do
subject { described_class.new(Flipper::Adapters::Memory.new, handler: :raise) }

context "#get" do
it "raises an error for unknown feature" do
expect { subject.get(feature) }.to raise_error(Flipper::Adapters::Strict::NotFound)
end
end
end

context "handler: :warn" do
subject { described_class.new(Flipper::Adapters::Memory.new, handler: :warn) }

context "#get" do
it "raises an error for unknown feature" do
expect(silence { subject.get(feature) }).to match(/Could not find feature "unknown"/)
end
end
end
end

0 comments on commit 6f8f0f6

Please sign in to comment.