Sonntag, 30. August 2015

Render Rails layout partials!

In Ruby on Rails in general repetitions in views are eliminated by partials.
This works for most cases. Widgets or complex controls also often consist of an HTML skeleton that repeats itself. However, they also contain some content HTML that differs.
As an example, a modal dialog is used (people/_people.html.erb):

A modal dialog for other resources would look alike. They only would differ in the HTML within the modal body. The rest (header, footer, etc.) were just repetition. It therefore makes sense to extract the HTML skeleton into a partial.
The content can consist of any HTML. To pass it to the partial modal as a variable is not an option. But there is an elegant solution:
ActionView#render provides the option :layout. It is often used to render a page in a certain layout. But it also is intended to render a partial in a "Layout" (people/_people.html.erb):
<%= render layout: 'shared/modal' do %>
  <%= render @people %>
<% end %>
und das wiederverwendbare dialog widget (shared/_modal.html.erb):

The entire HTML skeleton was extracted into the partial. The content can be passed as a block and injected with yield to the right place.
Even more complex widgets can be shared with this approach.
For example, if the partial consumers require a more flexible set of buttons (besides the Cancel button), ActionView#content_for comes into play.
The extended partial shared/_modal.html.erb:

and the consumer template people/_people.html.erb:
<%= render layout: 'shared/modal' do %>
  <%= render @people %>
  <% content_for :buttons do %>
    <%= link_to 'print', people_path(format: :pdf) %>
  <% end %>
<% end %>
Further articles of interest:

Supported by Ruby 2.2.1, Ruby on Rails 4.2.1