UtopiaSourceUtopiaPathMatcher

class Matcher

Performs structured, efficient, matches against class Utopia::Path instances. Supports regular expressions, type-casts and constants.

Example.

path = Utopia::Path['users/20/edit']
matcher = Utopia::Path::Matcher[users: /users/, id: Integer, action: String]
match_data = matcher.match(path)

Signature

Nested

Definitions

def initialize(patterns = [])

Implementation

def initialize(patterns = [])
	@patterns = patterns
end

def self.[](patterns)

Construct a matcher from typed named patterns.

Signature

parameter patterns Hash

The path rewrite patterns.

returns Matcher

The matcher.

Implementation

def self.[](patterns)
	self.new(patterns)
end

def coerce(klass, value)

Coerce.

Signature

parameter klass Class

The class to configure.

parameter value String

The captured text.

returns Object

The captured text coerced to klass.

Implementation

def coerce(klass, value)
	if klass == Integer
		Integer(value)
	elsif klass == Float
		Float(value)
	elsif klass == String
		value.to_s
	else
		klass.new(value)
	end
rescue
	return nil
end

def match(path)

This is a path prefix matching algorithm. The pattern is an array of String, Symbol, Regexp, or nil. The path is an array of String.

Implementation

def match(path)
	components = path.to_a
	
	# Can't possibly match if not enough components:
	return nil if components.size < @patterns.size
	
	named_parts = {}
	
	# Try to match each component against the pattern:
	@patterns.each_with_index do |(key, pattern), index|
		component = components[index]
		
		if pattern.is_a? Class
			return nil unless value = coerce(pattern, component)
			
			named_parts[key] = value
		elsif pattern
			if result = pattern.match(component)
				named_parts[key] = result
			else
				# Couldn't match:
				return nil
			end
		else
			# Ignore this part:
			named_parts[key] = component
		end
	end
	
	return MatchData.new(named_parts, components[@patterns.size..-1])
end