lennarb 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,99 +1,124 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
3
6
  module Lenna
4
- class Router
5
- # The Route::Builder class is responsible for building the tree of routes.
6
- #
7
- # The tree of routes is built by adding routes to the tree. Each route is
8
- # represented by a node in the tree and each node has a path and an
9
- # endpoint. The path is the path of the route and the endpoint is then
10
- # action to be executed when the route is matched.
11
- #
12
- # Those nodes are stored in a cache to avoid rebuilding the tree of routes
13
- # for each request.
14
- #
15
- # The tree use `Trie` data structures to optimize the search for a route.
16
- # The trie is a tree where each node is a character of the path.
17
- # This way, the search for a route is O(n) where n is the length of the
18
- # path.
19
- #
20
- class Builder
21
- def initialize(root_node) = @root_node = root_node
7
+ class Router
8
+ # The Route::Builder class is responsible for building the tree of routes.
9
+ #
10
+ # The tree of routes is built by adding routes to the tree. Each route is
11
+ # represented by a node in the tree and each node has a path and an
12
+ # endpoint. The path is the path of the route and the endpoint is then
13
+ # action to be executed when the route is matched.
14
+ #
15
+ # Those nodes are stored in a cache to avoid rebuilding the tree of routes
16
+ # for each request.
17
+ #
18
+ # The tree use `Trie` data structures to optimize the search for a route.
19
+ # The trie is a tree where each node is a character of the path.
20
+ # This way, the search for a route is O(n) where n is the length of the
21
+ # path.
22
+ #
23
+ # @private
24
+ #
25
+ class Builder
26
+ def initialize(root_node) = @root_node = root_node
22
27
 
23
- # @param method [String] the HTTP method
24
- # @param path [String] the path to be matched
25
- # @param action [Proc] the action to be executed
26
- # @param cache [Cache] the cache to be used
27
- # @return [void]
28
- def call(method, path, action, cache)
29
- path_key = cache.cache_key(method, path)
28
+ # This method will add a route to the tree of routes.
29
+ #
30
+ # @parameter method [String] the HTTP method
31
+ # @parameter path [String] the path to be matched
32
+ # @parameter action [Proc] the action to be executed
33
+ # @parameter cache [Cache] the cache to be used
34
+ #
35
+ # @return [void]
36
+ #
37
+ def call(method, path, action, cache)
38
+ path_key = cache.cache_key(method, path)
30
39
 
31
- return if cache.exist?(path_key)
40
+ return if cache.exist?(path_key)
32
41
 
33
- current_node = find_or_create_route_node(path)
34
- setup_endpoint(current_node, method, action)
42
+ current_node = find_or_create_route_node(path)
43
+ setup_endpoint(current_node, method, action)
35
44
 
36
- cache.add(path_key, current_node)
37
- end
45
+ cache.add(path_key, current_node)
46
+ end
38
47
 
39
- private
48
+ private
40
49
 
41
- # This method will create routes that are missing.
42
- # @param path [String] the path to be matched
43
- # @return [Node] the node that matches the path
44
- def find_or_create_route_node(path)
45
- current_node = @root_node
46
- split_path(path).each do |part|
47
- current_node = find_or_create_node(current_node, part)
48
- end
49
- current_node
50
- end
50
+ # This method will create routes that are missing.
51
+ # @parameter path [String] the path to be matched
52
+ #
53
+ # @return [Node] the node that matches the path
54
+ #
55
+ def find_or_create_route_node(path)
56
+ current_node = @root_node
57
+ split_path(path).each do |part|
58
+ current_node = find_or_create_node(current_node, part)
59
+ end
60
+ current_node
61
+ end
51
62
 
