Add new Feature class to toggle based on a closure

This enables toggling features as best fits us in each case. With this
new approach we can then toggle :customer_balance to an entire instance,
which is what we want in France.
This commit is contained in:
Pau Perez
2021-02-03 11:41:23 +01:00
parent 4d7b29ca33
commit 14cee0e45d
4 changed files with 102 additions and 6 deletions

View File

@@ -1,5 +1,11 @@
require 'open_food_network/feature_toggle'
beta_testers = ENV['BETA_TESTERS']&.split(/[\s,]+/)
beta_testers = ENV['BETA_TESTERS']&.split(/[\s,]+/) || []
OpenFoodNetwork::FeatureToggle.enable(:customer_balance, beta_testers)
OpenFoodNetwork::FeatureToggle.enable(:customer_balance) do |user|
if beta_testers == ['all']
true
else
beta_testers.include?(user.email)
end
end

View File

@@ -30,11 +30,14 @@ module OpenFoodNetwork
new.enabled?(feature_name, user)
end
def self.enable(feature_name, user_emails)
return unless user_emails.present?
def self.enable(feature_name, user_emails = nil, &block)
Thread.current[:features] ||= {}
Thread.current[:features][feature_name] = Feature.new(user_emails)
if user_emails.nil?
Thread.current[:features][feature_name] = BlockFeature.new(block)
else
Thread.current[:features][feature_name] = Feature.new(user_emails)
end
end
def initialize
@@ -86,4 +89,18 @@ module OpenFoodNetwork
false
end
end
class BlockFeature
def initialize(block)
@block = block
end
def enabled?(user)
block.call(user)
end
private
attr_reader :block
end
end

View File

@@ -0,0 +1,47 @@
require 'spec_helper'
describe 'config/initializers/feature_toggles.rb' do
let(:user) { build(:user) }
around do |example|
original = ENV['BETA_TESTERS']
example.run
ENV['BETA_TESTERS'] = original
end
context 'when beta_testers is ["all"]' do
before { ENV['BETA_TESTERS'] = 'all' }
it 'returns true' do
require './config/initializers/feature_toggles' # execute the initializer's code block
enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user)
expect(enabled).to eq(true)
end
end
context 'when beta_testers is a list of emails' do
context 'and the user is in the list' do
let(:other_user) { build(:user) }
before { ENV['BETA_TESTERS'] = "#{user.email}, #{other_user.email}" }
it 'enables the feature' do
require './config/initializers/feature_toggles' # execute the initializer's code block
enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user)
expect(enabled).to eq(true)
end
end
context 'and the user is not in the list' do
before { ENV['BETA_TESTERS'] = '' }
it 'disables the feature' do
require './config/initializers/feature_toggles' # execute the initializer's code block
enabled = OpenFoodNetwork::FeatureToggle.enabled?(:customer_balance, user)
expect(enabled).to eq(false)
end
end
end
end

View File

@@ -48,5 +48,31 @@ module OpenFoodNetwork
end
end
end
context 'when passing in a block' do
let(:user) { build(:user) }
context 'and the block does not specify arguments' do
before do
FeatureToggle.enable(:foo) { 'return value' }
end
it "returns the block's return value" do
expect(FeatureToggle.enabled?(:foo, user)).to eq('return value')
end
end
context 'and the block specifies arguments' do
let(:users) { [user.email] }
before do
FeatureToggle.enable(:foo) { |user| users.include?(user.email) }
end
it "returns the block's return value" do
expect(FeatureToggle.enabled?(:foo, user)).to eq(true)
end
end
end
end
end