Class: Flame::Router::Routes

Inherits:
Hash
  • Object
show all
Defined in:
lib/flame/router/routes.rb

Overview

Custom Hash for routes

Constant Summary collapse

PADDING_SIZE =
Router::HTTP_METHODS.map(&:size).max
PADDING_FORMAT =
"%#{PADDING_SIZE}.#{PADDING_SIZE}s".freeze

Instance Method Summary collapse

Constructor Details

#initialize(*path_parts) ⇒ Routes

Returns a new instance of Routes.

Examples:

Initialize without keys

Flame::Router::Routes.new # => {}

Initialize with nested keys

Flame::Router::Routes.new('/foo/bar/baz')
# => { 'foo' => { 'bar' => { 'baz' => {} } } }

Parameters:



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/flame/router/routes.rb', line 14

def initialize(*path_parts)
	super()

	path = Flame::Path.new(*path_parts)
	return if path.parts.empty?

	nested_routes = self.class.new Flame::Path.new(*path.parts[1..])
	# path.parts.reduce(result) do |hash, part|
	# 	hash[part] ||= self.class.new
	# end
	self[path.parts.first] = nested_routes
end

Instance Method Details

#[](key) ⇒ Flame::Router::Routes, ...

Move into Hash by equal key

Examples:

Move by static path part

routes = Flame::Router::Routes.new('/foo/bar/baz')
routes['foo'] # => { 'bar' => { 'baz' => {} } }

Move by HTTP-method

routes = Flame::Router::Routes.new('/foo/bar')
routes['foo']['bar'][:GET] = 42
routes['foo']['bar'][:GET] # => 42

Parameters:

Returns:



37
38
39
40
41
42
43
44
# File 'lib/flame/router/routes.rb', line 37

def [](key)
	if key.is_a? String
		key = Flame::Path::Part.new(key)
	elsif !key.is_a?(Flame::Path::Part) && !key.is_a?(Symbol)
		return
	end
	super
end

#allowObject



81
82
83
84
85
86
# File 'lib/flame/router/routes.rb', line 81

def allow
	methods = keys.select { |key| key.is_a? Symbol }
	return if methods.empty?

	methods.push(:OPTIONS).join(', ')
end

#dig_through_opt_argsFlame::Router::Routes

Dig through optional arguments as keys

Returns:



73
74
75
76
77
78
79
# File 'lib/flame/router/routes.rb', line 73

def dig_through_opt_args
	[
		self[first_opt_arg_key]&.dig_through_opt_args,
		self
	]
		.compact.find(&:first_route)
end

#first_routeFlame::Router::Route

Return the first available route (at the first level).

Returns:



48
49
50
# File 'lib/flame/router/routes.rb', line 48

def first_route
	values.find { |value| value.is_a?(Route) }
end

Navigate to Routes or Route through static parts or arguments

Examples:

Move by static path part and argument

routes = Flame::Router::Routes.new('/foo/:first/bar')
routes.navigate('foo', 'value') # => { 'bar' => {} }

Parameters:

Returns:



59
60
61
62
63
64
65
66
67
68
# File 'lib/flame/router/routes.rb', line 59

def navigate(*path_parts)
	path_parts = Flame::Path.new(*path_parts).parts
	return dig_through_opt_args if path_parts.empty?

	endpoint =
		self[path_parts.first] || dig(first_opt_arg_key, path_parts.first)

	endpoint&.navigate(*path_parts[1..]) ||
		find_among_arg_keys(path_parts[1..])
end

#sortObject

Sort routes for human readability



106
107
108
109
110
111
112
113
# File 'lib/flame/router/routes.rb', line 106

def sort
	sort_by do |key, _value|
		[
			key.is_a?(Symbol) ? Router::HTTP_METHODS.index(key) : Float::INFINITY,
			key.to_s
		]
	end
end

#to_s(prefix = '/') ⇒ Object

Output routes in human readable format



92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/flame/router/routes.rb', line 92

def to_s(prefix = '/')
	sort.map do |key, value|
		if key.is_a?(Symbol)
			<<~OUTPUT
				\e[1m#{format PADDING_FORMAT, key} #{prefix}\e[22m
				#{' ' * PADDING_SIZE} \e[3m\e[36m#{value}\e[0m\e[23m
			OUTPUT
		else
			value.to_s(Flame::Path.new(prefix, key))
		end
	end.join
end