Class: Mustermann::Router

Inherits:
Object
  • Object
show all
Defined in:
lib/mustermann/router.rb

Overview

An extremely simple, Rack-compatible router implementation using Set for pattern matching.

Examples:

Basic usage

require 'mustermann/router'

router = Mustermann::Router.new do
  get "/hello/:name" do |env|
    name = env["mustermann.match"][:name]
    [200, { "content-type" => "text/plain" }, ["Hello, #{name}!"]]
  end
end

# in config.ru
run router

Routing to other applications

router = Mustermann::Router.new do
  get  "/users",     MyApp::Users::Index
  get  "/users/:id", MyApp::Users::Show
  post "/users",     MyApp::Users::Create
  fallback           MyApp::NotFound
end

router.path_for(MyApp::Users::Show, id: 42) # => "/users/42"

As middleware

use Mustermann::Router do
  get("/up") { [200, { "Content-Type" => "text/plain" }, ["Up!"]] }
end

run MyApp

See Also:

Instance Method Summary collapse

Constructor Details

#initialize(fallback = nil, key: "mustermann.match", **options, &block) ⇒ Router

Initializes a new router.

Parameters:

  • key (String) (defaults to: "mustermann.match")

    The key under which the route match will be stored in the Rack environment hash (default: “mustermann.match”).

  • options (Hash)

    Options to be passed to the Mustermann patterns.



48
49
50
51
52
53
54
# File 'lib/mustermann/router.rb', line 48

def initialize(fallback = nil, key: "mustermann.match", **options, &block)
  @key      = key
  @sets     = VERBS.to_h { |verb| [verb, Set.new] }
  @options  = options
  @fallback = fallback || ->(env) { NOT_FOUND.dup }
  instance_exec(&block) if block_given?
end

Instance Method Details

#call(env) ⇒ Array

Returns The Rack response array (status, headers, body).

Parameters:

  • env (Hash)

    The Rack environment hash for the request.

Returns:

  • (Array)

    The Rack response array (status, headers, body).



58
59
60
61
62
63
64
# File 'lib/mustermann/router.rb', line 58

def call(env)
  if routes = @sets[env["REQUEST_METHOD"]] and match = routes.match(env["PATH_INFO"] || "/")
    env = env.merge(@key => match)
    return match.value.call(env)
  end
  @fallback.call(env)
end

#fallback(fallback = nil, &block) ⇒ Object



66
# File 'lib/mustermann/router.rb', line 66

def fallback(fallback = nil, &block) = @fallback = fallback || block || @fallback

#path_for(app, behavior = nil, params = {}) ⇒ String

Helps generate links

Parameters:

  • app (#call)

    The Rack application or middleware for which to generate the path.

  • behavior (Symbol) (defaults to: nil)

    What to do with additional key/value pairs not present in the values hash. Possible options: :raise, :ignore, :append.

  • values (Hash{Symbol: #to_s, Array<#to_s>})

    Values to use for expansion.

Returns:

  • (String)

    The generated path.



90
91
92
93
# File 'lib/mustermann/router.rb', line 90

def path_for(app, behavior = nil, params = {})
  set = @sets.values.find { |s| s.has_value?(app) } || @sets[VERBS.first]
  set.expand(app, behavior, params)
end

#route(verb, pattern, target = nil, **options) {|env| ... } ⇒ void

Note:

Shorthand methods, like ‘get`, `post`, etc. dynamically are defined for all supported verbs.

This method returns an undefined value.

Adds a route for the given verb and pattern, with the given target.

Parameters:

  • verb (String)

    HTTP verb (e.g. “GET”, “POST”)

  • pattern (String, Mustermann::Pattern)

    Pattern string or Mustermann pattern (e.g. “/users/:id”)

  • target (#call, nil) (defaults to: nil)

    The Rack application or middleware to call when the route matches. Can be passed a block as well.

Yields:

  • (env)

    Block to be used as the target if no explicit target is given.

Yield Parameters:

  • env (Hash)

    The Rack environment hash for the request.

Raises:

  • (ArgumentError)


78
79
80
81
82
83
# File 'lib/mustermann/router.rb', line 78

def route(verb, pattern, target = nil, **options, &block)
  raise ArgumentError, "need to provide target, :to or a block" unless target || block
  raise ArgumentError, "unknown verb: #{verb}" unless VERBS.include?(verb)
  pattern = Mustermann.new(pattern, **@options, **options)
  @sets[verb].add(pattern, target || block)
end