diff options
Diffstat (limited to 'lib/gitlab/with_feature_category.rb')
-rw-r--r-- | lib/gitlab/with_feature_category.rb | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/gitlab/with_feature_category.rb b/lib/gitlab/with_feature_category.rb new file mode 100644 index 00000000000..65d21daf78a --- /dev/null +++ b/lib/gitlab/with_feature_category.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module Gitlab + module WithFeatureCategory + extend ActiveSupport::Concern + include Gitlab::ClassAttributes + + class_methods do + def feature_category(category, actions = []) + feature_category_configuration[category] ||= [] + feature_category_configuration[category] += actions.map(&:to_s) + + validate_config!(feature_category_configuration) + end + + def feature_category_for_action(action) + category_config = feature_category_configuration.find do |_, actions| + actions.empty? || actions.include?(action) + end + + category_config&.first || superclass_feature_category_for_action(action) + end + + private + + def validate_config!(config) + empty = config.find { |_, actions| actions.empty? } + duplicate_actions = config.values.map(&:uniq).flatten.group_by(&:itself).select { |_, v| v.count > 1 }.keys + + if config.length > 1 && empty + raise ArgumentError, "#{empty.first} is defined for all actions, but other categories are set" + end + + if duplicate_actions.any? + raise ArgumentError, "Actions have multiple feature categories: #{duplicate_actions.join(', ')}" + end + end + + def feature_category_configuration + class_attributes[:feature_category_config] ||= {} + end + + def superclass_feature_category_for_action(action) + return unless superclass.respond_to?(:feature_category_for_action) + + superclass.feature_category_for_action(action) + end + end + end +end |