52
- # @param current_node [Node] the current node
53
- # @param part [String] the part of the path
54
- # @return [Node] the node that matches the part of the path
55
- # @note This method will create the nodes that are missing.
56
- # This way, the tree of routes is built.
57
- # @example Given the part ':id' and the tree bellow:
58
- # root
59
- # └── users
60
- # └── :id
61
- # The method will return the node :id.
62
- # If the node :id does not exist, it will be created.
63
- # The tree will be:
64
- # root
65
- # └── users
66
- # └── :id
67
- def find_or_create_node(current_node, part)
68
- if part.start_with?(':')
69
- # If it is a placeholder, then we just create or update
70
- # the placeholder node with the placeholder name.
71
- placeholder_name = part[1..].to_sym
72
- current_node.children[:placeholder] ||= Node.new(
73
- {},
74
- nil,
75
- placeholder_name
76
- )
77
- else
78
- current_node.children[part] ||= Node.new
79
- end
80
- current_node.children[part.start_with?(':') ? :placeholder : part]
81
- end
63
+ # This method will create the nodes that are missing.
64
+ #
65
+ # @parameter current_node [Node] the current node
66
+ # @parameter part [String] the part of the path
67
+ #
68
+ # @return [Node] the node that matches the part of the path
69
+ #
70
+ # This way, the tree of routes is built.
71
+ # @example Given the part ':id' and the tree bellow:
72
+ # root
73
+ # └── users
74
+ # └── :id
75
+ # The method will return the node :id.
76
+ # If the node :id does not exist, it will be created.
77
+ # The tree will be:
78
+ # root
79
+ # └── users
80
+ # └── :id
81
+ #
82
+ def find_or_create_node(current_node, part)
83
+ if part.start_with?(':')
84
+ # If it is a placeholder, then we just create or update
85
+ # the placeholder node with the placeholder name.
86
+ placeholder_name = part[1..].to_sym
87
+ current_node.children[:placeholder] ||= Node.new(
88
+ {},
89
+ nil,
90
+ placeholder_name
91
+ )
92
+ else
93
+ current_node.children[part] ||= Node.new
94
+ end
95
+ current_node.children[part.start_with?(':') ? :placeholder : part]
96
+ end
82
97
 
83
- # @param current_node [Node] the current node
84
- # @param method [String] the HTTP method
85
- # @param action [Proc] the action to be executed
86
- def setup_endpoint(current_node, method, action)
87
- current_node.endpoint ||= {}
88
- current_node.endpoint[method] = action
89
- end
98
+ # This method will setup the endpoint of the current node.
99
+ #
100
+ # @parameter current_node [Node] the current node
101
+ # @parameter method [String] the HTTP method
102
+ # @parameter action [Proc] the action to be executed
103
+ #
104
+ # @return [void]
105
+ #
106
+ def setup_endpoint(current_node, method, action)
107
+ current_node.endpoint ||= {}
108
+ current_node.endpoint[method] = action
109
+ end
90
110
 
91
- # @param path [String] the path to be split
92
- # @return [Array] the splitted path
93
- # @todo: Move this to a separate file and require it here.
94
- # Maybe utils or something like that.
95
- # Use Rack::Utils.split_path_info instead.
96
- def split_path(path) = path.split('/').reject(&:empty?)
97
- end
98
- end
111
+ # This method will split the path into parts.
112
+ #
113
+ # @parameter path [String] the path to be split
114
+ #
115
+ # @return [Array] the splitted path
116
+ #
117
+ # TODO: Move this to a separate file and require it here.
118
+ # Maybe utils or something like that.
119
+ # Use Rack::Utils.split_path_info instead.
120
+ #
121
+ def split_path(path) = path.split('/').reject(&:empty?)
122
+ end
123
+ end
99
124
  end
@@ -1,38 +1,52 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
3
6
  module Lenna
4
- class Router
5
- # @api public
6
- # @note This class is used to cache the routes.
7
- class Cache
8
- def initialize = @cache = {}
7
+ class Router
8
+ # This class is used to cache the routes.
9
+ #
10
+ # @private
11
+ #
12
+ class Cache
13
+ def initialize = @cache = {}
9
14
 
10
- # @api public
11
- # @param [String] method
12
- # @param [String] path
13
- # @return [String]
14
- # @note This method is used to generate a key for the cache.
15
- def cache_key(method, path) = "#{method} #{path}"
15
+ # This method is used to generate a key for the cache.
16
+ #
17
+ # @parameter [String] method
18
+ # @parameter [String] path
19
+ #
20
+ # @return [String]
21
+ #
22
+ def cache_key(method, path) = "#{method} #{path}"
16
23
 
17
- # @api public
18
- # @param route_key [String] The key for the route.
19
- # @param node [Lenna::Route::Node] The node for the route.
20
- # @return [Lenna::Route::Node]
21
- # @note This method is used to add a route to the cache.
22
- def add(route_key, node) = @cache[route_key] = node
24
+ # This method is used to add a route to the cache.
25
+ #
26
+ # @parameter route_key [String] The key for the route.
27
+ # @parameter node [Lenna::Route::Node] The node for the route.
28
+ #
29
+ # @return [Lenna::Route::Node]
30
+ #
31
+ def add(route_key, node) = @cache[route_key] = node
23
32
 
24
- # @api public
25
- # @param route_key [String] The key for the route.
26
- # @return [Lenna::Route::Node]
27
- # @note This method is used to get a route from the cache.
28
- def get(route_key) = @cache[route_key]
33
+ # This method is used to get a route from the cache.
34
+ #
35
+ # @parameter route_key [String] The key for the route.
36
+ #
37
+ # @return [Lenna::Route::Node]
38
+ #
39
+ def get(route_key) = @cache[route_key]
29
40
 
