# frozen_string_literal: true # Ariadne::FetchOrFallbackHelper # A little helper to enable graceful fallbacks # # Use this helper to quietly ensure a value is # one that you expect: # # allowed_values - allowed options for *value* # given_value - input being coerced # fallback - returned if *given_value* is not included in *allowed_values* # # fetch_or_raise([1,2,3], 5) => 2 # fetch_or_raise([1,2,3], 1) => 1 # fetch_or_raise([1,2,3], nil) => 2 module Ariadne # :nodoc: module FetchOrFallbackHelper include LoggerHelper mattr_accessor :fallback_raises, default: true InvalidValueError = Class.new(StandardError) TRUE_OR_FALSE = Set.new([true, false]).freeze INTEGER_TYPES = Set.new(["Integer"]).freeze def fetch_or_raise(allowed_values, given_value, against: nil) if !allowed_values.is_a?(Array) && !allowed_values.is_a?(Set) raise ArgumentError, "allowed_values must be an array or a set; it was #{allowed_values.class}" end check_against_given_value = against || given_value if allowed_values.include?(check_against_given_value) given_value elsif fallback_raises raise InvalidValueError, <<~MSG fetch_or_raise was called with an invalid value. Expected one of: #{allowed_values.inspect} Got: #{given_value.inspect} MSG end end # TODO: use these two more def fetch_or_raise_boolean(given_value) fetch_or_raise(TRUE_OR_FALSE, given_value) end def fetch_or_raise_integer(given_value) fetch_or_raise(INTEGER_TYPES, given_value, against: given_value.class.name) end # TODO: test this def check_incoming_tag(preferred_tag, given_tag) return preferred_tag if given_tag.blank? || preferred_tag == given_tag unless silence_warnings? message = <<~MSG Ariadne: note that `#{preferred_tag}` is the preferred tag for `#{self.class.name}`; you passed `#{given_tag}` (which will still be used) MSG logger.warn(message) end given_tag end # TODO: test this def check_incoming_attribute(preferred_attribute, given_attribute) return preferred_attribute if given_attribute.blank? || preferred_attribute != given_attribute unless silence_warnings? message = <<~MSG Ariadne: note that `#{preferred_attribute}` is the preferred attribute for `#{self.class.name}`; you passed `#{given_attribute}` (which will still be used) MSG logger.warn(message) end given_attribute end # TODO: test this def check_incoming_value(preferred_value, given_pair) return preferred_value if given_pair.blank? || !given_pair.is_a?(Hash) given_key = given_pair.keys.first given_value = given_pair.values.first return preferred_value if given_value.blank? unless silence_warnings? message = <<~MSG Ariadne: note that `#{preferred_value}` is the preferred value for `#{given_key}` here; you passed `#{given_value}` (which will still be used) MSG logger.warn(message) end given_value end end end