class Hanami::Router
Rack compatible, lightweight and fast HTTP Router
.
@since 0.1.0
@example It offers an intuitive DSL, that supports most of the HTTP verbs:
require 'hanami/router' endpoint = ->(env) { [200, {}, ['Welcome to Hanami::Router!']] } router = Hanami::Router.new do get '/', to: endpoint # => get and head requests post '/', to: endpoint put '/', to: endpoint patch '/', to: endpoint delete '/', to: endpoint options '/', to: endpoint trace '/', to: endpoint end
@example Specify an endpoint with `:to` (Rack compatible object)
require 'hanami/router' endpoint = ->(env) { [200, {}, ['Welcome to Hanami::Router!']] } router = Hanami::Router.new do get '/', to: endpoint end # :to is mandatory for the default resolver (`Hanami::Routing::EndpointResolver.new`), # This behavior can be changed by passing a custom resolver to `Hanami::Router#initialize`
@example Specify an endpoint with `:to` (controller and action string)
require 'hanami/router' router = Hanami::Router.new do get '/', to: 'articles#show' # => Articles::Show end # This is a builtin feature for a Hanami::Controller convention.
@example Specify a named route with `:as`
require 'hanami/router' endpoint = ->(env) { [200, {}, ['Welcome to Hanami::Router!']] } router = Hanami::Router.new(scheme: 'https', host: 'hanamirb.org') do get '/', to: endpoint, as: :root end router.path(:root) # => '/' router.url(:root) # => 'https://hanamirb.org/' # This isn't mandatory for the default route class (`Hanami::Routing::Route`), # This behavior can be changed by passing a custom route to `Hanami::Router#initialize`
@example Mount an application
require 'hanami/router' router = Hanami::Router.new do mount Api::App, at: '/api' end # All the requests starting with "/api" will be forwarded to Api::App
Constants
- ROOT_PATH
Defines root path
@since 0.7.0 @api private
@see
Hanami::Router#root
- VERSION
@since 0.1.0
Public Class Methods
Returns the given block as it is.
When Hanami::Router
is used as a standalone gem and the routes are defined into a configuration file, some systems could raise an exception.
Imagine the following file into a Ruby on Rails application:
get '/', to: 'api#index'
Because Ruby on Rails in production mode use to eager load code and the routes file uses top level method calls, it crashes the application.
If we wrap these routes with Hanami::Router.define
, the block doesn't get yielded but just returned to the caller as it is.
Usually the receiver of this block is Hanami::Router#initialize
, which finally evaluates the block.
@param blk [Proc] a set of route definitions
@return [Proc] the given block
@since 0.5.0
@example
# apps/web/config/routes.rb Hanami::Router.define do get '/', to: 'home#index' end
# File lib/hanami/router.rb, line 140 def self.define(&blk) blk end
Initialize the router.
@param options [Hash] the options to initialize the router
@option options [String] :scheme The HTTP scheme (defaults to `“http”`) @option options [String] :host The URL host (defaults to `“localhost”`) @option options [String] :port The URL port (defaults to `“80”`) @option options [Object, resolve, find, action_separator] :resolver
the route resolver (defaults to `Hanami::Routing::EndpointResolver.new`)
@option options [Object, generate] :route the route class
(defaults to `Hanami::Routing::Route`)
@option options [String] :action_separator the separator between controller
and action name (eg. 'dashboard#show', where '#' is the :action_separator)
@option options [Array<Symbol,String,Object mime_types, parse>] :parsers
the body parsers for mime types
@param blk [Proc] the optional block to define the routes
@return [Hanami::Router] self
@since 0.1.0
@example Basic example
require 'hanami/router' endpoint = ->(env) { [200, {}, ['Welcome to Hanami::Router!']] } router = Hanami::Router.new router.get '/', to: endpoint # or router = Hanami::Router.new do get '/', to: endpoint end
@example Body parsers
require 'json' require 'hanami/router' # It parses JSON body and makes the attributes available to the params endpoint = ->(env) { [200, {},[env['router.params'].inspect]] } router = Hanami::Router.new(parsers: [:json]) do patch '/books/:id', to: endpoint end # From the shell curl http://localhost:2300/books/1 \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{"published":"true"}' \ -X PATCH # It returns [200, {}, ["{:published=>\"true\",:id=>\"1\"}"]]
@example Custom body parser
require 'hanami/router' class XmlParser def mime_types ['application/xml', 'text/xml'] end # Parse body and return a Hash def parse(body) # ... end end # It parses XML body and makes the attributes available to the params endpoint = ->(env) { [200, {},[env['router.params'].inspect]] } router = Hanami::Router.new(parsers: [XmlParser.new]) do patch '/authors/:id', to: endpoint end # From the shell curl http://localhost:2300/authors/1 \ -H "Content-Type: application/xml" \ -H "Accept: application/xml" \ -d '<name>LG</name>' \ -X PATCH # It returns [200, {}, ["{:name=>\"LG\",:id=>\"1\"}"]]
# File lib/hanami/router.rb, line 237 def initialize(options = {}, &blk) @router = Routing::HttpRouter.new(options) define(&blk) end
Public Instance Methods
Resolve the given Rack env to a registered endpoint and invoke it.
@param env [Hash] a Rack env instance
@return [Rack::Response, Array]
@since 0.1.0
# File lib/hanami/router.rb, line 1018 def call(env) @router.call(env) end
To support defining routes in the `define` wrapper.
@param blk [Proc] the block to define the routes
@return [Hanami::Routing::Route]
@since 0.2.0
@example In Hanami
framework
class Application < Hanami::Application configure do routes 'config/routes' end end # In `config/routes` define do get # ... end
# File lib/hanami/router.rb, line 276 def define(&blk) instance_eval(&blk) if block_given? end
Check if there are defined routes
@return [TrueClass,FalseClass] the result of the check
@since 0.2.0 @api private
@example
router = Hanami::Router.new router.defined? # => false router = Hanami::Router.new { get '/', to: ->(env) { } } router.defined? # => true
# File lib/hanami/router.rb, line 294 def defined? @router.routes.any? end
Defines a route that accepts a DELETE request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.1.0
# File lib/hanami/router.rb, line 488 def delete(path, options = {}, &blk) @router.delete(path, options, &blk) end
Defines a route that accepts a GET request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@since 0.1.0
@example Fixed matching string
require 'hanami/router' router = Hanami::Router.new router.get '/hanami', to: ->(env) { [200, {}, ['Hello from Hanami!']] }
@example String matching with variables
require 'hanami/router' router = Hanami::Router.new router.get '/flowers/:id', to: ->(env) { [ 200, {}, ["Hello from Flower no. #{ env['router.params'][:id] }!"] ] }
@example Variables Constraints
require 'hanami/router' router = Hanami::Router.new router.get '/flowers/:id', id: /\d+/, to: ->(env) { [200, {}, [":id must be a number!"]] }
@example String matching with globbling
require 'hanami/router' router = Hanami::Router.new router.get '/*', to: ->(env) { [ 200, {}, ["This is catch all: #{ env['router.params'].inspect }!"] ] }
@example String matching with optional tokens
require 'hanami/router' router = Hanami::Router.new router.get '/hanami(.:format)', to: ->(env) { [200, {}, ["You've requested #{ env['router.params'][:format] }!"]] }
@example Named routes
require 'hanami/router' router = Hanami::Router.new(scheme: 'https', host: 'hanamirb.org') router.get '/hanami', to: ->(env) { [200, {}, ['Hello from Hanami!']] }, as: :hanami router.path(:hanami) # => "/hanami" router.url(:hanami) # => "https://hanamirb.org/hanami"
@example Duck typed endpoints (Rack compatible objects)
require 'hanami/router' router = Hanami::Router.new router.get '/hanami', to: ->(env) { [200, {}, ['Hello from Hanami!']] } router.get '/middleware', to: Middleware router.get '/rack-app', to: RackApp.new router.get '/method', to: ActionControllerSubclass.action(:new) # Everything that responds to #call is invoked as it is
@example Duck typed endpoints (strings)
require 'hanami/router' class RackApp def call(env) # ... end end router = Hanami::Router.new router.get '/hanami', to: 'rack_app' # it will map to RackApp.new
@example Duck typed endpoints (string: controller + action)
require 'hanami/router' module Flowers class Index def call(env) # ... end end end router = Hanami::Router.new router.get '/flowers', to: 'flowers#index' # It will map to Flowers::Index.new, which is the # Hanami::Controller convention.
# File lib/hanami/router.rb, line 412 def get(path, options = {}, &blk) @router.get(path, options, &blk) end
Returns an routes inspector
@since 0.2.0
@see Hanami::Routing::RoutesInspector
@example
require 'hanami/router' router = Hanami::Router.new do get '/', to: 'home#index' get '/login', to: 'sessions#new', as: :login post '/login', to: 'sessions#create' delete '/logout', to: 'sessions#destroy', as: :logout end puts router.inspector # => GET, HEAD / Home::Index login GET, HEAD /login Sessions::New POST /login Sessions::Create logout GET, HEAD /logout Sessions::Destroy
# File lib/hanami/router.rb, line 1216 def inspector require 'hanami/routing/routes_inspector' Routing::RoutesInspector.new(@router.routes, @router.prefix) end
Defines a route that accepts a LINK request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.8.0
# File lib/hanami/router.rb, line 526 def link(path, options = {}, &blk) @router.link(path, options, &blk) end
Mount a Rack application at the specified path. All the requests starting with the specified path, will be forwarded to the given application.
All the other methods (eg get
) support callable objects, but they restrict the range of the acceptable HTTP verb. Mounting an application with mount
doesn't apply this kind of restriction at the router level, but let the application to decide.
@param app [#call] a class or an object that responds to call
@param options [Hash] the options to customize the mount @option options [:at] the relative path where to mount the app
@since 0.1.1
@example Basic usage
require 'hanami/router' Hanami::Router.new do mount Api::App.new, at: '/api' end # Requests: # # GET /api # => 200 # GET /api/articles # => 200 # POST /api/articles # => 200 # GET /api/unknown # => 404
@example Difference between get
and mount
require 'hanami/router' Hanami::Router.new do get '/rack1', to: RackOne.new mount RackTwo.new, at: '/rack2' end # Requests: # # # /rack1 will only accept GET # GET /rack1 # => 200 (RackOne.new) # POST /rack1 # => 405 # # # /rack2 accepts all the verbs and delegate the decision to RackTwo # GET /rack2 # => 200 (RackTwo.new) # POST /rack2 # => 200 (RackTwo.new)
@example Types of mountable applications
require 'hanami/router' class RackOne def self.call(env) end end class RackTwo def call(env) end end class RackThree def call(env) end end module Dashboard class Index def call(env) end end end Hanami::Router.new do mount RackOne, at: '/rack1' mount RackTwo, at: '/rack2' mount RackThree.new, at: '/rack3' mount ->(env) {[200, {}, ['Rack Four']]}, at: '/rack4' mount 'dashboard#index', at: '/dashboard' end # 1. RackOne is used as it is (class), because it respond to .call # 2. RackTwo is initialized, because it respond to #call # 3. RackThree is used as it is (object), because it respond to #call # 4. That Proc is used as it is, because it respond to #call # 5. That string is resolved as Dashboard::Index (Hanami::Controller)
# File lib/hanami/router.rb, line 1007 def mount(app, options) @router.mount(app, options) end
Defines a Ruby block: all the routes defined within it will be namespaced with the given relative path.
Namespaces blocks can be nested multiple times.
@param namespace [String] the relative path where the nested routes will
be mounted
@param blk [Proc] the block that defines the resources
@return [Hanami::Routing::Namespace] the generated namespace.
@since 0.1.0
@see Hanami::Router
@example Basic example
require 'hanami/router' Hanami::Router.new do namespace 'trees' do get '/sequoia', to: endpoint # => '/trees/sequoia' end end
@example Nested namespaces
require 'hanami/router' Hanami::Router.new do namespace 'animals' do namespace 'mammals' do get '/cats', to: endpoint # => '/animals/mammals/cats' end end end
@example
require 'hanami/router' router = Hanami::Router.new router.namespace 'trees' do get '/sequoia', to: endpoint # => '/trees/sequoia' end
# File lib/hanami/router.rb, line 673 def namespace(namespace, &blk) Routing::Namespace.new(self, namespace, &blk) end
Defines a route that accepts a OPTIONS request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.1.0
# File lib/hanami/router.rb, line 594 def options(path, options = {}, &blk) @router.options(path, options, &blk) end
Defines a route that accepts a PATCH request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.1.0
# File lib/hanami/router.rb, line 469 def patch(path, options = {}, &blk) @router.patch(path, options, &blk) end
Generate an relative URL for a specified named route. The additional arguments will be used to compose the relative URL - in
case it has tokens to match - and for compose the query string.
@param route [Symbol] the route name
@return [String]
@raise [Hanami::Routing::InvalidRouteException] when the router fails to
recognize a route, because of the given arguments.
@since 0.1.0
@example
require 'hanami/router' router = Hanami::Router.new(scheme: 'https', host: 'hanamirb.org') router.get '/login', to: 'sessions#new', as: :login router.get '/:name', to: 'frameworks#show', as: :framework router.path(:login) # => "/login" router.path(:login, return_to: '/dashboard') # => "/login?return_to=%2Fdashboard" router.path(:framework, name: 'router') # => "/router"
# File lib/hanami/router.rb, line 1164 def path(route, *args) @router.path(route, *args) end
Defines a route that accepts a POST request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.1.0
# File lib/hanami/router.rb, line 431 def post(path, options = {}, &blk) @router.post(path, options, &blk) end
Defines a route that accepts a PUT request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.1.0
# File lib/hanami/router.rb, line 450 def put(path, options = {}, &blk) @router.put(path, options, &blk) end
Recognize the given env, path, or name and return a route for testing inspection.
If the route cannot be recognized, it still returns an object for testing inspection.
@param env [Hash, String, Symbol] Rack env, path or route name @param options [Hash] a set of options for Rack env or route params @param params [Hash] a set of params
@return [Hanami::Routing::RecognizedRoute] the recognized route
@since 0.5.0
@see Hanami::Router#env_for
@see Hanami::Routing::RecognizedRoute
@example Successful Path Recognition
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize('/books/23') route.verb # => "GET" (default) route.routable? # => true route.params # => {:id=>"23"}
@example Successful Rack Env Recognition
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize(Rack::MockRequest.env_for('/books/23')) route.verb # => "GET" (default) route.routable? # => true route.params # => {:id=>"23"}
@example Successful Named Route Recognition
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize(:book, id: 23) route.verb # => "GET" (default) route.routable? # => true route.params # => {:id=>"23"}
@example Failing Recognition For Unknown Path
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize('/books') route.verb # => "GET" (default) route.routable? # => false
@example Failing Recognition For Path With Wrong HTTP Verb
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize('/books/23', method: :post) route.verb # => "POST" route.routable? # => false
@example Failing Recognition For Rack Env With Wrong HTTP Verb
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize(Rack::MockRequest.env_for('/books/23', method: :post)) route.verb # => "POST" route.routable? # => false
@example Failing Recognition Named Route With Wrong Params
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize(:book) route.verb # => "GET" (default) route.routable? # => false
@example Failing Recognition Named Route With Wrong HTTP Verb
require 'hanami/router' router = Hanami::Router.new do get '/books/:id', to: 'books#show', as: :book end route = router.recognize(:book, {method: :post}, {id: 1}) route.verb # => "POST" route.routable? # => false route.params # => {:id=>"1"}
# File lib/hanami/router.rb, line 1130 def recognize(env, options = {}, params = nil) require 'hanami/routing/recognized_route' env = env_for(env, options, params) responses, _ = *@router.recognize(env) Routing::RecognizedRoute.new( responses.nil? ? responses : responses.first, env, @router) end
Defines an HTTP redirect
@param path [String] the path that needs to be redirected @param options [Hash] the options to customize the redirect behavior @option options [Fixnum] the HTTP status to return (defaults to `301`)
@return [Hanami::Routing::Route] the generated route.
This may vary according to the `:route` option passed to the initializer
@since 0.1.0
@see Hanami::Router
@example
require 'hanami/router' Hanami::Router.new do redirect '/legacy', to: '/new_endpoint' redirect '/legacy2', to: '/new_endpoint2', code: 302 end
@example
require 'hanami/router' router = Hanami::Router.new router.redirect '/legacy', to: '/new_endpoint'
# File lib/hanami/router.rb, line 624 def redirect(path, options = {}, &endpoint) destination_path = @router.find(options) get(path).redirect(destination_path, options[:code] || 301).tap do |route| route.dest = Hanami::Routing::RedirectEndpoint.new(destination_path, route.dest) end end
Defines a set of named routes for a single RESTful resource. It has a built-in integration for Hanami::Controller.
@param name [String] the name of the resource @param options [Hash] a set of options to customize the routes @option options [Array<Symbol>] :only a subset of the default routes
that we want to generate
@option options [Array<Symbol>] :except prevent the given routes to be
generated
@param blk [Proc] a block of code to generate additional routes
@return [Hanami::Routing::Resource]
@since 0.1.0
@see Hanami::Routing::Resource
@see Hanami::Routing::Resource::Action
@see Hanami::Routing::Resource::Options
@example Default usage
require 'hanami/router' Hanami::Router.new do resource 'identity' end # It generates: # # +--------+----------------+-------------------+----------+----------------+ # | Verb | Path | Action | Name | Named Route | # +--------+----------------+-------------------+----------+----------------+ # | GET | /identity | Identity::Show | :show | :identity | # | GET | /identity/new | Identity::New | :new | :new_identity | # | POST | /identity | Identity::Create | :create | :identity | # | GET | /identity/edit | Identity::Edit | :edit | :edit_identity | # | PATCH | /identity | Identity::Update | :update | :identity | # | DELETE | /identity | Identity::Destroy | :destroy | :identity | # +--------+----------------+-------------------+----------+----------------+
@example Limit the generated routes with :only
require 'hanami/router' Hanami::Router.new do resource 'identity', only: [:show, :new, :create] end # It generates: # # +--------+----------------+------------------+----------+----------------+ # | Verb | Path | Action | Name | Named Route | # +--------+----------------+------------------+----------+----------------+ # | GET | /identity | Identity::Show | :show | :identity | # | GET | /identity/new | Identity::New | :new | :new_identity | # | POST | /identity | Identity::Create | :create | :identity | # +--------+----------------+------------------+----------+----------------+
@example Limit the generated routes with :except
require 'hanami/router' Hanami::Router.new do resource 'identity', except: [:edit, :update, :destroy] end # It generates: # # +--------+----------------+------------------+----------+----------------+ # | Verb | Path | Action | Name | Named Route | # +--------+----------------+------------------+----------+----------------+ # | GET | /identity | Identity::Show | :show | :identity | # | GET | /identity/new | Identity::New | :new | :new_identity | # | POST | /identity | Identity::Create | :create | :identity | # +--------+----------------+------------------+----------+----------------+
@example Additional single routes
require 'hanami/router' Hanami::Router.new do resource 'identity', only: [] do member do patch 'activate' end end end # It generates: # # +--------+--------------------+--------------------+------+--------------------+ # | Verb | Path | Action | Name | Named Route | # +--------+--------------------+--------------------+------+--------------------+ # | PATCH | /identity/activate | Identity::Activate | | :activate_identity | # +--------+--------------------+--------------------+------+--------------------+
@example Additional collection routes
require 'hanami/router' Hanami::Router.new do resource 'identity', only: [] do collection do get 'keys' end end end # It generates: # # +------+----------------+----------------+------+----------------+ # | Verb | Path | Action | Name | Named Route | # +------+----------------+----------------+------+----------------+ # | GET | /identity/keys | Identity::Keys | | :keys_identity | # +------+----------------+----------------+------+----------------+
# File lib/hanami/router.rb, line 795 def resource(name, options = {}, &blk) Routing::Resource.new(self, name, options.merge(separator: @router.action_separator), &blk) end
Defines a set of named routes for a plural RESTful resource. It has a built-in integration for Hanami::Controller.
@param name [String] the name of the resource @param options [Hash] a set of options to customize the routes @option options [Array<Symbol>] :only a subset of the default routes
that we want to generate
@option options [Array<Symbol>] :except prevent the given routes to be
generated
@param blk [Proc] a block of code to generate additional routes
@return [Hanami::Routing::Resources]
@since 0.1.0
@see Hanami::Routing::Resources
@see Hanami::Routing::Resources::Action
@see Hanami::Routing::Resource::Options
@example Default usage
require 'hanami/router' Hanami::Router.new do resources 'articles' end # It generates: # # +--------+--------------------+-------------------+----------+----------------+ # | Verb | Path | Action | Name | Named Route | # +--------+--------------------+-------------------+----------+----------------+ # | GET | /articles | Articles::Index | :index | :articles | # | GET | /articles/:id | Articles::Show | :show | :articles | # | GET | /articles/new | Articles::New | :new | :new_articles | # | POST | /articles | Articles::Create | :create | :articles | # | GET | /articles/:id/edit | Articles::Edit | :edit | :edit_articles | # | PATCH | /articles/:id | Articles::Update | :update | :articles | # | DELETE | /articles/:id | Articles::Destroy | :destroy | :articles | # +--------+--------------------+-------------------+----------+----------------+
@example Limit the generated routes with :only
require 'hanami/router' Hanami::Router.new do resources 'articles', only: [:index] end # It generates: # # +------+-----------+-----------------+--------+-------------+ # | Verb | Path | Action | Name | Named Route | # +------+-----------+-----------------+--------+-------------+ # | GET | /articles | Articles::Index | :index | :articles | # +------+-----------+-----------------+--------+-------------+
@example Limit the generated routes with :except
require 'hanami/router' Hanami::Router.new do resources 'articles', except: [:edit, :update] end # It generates: # # +--------+--------------------+-------------------+----------+----------------+ # | Verb | Path | Action | Name | Named Route | # +--------+--------------------+-------------------+----------+----------------+ # | GET | /articles | Articles::Index | :index | :articles | # | GET | /articles/:id | Articles::Show | :show | :articles | # | GET | /articles/new | Articles::New | :new | :new_articles | # | POST | /articles | Articles::Create | :create | :articles | # | DELETE | /articles/:id | Articles::Destroy | :destroy | :articles | # +--------+--------------------+-------------------+----------+----------------+
@example Additional single routes
require 'hanami/router' Hanami::Router.new do resources 'articles', only: [] do member do patch 'publish' end end end # It generates: # # +--------+-----------------------+-------------------+------+-------------------+ # | Verb | Path | Action | Name | Named Route | # +--------+-----------------------+-------------------+------+-------------------+ # | PATCH | /articles/:id/publish | Articles::Publish | | :publish_articles | # +--------+-----------------------+-------------------+------+-------------------+
@example Additional collection routes
require 'hanami/router' Hanami::Router.new do resources 'articles', only: [] do collection do get 'search' end end end # It generates: # # +------+------------------+------------------+------+------------------+ # | Verb | Path | Action | Name | Named Route | # +------+------------------+------------------+------+------------------+ # | GET | /articles/search | Articles::Search | | :search_articles | # +------+------------------+------------------+------+------------------+
# File lib/hanami/router.rb, line 918 def resources(name, options = {}, &blk) Routing::Resources.new(self, name, options.merge(separator: @router.action_separator), &blk) end
Defines a root route (a GET route for '/')
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@since 0.7.0
@example Fixed matching string
require 'hanami/router' router = Hanami::Router.new router.root to: ->(env) { [200, {}, ['Hello from Hanami!']] }
@example Included names as `root` (for path and url helpers)
require 'hanami/router' router = Hanami::Router.new(scheme: 'https', host: 'hanamirb.org') router.root to: ->(env) { [200, {}, ['Hello from Hanami!']] } router.path(:root) # => "/" router.url(:root) # => "https://hanamirb.org/"
# File lib/hanami/router.rb, line 575 def root(options = {}, &blk) @router.get(ROOT_PATH, options.merge(as: :root), &blk) end
Returns self
This is a duck-typing trick for compatibility with `Hanami::Application`. It's used by `Hanami::Routing::RoutesInspector` to inspect both apps and routers.
@return [self]
@since 0.2.0 @api private
# File lib/hanami/router.rb, line 252 def routes self end
Defines a route that accepts a TRACE request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.1.0
# File lib/hanami/router.rb, line 507 def trace(path, options = {}, &blk) @router.trace(path, options, &blk) end
Defines a route that accepts an UNLINK request for the given path.
@param path [String] the relative URL to be matched
@param options [Hash] the options to customize the route @option options [String,Proc,Class,Object#call] :to the endpoint
@param blk [Proc] the anonymous proc to be used as endpoint for the route
@return [Hanami::Routing::Route] this may vary according to the :route
option passed to the constructor
@see Hanami::Router#get
@since 0.8.0
# File lib/hanami/router.rb, line 545 def unlink(path, options = {}, &blk) @router.unlink(path, options, &blk) end
Generate a URL for a specified named route. The additional arguments will be used to compose the relative URL - in
case it has tokens to match - and for compose the query string.
@param route [Symbol] the route name
@return [String]
@raise [Hanami::Routing::InvalidRouteException] when the router fails to
recognize a route, because of the given arguments.
@since 0.1.0
@example
require 'hanami/router' router = Hanami::Router.new(scheme: 'https', host: 'hanamirb.org') router.get '/login', to: 'sessions#new', as: :login router.get '/:name', to: 'frameworks#show', as: :framework router.url(:login) # => "https://hanamirb.org/login" router.url(:login, return_to: '/dashboard') # => "https://hanamirb.org/login?return_to=%2Fdashboard" router.url(:framework, name: 'router') # => "https://hanamirb.org/router"
# File lib/hanami/router.rb, line 1191 def url(route, *args) @router.url(route, *args) end
Protected Instance Methods
Fabricate Rack env for the given Rack env, path or named route
@param env [Hash, String, Symbol] Rack env, path or route name @param options [Hash] a set of options for Rack env or route params @param params [Hash] a set of params
@return [Hash] Rack env
@since 0.5.0 @api private
@see Hanami::Router#recognize
@see www.rubydoc.info/github/rack/rack/Rack%2FMockRequest.env_for
# File lib/hanami/router.rb, line 1236 def env_for(env, options = {}, params = nil) env = case env when String Rack::MockRequest.env_for(env, options) when Symbol begin url = path(env, params || options) return env_for(url, options) rescue Hanami::Routing::InvalidRouteException {} end else env end end