The hash_routes plugin builds on top of the hash_branches and hash_paths plugins, and adds a DSL
for configuring hash branches and paths. It also adds an r.hash_routes
method for first attempting dispatch to the configured hash_paths, then to the configured hash_branches:
class App < Roda plugin :hash_routes hash_branch("a") do |r| # /a branch end hash_branch("b") do |r| # /b branch end hash_path("/a") do |r| # /a path end hash_path("/a/b") do |r| # /a/b path end route do |r| r.hash_routes end end
With the above routing tree, requests for /a
and /a/b
will be routed to the appropriate hash_path
block. Other requests for the /a
branch, and all requests for the /b
branch will be routed to the appropriate hash_branch
block.
It is best for performance to explicitly specify the namespace when calling r.hash_routes
.
Because specifying routes explicitly using the hash_branch
and hash_path
class methods can get repetitive, the hash_routes plugin offers a DSL
for DRYing the code up. This DSL
is used by calling the hash_routes
class method. The DSL
used tries to mirror the standard Roda
DSL
, but it is not a normal routing tree (it’s not possible to execute arbitrary code between branches during routing).
class App < Roda plugin :hash_routes # No block argument is used, DSL evaluates block using instance_exec hash_routes "" do # on method is used for routing to next segment, # for similarity to standard Roda on "a" do |r| r.hash_routes '/a' end on "b" do |r| r.hash_routes(:b) end end # Block argument is used, block is yielded DSL instance hash_routes "/a" do |hr| # is method is used for routing to the remaining path, # for similarity to standard Roda hr.is "b" do |r| # /a/b path end hr.is "c" do |r| # /a/c path end end hash_routes :b do is "b" do |r| # /b/b path end is "c" do |r| # /b/c path end end route do |r| # No change here, DSL only makes setup DRYer r.hash_branches end end
The hash_routes
DSL
also offers some additional features to handle additional cases. It supports verb methods, such as get
and post
, which operate like is
, but are only called if the verb matches (and are not yielded the request). It supports a view
method for routes that only render views, as well as a views
method for setting up routes for multiple views in a single call, which is a good replacement for the multi_view
plugin. is
, view
, and the verb methods can use a value of true
for the empty remaining path (as the empty string specifies the "/"
remaining path). It also supports a dispatch_from
method, allowing you to setup dispatching to current group of routes from a higher-level namespace. The hash_routes
class method will return the DSL
instance, so you are not limited to using it with a block.
Here’s the above example modified to use some of these features:
class App < Roda plugin :hash_routes hash_routes "/a" do # Dispatch requests for the /a branch from the empty (default) routing # namespace to this namespace dispatch_from "a" # Handle GET /a path, render "a" template, returning 404 for non-GET requests view true, "a" # Handle /a/b path, returning 404 for non-GET requests get "b" do # GET /a/b path end # Handle /a/c path, returning 404 for non-POST requests post "c" do # POST /a/c path end end bhr = hash_routes(:b) # Dispatch requests for the /b branch from the empty routing to this namespace, # but first check routes in the :b_preauth namespace. If there is no # matching route in the :b_preauth namespace, call the check_authenticated! # method before dispatching to any of the routes in this namespace bhr.dispatch_from "", "b" do |r| r.hash_routes :b_preauth check_authenticated! end bhr.is true do |r| # /b path end bhr.is "" do |r| # /b/ path end # GET /b/d path, render 'd2' template, returning 404 for non-GET requests bhr.views 'd', 'd2' # GET /b/e path, render 'e' template, returning 404 for non-GET requests # GET /b/f path, render 'f' template, returning 404 for non-GET requests bhr.views %w'e f' route do |r| r.hash_branches end end
The view
and views
method depend on the render plugin being loaded, but this plugin does not load the render plugin. You must load the render plugin separately if you want to use the view
and views
methods.
Certain parts of the hash_routes
DSL
support do not work with the route_block_args plugin, as doing so would reduce performance. These are:
-
dispatch_from
-
view
-
views
-
all verb methods (get, post, etc.)
Classes and Modules
Public Class methods
# File lib/roda/plugins/hash_routes.rb 177 def self.configure(app) 178 app.opts[:hash_routes_methods] ||= {} 179 end
# File lib/roda/plugins/hash_routes.rb 172 def self.load_dependencies(app) 173 app.plugin :hash_branches 174 app.plugin :hash_paths 175 end