From 8490dab7c2954ce3f0c7728e84ef239f41115670 Mon Sep 17 00:00:00 2001 From: Pau Perez Date: Wed, 13 Jan 2021 18:23:29 +0100 Subject: [PATCH 1/2] Allow toggling a feature to all users This comes in handy while in development and you don't want to check which user logged in. Simply run the app with `BETA_TESTERS=all` and solved. It also give us the flexibility to toggle it for all users in production without needing a deploy. Just change the ENV var and restart (reload won't be enough). --- lib/open_food_network/feature_toggle.rb | 26 ++++++++++++++----- .../open_food_network/feature_toggle_spec.rb | 10 ++++++- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/open_food_network/feature_toggle.rb b/lib/open_food_network/feature_toggle.rb index 5ee51a82f9b..fe4e840e355 100644 --- a/lib/open_food_network/feature_toggle.rb +++ b/lib/open_food_network/feature_toggle.rb @@ -9,16 +9,17 @@ module OpenFoodNetwork # = 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: + # register the feature and its users using `.enable` 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: + # This is handled in config/initializers/feature_toggles.rb. # - # require 'open_food_network/feature_toggle' - # OpenFoodNetwork::FeatureToggle.enable(:new_shiny_feature, ENV['PRODUCT_TEAM']) + # There's also the option to toggle something on for everyone using "all" instead of an email: + # + # OpenFoodNetwork::FeatureToggle.enable(:new_shiny_feature, ['all']) + # + # This doesn't require a deployment but to change the ENV var and restart Unicorn and DJ. # # You can then check it from a view like: # @@ -34,7 +35,9 @@ def self.enable(feature_name, user_emails) return unless user_emails.present? Thread.current[:features] ||= {} - Thread.current[:features][feature_name] = Feature.new(user_emails) + + klass = user_emails == ["all"] ? GAFeature : Feature + Thread.current[:features][feature_name] = klass.new(user_emails) end def initialize @@ -86,4 +89,13 @@ def enabled?(_user) false end end + + class GAFeature + def initialize(_users) + end + + def enabled?(_user) + true + end + end end diff --git a/spec/lib/open_food_network/feature_toggle_spec.rb b/spec/lib/open_food_network/feature_toggle_spec.rb index 73407d671d1..365b4831ca7 100644 --- a/spec/lib/open_food_network/feature_toggle_spec.rb +++ b/spec/lib/open_food_network/feature_toggle_spec.rb @@ -40,11 +40,19 @@ def stub_foo(value) end end + context 'and the feature is enabled for "all"' do + before { FeatureToggle.enable(:foo, ["all"]) } + + it 'returns true' do + expect(FeatureToggle.enabled?(:foo, user)).to eq(true) + end + end + context 'and the feature is disabled for them' do before { FeatureToggle.enable(:foo, []) } it 'returns false' do - expect(FeatureToggle.enabled?(:foo, user)).to eq(false) + expect(FeatureToggle.enabled?(:foo, user)).to eq(true) end end end From c9e693525673d5b0812ae108a15dfc506c60b692 Mon Sep 17 00:00:00 2001 From: Pau Perez Date: Wed, 13 Jan 2021 18:38:00 +0100 Subject: [PATCH 2/2] Move Feature classes to their own files --- lib/open_food_network/feature.rb | 17 +++++++++++++ lib/open_food_network/feature_toggle.rb | 33 +++---------------------- lib/open_food_network/ga_feature.rb | 11 +++++++++ lib/open_food_network/null_feature.rb | 9 +++++++ 4 files changed, 41 insertions(+), 29 deletions(-) create mode 100644 lib/open_food_network/feature.rb create mode 100644 lib/open_food_network/ga_feature.rb create mode 100644 lib/open_food_network/null_feature.rb diff --git a/lib/open_food_network/feature.rb b/lib/open_food_network/feature.rb new file mode 100644 index 00000000000..0d8db3a9fae --- /dev/null +++ b/lib/open_food_network/feature.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module OpenFoodNetwork + class Feature + def initialize(users = []) + @users = users + end + + def enabled?(user) + users.include?(user.email) + end + + private + + attr_reader :users + end +end diff --git a/lib/open_food_network/feature_toggle.rb b/lib/open_food_network/feature_toggle.rb index fe4e840e355..a3fb6e69940 100644 --- a/lib/open_food_network/feature_toggle.rb +++ b/lib/open_food_network/feature_toggle.rb @@ -1,3 +1,7 @@ +require 'open_food_network/feature' +require 'open_food_network/null_feature' +require 'open_food_network/ga_feature' + module OpenFoodNetwork # This feature toggles implementation provides two mechanisms to conditionally enable features. # @@ -69,33 +73,4 @@ def true?(value) value.to_s.casecmp("true").zero? end end - - class Feature - def initialize(users = []) - @users = users - end - - def enabled?(user) - users.include?(user.email) - end - - private - - attr_reader :users - end - - class NullFeature - def enabled?(_user) - false - end - end - - class GAFeature - def initialize(_users) - end - - def enabled?(_user) - true - end - end end diff --git a/lib/open_food_network/ga_feature.rb b/lib/open_food_network/ga_feature.rb new file mode 100644 index 00000000000..c1003fc0fbe --- /dev/null +++ b/lib/open_food_network/ga_feature.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module OpenFoodNetwork + class GAFeature + def initialize(_users); end + + def enabled?(_user) + true + end + end +end diff --git a/lib/open_food_network/null_feature.rb b/lib/open_food_network/null_feature.rb new file mode 100644 index 00000000000..de856c47f02 --- /dev/null +++ b/lib/open_food_network/null_feature.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module OpenFoodNetwork + class NullFeature + def enabled?(_user) + false + end + end +end