# frozen_string_literal: true module Spree module Core # Wrapper for a value that can be different depending on the Solidus version # # Some configuration defaults can be added or changed when a new Solidus # version is released. This class encapsulates getting the correct value for a # given Solidus version. # # The way it works is you provide an initial value in time, plus the version # boundary where it got changed. Then you can fetch the value providing the # desired Solidus version: # # @example # value = VersionedValue.new(true, "3.0.0" => false) # value.call("2.7.0") # => true # value.call("3.0.0") # => false # value.call("3.1.0") # => false # # Remember that you must provide the exact boundary when a value got changed, # which could easily be during a pre-release: # # @example # value = VersionedValue.new(true, "3.0.0" => false) # value.call("3.0.0.alpha") # => true # # value = VersionedValue.new(true, "3.0.0.alpha" => false) # value.call("3.0.0.alpha") # => false # # Multiple boundaries can also be provided: # # @example # value = VersionedValue.new(0, "2.0.0" => 1, "3.0.0" => 2) # value.call("1.0.0") # => 0 # value.call("2.1.0") # => 1 # value.call("3.0.0") # => 2 class VersionedValue attr_reader :boundaries # @param initial_value [Any] # @param boundary [Hash] Map from version number to new value def initialize(initial_value, boundaries = {}) @boundaries = Hash[ { '0' => initial_value } .merge(boundaries) .transform_keys { |version| to_gem_version(version) } .sort ] end # @param solidus_version [String] def call(solidus_version = Spree.solidus_version) solidus_version = to_gem_version(solidus_version) boundaries.fetch( boundaries .keys .reduce do |target, following| if target <= solidus_version && solidus_version < following target else following end end ) end private def to_gem_version(string) Gem::Version.new(string) end end end end