lib/page_magic/mapping.rb
# frozen_string_literal: true
require_relative '../active_support/core_ext/object/to_query'
require_relative 'comparator'
module PageMagic
# models mapping used to relate pages to uris
class Mapping
attr_reader :path, :parameters, :fragment
# @param [Object] path String or Regular expression to match with
# @param [Hash] parameters mapping of parameter name to literal or regex to match with
# @param [Object] fragment String or Regular expression to match with
# @raise [MatcherInvalidException] if at least one component is not specified
def initialize(path = nil, parameters: {}, fragment: nil)
raise MatcherInvalidException unless path || parameters || fragment
@path = Comparator.for(path)
@parameters = Comparator.for(parameters)
@fragment = Comparator.for(fragment)
end
# @return [Boolean] true if no component contains a Regexp
def can_compute_uri?
!fragment.fuzzy? && !path.fuzzy? && !parameters.fuzzy?
end
# @return [String] uri represented by this mapping
def compute_uri
path.to_s.dup.tap do |uri|
uri << "?#{parameters.comparator.to_query}" unless parameters.empty?
uri << "##{fragment}" if fragment.present?
end
end
# @return [Fixnum] hash for instance
def hash
[path, parameters, fragment].hash
end
# @param [String] uri
# @return [Boolean] returns true if the uri is matched against this matcher
def match?(uri)
uri = URI(uri)
path.match?(uri.path) && parameters.match?(parameters_hash(uri.query)) && fragment.match?(uri.fragment)
end
# compare this matcher against another
# @param [Mapping] other
# @return [Fixnum] -1 = smaller, 0 = equal to, 1 = greater than
def <=>(other)
path_comparison = path <=> other.path
return path_comparison unless path_comparison.zero?
parameter_comparison = parameters <=> other.parameters
return parameter_comparison unless parameter_comparison.zero?
fragment <=> other.fragment
end
# check equality
# @param [Mapping] other
# @return [Boolean]
def ==(other)
return false unless other.is_a?(Mapping)
path == other.path && parameters == other.parameters && fragment == other.fragment
end
alias eql? ==
private
def parameters_hash(string)
CGI.parse(string.to_s.downcase).collect { |key, value| [key.downcase, value.first] }.to_h
end
end
end