A view is an object that’s responsible for rendering a template.

In a full stack Hanami application, an incoming HTTP request goes through the router, it instantiates and calls an action, which sets the status code and the headers for the response. The last bit is the body, which is set by the corresponding view’s output.

A Simple View

Hanami ships a generator for actions that creates a view and a template.

  1. $ hanami generate action web dashboard#index
  2. insert apps/web/config/routes.rb
  3. create spec/web/controllers/dashboard/index_spec.rb
  4. create apps/web/controllers/dashboard/index.rb
  5. create apps/web/views/dashboard/index.rb
  6. create apps/web/templates/dashboard/index.html.erb
  7. create spec/web/views/dashboard/index_spec.rb

Looking at those file names, we have an action called Web::Controllers::Dashboard::Index (read about actions naming). Our view has a similar name: Web::Views::Dashboard::Index.

Let’s examine the view:

  1. # apps/web/views/dashboard/index.rb
  2. module Web
  3. module Views
  4. module Dashboard
  5. class Index
  6. include Web::View
  7. end
  8. end
  9. end
  10. end

Naming

That file begins with a module declaration which is similar to the action naming structure. The only difference is that we use Views module instead of Controllers. All the views are nested under it. This module is generated at the runtime for us, when the application starts.

For a given application named Web, views are available under Web::Views.

This symmetry is really important at run time. After the action has finished its job, control passes to the framework which looks for the matching view.

For a given action named Web::Controllers::Home::Index which is handling a request, Hanami will look for a corresponding Web::Views::Home::Index view.

View Module

All the main Hanami components are mixins meant to be included. Because a Hanami Container can run multiple applications within the same Ruby process, the configurations of these different components should be kept separated.

In our example, we have a directive include Web::View. That means our view will behave according to the configuration of the Web application.

For a given application named Web, the view mixin to include is Web::View.