Variables

When we have dynamic content to serve, we want our URI to be dynamic as well. This can be easily achieved via path variables. They are defined with a colon, followed by a name (eg. :id).

Once an incoming request is forwarded to our endpoint, we can access the current value in our param’s action (params[:id]).

  1. get '/books/:id', to: 'books#show'

Multiple variables can be used in a path.

    It’s possible to specify constraints for each variable. The rule MUST be expressed as a regular expression. If a request can satisfy all of them, we’re good, otherwise a 404 is returned.

    1. get '/authors/:id', id: /\d+/, to: 'authors#show'

    Optional Tokens

    Imagine we want to serve static files from a user repository. It would be impossible to know in advance which files are stored and to prepare routes accordingly.

    To solve this problem, Hanami supports wildcard matching.

    1. get '/files/*', to: 'files#show'

    We can specify a unique name for each route, in order to generate paths from the router or to test them.

    1. root to: 'home#index'
    2. get '/hello', to: 'greet#index', as: :greeting

    When a Hanami application starts, it generates a Ruby module at the runtime under our application namespace: eg. Web.routes. We can use it to generate a relative or absolute URI for our route.

    1. Web.routes.path(:root) # => "/"
    2. Web.routes.url(:root) # => "http://localhost:2300/"
    3. Web.routes.path(:greeting) # => "/hello"
    4. Web.routes.url(:greeting) # => "http://localhost:2300/hello"

    Absolute URL generation is dependent on scheme, host and port settings in apps/web/application.rb.

    Routing Helpers

    Generating routes from Web.routes is helpful, because that module can be accessed from anywhere. However, this syntax is noisy.

    Hanami has routing helpers available as routes in: actions, views and templates.

    1. <%= routes.url(:greeting) %>

    Or

    1. <%= routes.greeting_path %>
    2. <%= routes.greeting_url %>
    1. namespace 'docs' do
    2. get '/installation', to: 'docs#installation'
    3. get '/usage', to: 'docs#usage'
    4. end
    5. # This will generate:
    6. #

    In case of legacy routes, we can handle HTTP redirects at the routing level.