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)
      "        \\e[1m\#{format PADDING_FORMAT, key} \#{prefix}\\e[22m\n        \#{' ' * PADDING_SIZE} \\e[3m\\e[36m\#{value}\\e[0m\\e[23m\n      OUTPUT\n    else\n      value.to_s(Flame::Path.new(prefix, key))\n    end\n  end.join\nend\n"