Every view has a template, which is passed the values from the view’s exposures and then used to render the view output.
Save your template in one of the
paths configured in your view.
Templates follow a 3-part naming scheme:
namematches the view’s
formatis for matching the template with the view’s format
engineis the rendering engine to use with the template
An example is
index.html.slim, which would be found for a view controller with a
"index" and a
:html. This template would be rendered with the Slim template engine.
dry-view uses Tilt to render its templates, and relies upon Tilt’s auto-detection of rendering engine based on the template file’s extension. However, you should explicitly
require any engine gems that you intend to use.
Some Tilt-supplied template engines may not fully support dry-view's features (like implicit block capturing). Your view will raise an exception, along with instructions for resolving the issue, if Tilt provides a non-compatible engine.
The currently known problematic engines are:
- Erb, which requires the Erbse engine
- Haml, which requires the Hamlit::Block engine
Each template is rendered with its own scope, which determines the methods available within the template. The scope behavior is established by 3 things:
- The scope’s class, which is
Dry::View::Scopeby default, but can be changed for a template by specifying a class for the view’s
scopesetting, or for a partial rendering by using
#scopefrom within a part or scope method, or within the template itself
- The template’s locals, the exposure values decorated by their parts
- The context object
The template scope evaluates methods sent to it in this order:
- The scope's own methods are all available
- If there is a matching local, it is returned
- If the context object responds to the method, it is called, along with any arguments passed to the method.
<!-- `#asset_path` is defined on the context object --> <img src="<%= asset_path("header.png") %>"> <!-- `#page_title` is defined on the custom scope class --> <h1><%= page_title %></h1> <!-- `#users` is a local --> <% users.each do |user| %> <p><%= user.name %></p> <% end %>
The template scope provides a
#render method, for rendering partials:
<%= render :sidebar %>
The template for a partial is prefixed by an underscore and searched through a series of directories, including a directory named after the current template, as well as a "shared" directory.
So for a
sidebar partial, rendered within a
users/index.html.erb template, the partial would be searched for at the following locations in your view's configured paths:
If a matching partial template is not found in these locations, the search is repeated in each parent directory until the view path’s root is reached, e.g.:
A partial called with no arguments is rendered with the same scope as its parent template. This is useful for breaking larger templates up into smaller chunks for readability. For example:
<h1>About us</h1> <%# Split this template into 3 partials, all sharing the same scope %> <%= render :introduction %> <%= render :location %> <%= render :contact_form %>
Otherwise, partials accept keywords arguments, which become the partial’s locals. For example:
<%= render :contact_form, form_title: "Get in touch" %>
The view’s context object remains part of the scope for every partial rendering, regardless of the arguments passed.