module ActionView::Helpers::CaptureHelper - actionpack-3.2.22 Documentation

# module ActionView::Helpers::CaptureHelper

CaptureHelper exposes methods to let you extract generated markup which can be used in other parts of a template or layout file.

It provides a method to capture blocks into variables through capture and a way to capture a block of markup for use in a layout through content_for.

### Public Instance Methods

capture(*args) { |*args| ... } click to toggle source

The capture method allows you to extract part of a template into a variable. You can then use this variable anywhere in your templates or layout.

#### Examples¶ ↑

The capture method can be used in ERB templates…

    <% @greeting = capture do %>
      Welcome to my shiny new web page!  The date and time is
      <%= Time.now %>
    <% end %>

…and Builder (RXML) templates.

    @timestamp = capture do
      "The current timestamp is #{Time.now}."
    end

You can then use that variable anywhere else. For example:

    <html>
    <head><title><%= @greeting %></title></head>
    <body>
    <b><%= @greeting %></b>
    </body></html>

    # File lib/action_view/helpers/capture_helper.rb, line 38
    def capture(*args)
      value = nil
      buffer = with_output_buffer { value = yield(*args) }
      if string = buffer.presence || value and string.is_a?(String)
        ERB::Util.html_escape string
      end
    end

content_for(name, content = nil, &block) click to toggle source

Calling #content_for stores a block of markup in an identifier for later use. You can make subsequent calls to the stored content in other templates, helper modules or the layout by passing the identifier as an argument to `content_for`.

Note: `yield` can still be used to retrieve the stored content, but calling `yield` doesn’t work in helper modules, while `content_for` does.

#### Examples¶ ↑

    <% content_for :not_authorized do %>
      alert('You are not authorized to do that!')
    <% end %>

You can then use `content_for :not_authorized` anywhere in your templates.

    <%= content_for :not_authorized if current_user.nil? %>

This is equivalent to:

    <%= yield :not_authorized if current_user.nil? %>

`content_for`, however, can also be used in helper modules.

    module StorageHelper
      def stored_content
        content_for(:storage) || "Your storage is empty"
      end
    end

This helper works just like normal helpers.

    <%= stored_content %>

You can use the `yield` syntax alongside an existing call to `yield` in a layout. For example:

    <%# This is the layout %>
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
      <title>My Website</title>
      <%= yield :script %>
    </head>
    <body>
      <%= yield %>
    </body>
    </html>

And now, we’ll create a view that has a `content_for` call that creates the `script` identifier.

    <%# This is our view %>
    Please login!

    <% content_for :script do %>
      <script type="text/javascript">alert('You are not authorized to view this page!')</script>
    <% end %>

Then, in another view, you could to do something like this:

    <%= link_to 'Logout', :action => 'logout', :remote => true %>

    <% content_for :script do %>
      <%= javascript_include_tag :defaults %>
    <% end %>

That will place `script` tags for your default set of JavaScript files on the page; this technique is useful if you’ll only be using these scripts in a few views.

Note that #content_for concatenates the blocks it is given for a particular identifier in order. For example:

    <% content_for :navigation do %>
      <li><%= link_to 'Home', :action => 'index' %></li>
    <% end %>

    <%#  Add some other content, or use a different template: %>

    <% content_for :navigation do %>
      <li><%= link_to 'Login', :action => 'login' %></li>
    <% end %>

Then, in another template or layout, this code would render both links in order:

    <ul><%= content_for :navigation %></ul>

Lastly, simple content can be passed as a parameter:

    <% content_for :script, javascript_include_tag(:defaults) %>

WARNING: #content_for is ignored in caches. So you shouldn’t use it for elements that will be fragment cached.

    # File lib/action_view/helpers/capture_helper.rb, line 136
    def content_for(name, content = nil, &block)
      if content || block_given?
        content = capture(&block) if block_given?
        @view_flow.append(name, content) if content
        nil
      else
        @view_flow.get(name)
      end
    end

content_for?(name) click to toggle source

#content_for? simply checks whether any content has been captured yet using #content_for Useful to render parts of your layout differently based on what is in your views.

#### Examples¶ ↑

Perhaps you will use different css in you layout if no #content_for :right_column

    <%# This is the layout %>
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
      <title>My Website</title>
      <%= yield :script %>
    </head>
    <body class="<%= content_for?(:right_col) ? 'one-column' : 'two-column' %>">
      <%= yield %>
      <%= yield :right_col %>
    </body>
    </html>

    # File lib/action_view/helpers/capture_helper.rb, line 175
    def content_for?(name)
      @view_flow.get(name).present?
    end

provide(name, content = nil, &block) click to toggle source

The same as `content_for` but when used with streaming flushes straight back to the layout. In other words, if you want to concatenate several times to the same buffer when rendering a given template, you should use `content_for`, if not, use `provide` to tell the layout to stop looking for more contents.

    # File lib/action_view/helpers/capture_helper.rb, line 151
    def provide(name, content = nil, &block)
      content = capture(&block) if block_given?
      result = @view_flow.append!(name, content) if content
      result unless content
    end