30
- # @api public
31
- # @param route_key [String] The key for the route.
32
- # @return [Boolean]
33
- # @note This method is used to check if a route exists
34
- # in the cache.
35
- def exist?(route_key) = @cache.key?(route_key)
36
- end
37
- end
41
+ # This method is used to check if a route is in the cache.
42
+ #
43
+ # @api public
44
+ #
45
+ # @parameter route_key [String] The key for the route.
46
+ #
47
+ # @return [Boolean]
48
+ #
49
+ def exist?(route_key) = @cache.key?(route_key)
50
+ end
51
+ end
38
52
  end
@@ -1,73 +1,77 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Released under the MIT License.
4
+ # Copyright, 2023, by Aristóteles Coutinho.
5
+
3
6
  module Lenna
4
- class Router
5
- # This class is used to manage the namespaces.
6
- #
7
- # @api private
8
- class NamespaceStack
9
- # @return [Array] The stack of namespaces
10
- #
11
- # @api private
12
- attr_reader :stack
7
+ class Router
8
+ # This class is used to manage the namespaces.
9
+ #
10
+ # @private `Since v0.1.0`
11
+ #
12
+ class NamespaceStack
13
+ # @return [Array] The stack of namespaces
14
+ #
15
+ # @private
16
+ #
17
+ attr_reader :stack
13
18
 
14
- # @return [void]
15
- #
16
- # @api private
17
- def initialize = @stack = ['']
19
+ # The initialize method is used to initialize the stack of namespaces.
20
+ #
21
+ # @private
22
+ #
23
+ # @attibute stack [Array] The stack of namespaces
24
+ #
25
+ # @return [void]
26
+ #
27
+ def initialize = @stack = ['']
18
28
 
19
- # This method is used to push a prefix to the stack.
20
- #
21
- # @param prefix [String] The prefix to be pushed
22
- # @return [void]
23
- #
24
- # @example:
25
- #
26
- # stack = NamespaceStack.new
27
- # stack.push('/users')
28
- # stack.current_prefix # => '/users'
29
- #
30
- # @see #resolve_prefix
31
- #
32
- # @api private
33
- def push(prefix)
34
- @stack.push(resolve_prefix(prefix))
35
- end
29
+ # This method is used to push a prefix to the stack.
30
+ #
31
+ # @parameter prefix [String] The prefix to be pushed
32
+ #
33
+ # @return [void]
34
+ #
35
+ # ex.
36
+ #
37
+ # stack = NamespaceStack.new
38
+ # stack.push('/users')
39
+ # stack.current_prefix # => '/users'
40
+ #
41
+ # @see #resolve_prefix
42
+ #
43
+ def push(prefix)
44
+ @stack.push(resolve_prefix(prefix))
45
+ end
36
46
 
37
- # @return [String] The popped prefix
38
- #
39
- # @api private
40
- def pop
41
- @stack.pop unless @stack.size == 1
42
- end
47
+ # This method is used to remove the last prefix from the stack.
48
+ #
49
+ # @return [String] The popped prefix
50
+ #
51
+ def pop
52
+ @stack.pop unless @stack.size == 1
53
+ end
43
54
 
44
- # @return [String] The current prefix
45
- #
46
- # @api private
47
- #
48
- # @since 0.1.0
49
- def current_prefix = @stack.last
55
+ # @return [String] The current prefix
56
+ #
57
+ def current_prefix = @stack.last
50
58
 
51
- # The to_s method is used to return the current prefix.
52
- #
53
- # @return [String] The current prefix
54
- #
55
- # @api private
56
- def to_s = current_prefix
59
+ # The to_s method is used to return the current prefix.
60
+ #
61
+ # @return [String] The current prefix
62
+ #
63
+ def to_s = current_prefix
57
64
 
58
- private
65
+ private
59
66
 
60
- # The resolve_prefix method is used to resolve the prefix.
61
- #
62
- # @param prefix [String] The prefix to be resolved
63
- # @return [String] The resolved prefix
64
- #
65
- # @see #current_prefix
66
- #
67
- # @since 0.1.0
68
- def resolve_prefix(prefix)
69
- current_prefix + prefix
70
- end
71
- end
72
- end
67
+ # The resolve_prefix method is used to resolve the prefix.
68
+ #
69
+ # @parameter prefix [String] The prefix to be resolved
70
+ # @return [String] The resolved prefix
71
+ #
72
+ def resolve_prefix(prefix)
73
+ current_prefix + prefix
74
+ end
75
+ end
76
+ end
73
77
  end