Files
openfoodnetwork/lib/open_food_network/feature_toggle.rb
Maikel Linke 5775051e35 Simplify FeatureToggle module
This saves ten lines of code and makes the simplicity of the
FeatureToggle interface clearer.
2021-04-12 18:26:18 +02:00

86 lines
2.3 KiB
Ruby

module OpenFoodNetwork
# This feature toggles implementation provides two mechanisms to conditionally enable features.
#
# You can provide an ENV var with the prefix `OFN_FEATURE_` and query it using the
# `ApplicationHelper#feature?` helper method. For instance, providing the ENV var
# `OFN_FEATURE_NEW_SHINNY_FEATURE` you could then query it from view as follows:
#
# - if feature? :new_shiny_feature
# = render "new_shiny_feature"
#
# Alternatively, you can choose which users have the feature toggled on. To do that you need to
# register the feature and its users from an initializer like:
#
# require 'open_food_network/feature_toggle'
# OpenFoodNetwork::FeatureToggle.enable(:new_shiny_feature, ['ofn@example.com'])
#
# Note, however, that it'd be better to read the user emails from an ENV var provisioned with
# ofn-install:
#
# require 'open_food_network/feature_toggle'
# OpenFoodNetwork::FeatureToggle.enable(:new_shiny_feature, ENV['PRODUCT_TEAM'])
#
# You can then check it from a view like:
#
# - if feature? :new_shiny_feature, spree_current_user
# = render "new_shiny_feature"
#
module FeatureToggle
def self.enabled?(feature_name, user = nil)
features = Thread.current[:features] || {}
if Flipper[feature_name].exist?
Flipper.enabled?(feature_name, user)
else
feature = features.fetch(feature_name, DefaultFeature.new(feature_name))
feature.enabled?(user)
end
end
def self.enable(feature_name, &block)
Thread.current[:features] ||= {}
Thread.current[:features][feature_name] = Feature.new(block)
end
end
class Feature
def initialize(block)
@block = block
end
def enabled?(user)
block.call(user)
end
private
attr_reader :block
end
class DefaultFeature
attr_reader :feature_name
def initialize(feature_name)
@feature_name = feature_name
end
def enabled?(_user)
true?(env_variable_value(feature_name))
end
private
def env_variable_value(feature_name)
ENV.fetch(env_variable_name(feature_name), nil)
end
def env_variable_name(feature_name)
"OFN_FEATURE_#{feature_name.to_s.upcase}"
end
def true?(value)
value.to_s.casecmp("true").zero?
end
end
end