require 'uri' module HeartlandRetail class Client ## # A wrapper around URI class URI ## # Returns a URI object based on the parsed string. # # @return [URI] def self.parse(value) return value.dup if value.is_a?(self) new(::URI.parse(value.to_s)) end ## # Creates a new URI object from an Addressable::URI # # @return [URI] def initialize(uri) @uri = uri end ## # Clones the URI object # # @return [URI] def dup self.class.new(@uri.dup) end ## # Returns a new URI with the given subpath appended to it. Ensures a single # forward slash between the URI's path and the given subpath. # # @return [URI] def subpath(subpath) uri = dup uri.path = "#{path}/" unless path.end_with?('/') escaped_subpath = ::URI::Parser.new.escape(subpath.to_s.gsub(/^\//, '')) uri.path = uri.path + escaped_subpath uri end ## # Merges the given hash of query string parameters and values with the URI's # existing query string parameters (if any). def merge_query_values!(values) old_query_values = self.query_values || {} self.query_values = old_query_values.merge(normalize_query_hash(values)) end ## # Checks if supplied URI matches current URI # # @return [boolean] def ==(other_uri) return false unless other_uri.is_a?(self.class) uri == other_uri.__send__(:uri) end ## # Overwrites the query using the supplied query values def query_values=(values) self.query = ::URI.encode_www_form(normalize_query_hash(values).sort) end ## # Returns a hash of query string parameters and values # # @return [hash] def query_values return nil if query.nil? ::URI.decode_www_form(query).each_with_object({}) do |(k, v), hash| if k.end_with?('[]') k.gsub!(/\[\]$/, '') hash[k] = Array(hash[k]) + [v] else hash[k] = v end end end private attr_reader :uri def self.delegate_and_wrap(*methods) methods.each do |method| define_method(method) do |*args, &block| @uri.__send__(method, *args, &block) end end end delegate_and_wrap( :path, :path=, :to_s, :query, :query= ) def normalize_query_hash(hash) hash.inject({}) do |copy, (k, v)| k = "#{k}[]" if v.is_a?(Array) && !k.to_s.end_with?('[]') copy[k.to_s] = normalize_query_value(v) copy end end def normalize_query_value(value) case value when Hash then normalize_query_hash(value) when true, false then value.to_s when Array then value.uniq else value end end end end end