Module: Nanoc::Helpers::Rendering

Includes:
Capturing
Defined in:
lib/nanoc/helpers/rendering.rb

Overview

Provides functionality for rendering layouts as partials.

Instance Method Summary collapse

Methods included from Capturing

#capture, #content_for

Instance Method Details

#render(identifier, other_assigns = {}, &block) ⇒ String?

Renders the given layout. The given layout will be run through the first matching layout rule.

When this method is invoked without a block, the return value will be the rendered layout (a string) and _erbout will not be modified.

When this method is invoked with a block, an empty string will be returned and the rendered content will be appended to _erbout. In this case, the content of the block will be captured (using the Capturing helper) and this content will be made available with yield. In other words, a yield inside the partial will output the content of the block passed to the method.

(For the curious: the reason why #render with a block has this behaviour of returning an empty string and modifying _erbout is because ERB does not support combining the <%= ... %> form with a method call that takes a block.)

The assigns (@item, @config, …) will be available in the partial. It is also possible to pass custom assigns to the method; these assigns will be made available as instance variables inside the partial.

Examples:

Rendering a head and a foot partial around some text


<%= render 'head' %> - MIDDLE - <%= render 'foot' %>
# => "HEAD - MIDDLE - FOOT"

Rendering a head partial with a custom title


# The 'head' layout
<h1><%= @title %></h1>

# The item/layout where the partial is rendered
<%= render 'head', :title => 'Foo' %>
# => "<h1>Foo</h1>"

Yielding inside a partial


# The 'box' partial
<div class="box">
  <%= yield %>
</div>

# The item/layout where the partial is rendered
<% render 'box' do %>
  I'm boxy! Luvz!
<% end %>

# Result
<div class="box">
  I'm boxy! Luvz!
</div>

Parameters:

  • identifier (String)

    The identifier of the layout that should be rendered

  • other_assigns (Hash) (defaults to: {})

    A hash containing extra assigns that will be made available as instance variables in the partial

Returns:

  • (String, nil)

    The rendered partial, or nil if this method was invoked with a block

Raises:

  • (Nanoc::Int::Errors::UnknownLayout)

    if the given layout does not exist

  • (Nanoc::Int::Errors::CannotDetermineFilter)

    if there is no layout rule for the given layout

  • (Nanoc::Int::Errors::UnknownFilter)

    if the layout rule for the given layout specifies an unknown filter



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/nanoc/helpers/rendering.rb', line 76

def render(identifier, other_assigns = {}, &block)
  # Find layout
  layout = @layouts[identifier]
  layout ||= @layouts[identifier.__nanoc_cleaned_identifier]
  raise Nanoc::Int::Errors::UnknownLayout.new(identifier) if layout.nil?

  # Visit
  dependency_tracker = @config._context.dependency_tracker
  dependency_tracker.bounce(layout)

  # Capture content, if any
  captured_content = block_given? ? capture(&block) : nil

  # Get assigns
  assigns = {
    content: captured_content,
    item: @item,
    item_rep: @item_rep,
    items: @items,
    layout: layout,
    layouts: @layouts,
    config: @config,
  }.merge(other_assigns)

  # Get filter name
  filter_name, filter_args = *@config._context.compiler.filter_name_and_args_for_layout(layout)
  raise Nanoc::Int::Errors::CannotDetermineFilter.new(layout.identifier) if filter_name.nil?

  # Get filter class
  filter_class = Nanoc::Filter.named(filter_name)
  raise Nanoc::Int::Errors::UnknownFilter.new(filter_name) if filter_class.nil?

  # Create filter
  filter = filter_class.new(assigns)

  begin
    # Notify start
    Nanoc::Int::NotificationCenter.post(:processing_started, layout)

    # Layout
    content = layout.unwrap.content
    arg = content.binary? ? content.filename : content.string
    result = filter.setup_and_run(arg, filter_args)

    # Append to erbout if we have a block
    if block_given?
      # Append result and return nothing
      erbout = eval('_erbout', block.binding)
      erbout << result
      ''
    else
      # Return result
      result
    end
  ensure
    # Notify end
    Nanoc::Int::NotificationCenter.post(:processing_ended, layout)
  end
end