Module: Roda::RodaPlugins::HashRoutes

Defined in:
lib/roda/plugins/hash_routes.rb

Overview

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.)

Defined Under Namespace

Modules: ClassMethods, RequestMethods Classes: DSL

Class Method Summary collapse

Class Method Details

.configure(app) ⇒ Object



177
178
179
# File 'lib/roda/plugins/hash_routes.rb', line 177

def self.configure(app)
  app.opts[:hash_routes_methods] ||= {}
end

.load_dependencies(app) ⇒ Object



172
173
174
175
# File 'lib/roda/plugins/hash_routes.rb', line 172

def self.load_dependencies(app)
  app.plugin :hash_branches
  app.plugin :hash_paths
end