Class: Syntropy::RoutingTree
- Inherits:
-
Object
- Object
- Syntropy::RoutingTree
- Defined in:
- lib/syntropy/routing_tree.rb
Overview
The RoutingTree class implements a file-based routing tree with support for static files, markdown files, ruby modules, parametric routes, subtree routes, nested middleware and error handlers.
A RoutingTree instance takes the given directory (root_dir) and constructs a tree of route entries corresponding to the directory’s contents. Finally, it generates an optimized router proc, which is used by the application to return a route entry for each incoming HTTP request.
Once initialized, the routing tree is immutable. When running Syntropy in watch mode, whenever a file or directory is changed, added or deleted, a new routing tree will be constructed, and the old one will be discarded.
File-based routing in Syntropy follows some simple rules:
-
Static files (anything other than markdown files or dynamic Ruby modules) are routed to according to their location in the file tree.
-
Index files with
.mdor.rbextension handle requests to their immediate containing directory. For example,/users/index.rbwill handle requests to/users. -
Index files with a ‘+` suffix will also handle requests to anywhere in their subtree. For example, `/users/index+.rb` will also handle requests to
/users/foo/bar. -
Other markdown and module files will handle requests to their bare name (that is, without the extension.) Thus,
/users/foo.rbwill handle requests to/users/foo. A route with a ‘+` suffix will also handle requests to the route’s subtree. Thus, ‘/users/foo+.rb` will also handle requests to/users/foo/bar. -
Parametric routes are implemented by enclosing the route name in square brackets. For example,
/processes/[proc_id]/index.rbwill handle requests to/posts/14etc. Parametric route parts can also be expressed as files, e.g./processes/[id]/sources/[src_id].rbwill handle requests to/posts/14/sources/42etc. The values for placeholders are added to the incoming request. Here too, a ‘+` suffix causes the route to also handle requests to its subtree. -
Directories and files whose names start with an underscore, e.g.
/_fooor/docs/_bar.rbare skipped and will not be added to the routing tree. This allows you to prevent access through the HTTP server to protected or internal modules or files.
Instance Attribute Summary collapse
-
#dynamic_map ⇒ Object
readonly
Returns the value of attribute dynamic_map.
-
#mount_path ⇒ Object
readonly
Returns the value of attribute mount_path.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#root_dir ⇒ Object
readonly
Returns the value of attribute root_dir.
-
#static_map ⇒ Object
readonly
Returns the value of attribute static_map.
Instance Method Summary collapse
-
#compute_clean_url_path(fn) ⇒ String
Computes a “clean” URL path for the given path.
-
#fn_to_rel_path(fn) ⇒ String
Converts filename to relative path.
-
#initialize(root_dir:, mount_path:, **env) ⇒ void
constructor
Initializes a new RoutingTree instance and computes the routing tree.
-
#mount_applet(path, applet) ⇒ void
Mounts the given applet on the routng tree at the given (absolute) mount path.
-
#router_proc ⇒ Proc
Returns the generated router proc for the routing tree.
Constructor Details
#initialize(root_dir:, mount_path:, **env) ⇒ void
Initializes a new RoutingTree instance and computes the routing tree
51 52 53 54 55 56 57 58 |
# File 'lib/syntropy/routing_tree.rb', line 51 def initialize(root_dir:, mount_path:, **env) @root_dir = root_dir @mount_path = mount_path @static_map = {} @dynamic_map = {} @env = env @root = compute_tree end |
Instance Attribute Details
#dynamic_map ⇒ Object (readonly)
Returns the value of attribute dynamic_map.
44 45 46 |
# File 'lib/syntropy/routing_tree.rb', line 44 def dynamic_map @dynamic_map end |
#mount_path ⇒ Object (readonly)
Returns the value of attribute mount_path.
44 45 46 |
# File 'lib/syntropy/routing_tree.rb', line 44 def mount_path @mount_path end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
44 45 46 |
# File 'lib/syntropy/routing_tree.rb', line 44 def root @root end |
#root_dir ⇒ Object (readonly)
Returns the value of attribute root_dir.
44 45 46 |
# File 'lib/syntropy/routing_tree.rb', line 44 def root_dir @root_dir end |
#static_map ⇒ Object (readonly)
Returns the value of attribute static_map.
44 45 46 |
# File 'lib/syntropy/routing_tree.rb', line 44 def static_map @static_map end |
Instance Method Details
#compute_clean_url_path(fn) ⇒ String
Computes a “clean” URL path for the given path. Modules and markdown are stripped of their extensions, and index file paths are also converted to the containing directory path. For example, the clean URL path for /foo/bar.rb is /foo/bar. The Clean URL path for /bar/baz/index.rb is /bar/baz.
74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/syntropy/routing_tree.rb', line 74 def compute_clean_url_path(fn) rel_path = fn.sub(@root_dir, '') case rel_path when /^(.*)\/index\.(md|rb|html)$/ Regexp.last_match(1).then { it == '' ? '/' : it } when /^(.*)\.(md|rb|html)$/ Regexp.last_match(1) else rel_path end end |
#fn_to_rel_path(fn) ⇒ String
Converts filename to relative path.
90 91 92 |
# File 'lib/syntropy/routing_tree.rb', line 90 def fn_to_rel_path(fn) fn.sub(/^#{Regexp.escape(@root_dir)}\//, '').sub(/\.[^\.]+$/, '') end |
#mount_applet(path, applet) ⇒ void
This method returns an undefined value.
Mounts the given applet on the routng tree at the given (absolute) mount path. This method must be called before the router proc is generated.
100 101 102 103 |
# File 'lib/syntropy/routing_tree.rb', line 100 def mount_applet(path, applet) path = rel_mount_path(path) mount_applet_on_tree(@root, path, applet) end |
#router_proc ⇒ Proc
Returns the generated router proc for the routing tree
63 64 65 |
# File 'lib/syntropy/routing_tree.rb', line 63 def router_proc @router_proc ||= generate_router_proc end |