# frozen_string_literal: true module SplitIoClient # # class to implement the combining matcher # class CombiningMatcher < Matcher MATCHER_TYPE = 'COMBINING_MATCHER' def initialize(combiner = '', matchers = []) @combiner = combiner @matchers = matchers end # # evaluates if the key matches the matchers within the combiner # # @param matching_key [string] key value to be matched # @param bucketing_key [string] bucketing key to be matched # @param evaluator [instance of Evaluator class] # @param attributes [hash] # # @return [boolean] def match?(args) if @matchers.empty? SplitLogger.log_if_debug('[CombiningMatcher] Matchers Empty') return false end case @combiner when Combiners::AND matches = eval_and(args) SplitLogger.log_if_debug("[CombiningMatcher] Combiner AND result -> #{matches}") return matches else SplitLogger.log_if_debug("[CombiningMatcher] Invalid Combiner Type - Combiner -> #{@combiner}") @logger.error('Invalid combiner type') end false end # # auxiliary method to evaluate each of the matchers within the combiner # # @param matching_key [string] key value to be matched # @param bucketing_key [string] bucketing key to be matched # @param evaluator [Evaluator] used in dependency_matcher # @param attributes [hash] attributes to pass to the treatment class # # @return [boolean] match value for combiner delegates def eval_and(args) # Convert all keys to symbols if args && args[:attributes] args[:attributes] = args[:attributes].each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v } end @matchers.all? do |matcher| if match_with_key?(matcher) matcher.match?(value: args[:matching_key]) else matcher.match?(args) end end end def match_with_key?(matcher) matcher.respond_to?(:attribute) && matcher.attribute.nil? && matcher.string_type? end # # function to print string value for this matcher # # @return [string] string value of this matcher def to_s @matcher_list.map(&:to_s).join("#{@combiner} ") end end end