3 # CaptureHelper exposes methods to let you extract generated markup which
4 # can be used in other parts of a template or layout file.
5 # It provides a method to capture blocks into variables through capture and
6 # a way to capture a block of markup for use in a layout through content_for.
8 # The capture method allows you to extract part of a template into a
9 # variable. You can then use this variable anywhere in your templates or layout.
12 # The capture method can be used in ERb templates...
14 # <% @greeting = capture do %>
15 # Welcome to my shiny new web page! The date and time is
19 # ...and Builder (RXML) templates.
21 # @timestamp = capture do
22 # "The current timestamp is #{Time.now}."
25 # You can then use that variable anywhere else. For example:
28 # <head><title><%= @greeting %></title></head>
30 # <b><%= @greeting %></b>
33 def capture(*args
, &block
)
34 # Return captured buffer in erb.
35 if block_called_from_erb
?(block
)
36 with_output_buffer
{ block
.call(*args
) }
38 # Return block result otherwise, but protect buffer also.
39 with_output_buffer
{ return block
.call(*args
) }
43 # Calling content_for stores a block of markup in an identifier for later use.
44 # You can make subsequent calls to the stored content in other templates or the layout
45 # by passing the identifier as an argument to <tt>yield</tt>.
49 # <% content_for :not_authorized do %>
50 # alert('You are not authorized to do that!')
53 # You can then use <tt>yield :not_authorized</tt> anywhere in your templates.
55 # <%= yield :not_authorized if current_user.nil? %>
57 # You can also use this syntax alongside an existing call to <tt>yield</tt> in a layout. For example:
59 # <%# This is the layout %>
60 # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
62 # <title>My Website</title>
63 # <%= yield :script %>
70 # And now, we'll create a view that has a content_for call that
71 # creates the <tt>script</tt> identifier.
73 # <%# This is our view %>
76 # <% content_for :script do %>
77 # <script type="text/javascript">alert('You are not authorized to view this page!')</script>
80 # Then, in another view, you could to do something like this:
82 # <%= link_to_remote 'Logout', :action => 'logout' %>
84 # <% content_for :script do %>
85 # <%= javascript_include_tag :defaults %>
88 # That will place <script> tags for Prototype, Scriptaculous, and application.js (if it exists)
89 # on the page; this technique is useful if you'll only be using these scripts in a few views.
91 # Note that content_for concatenates the blocks it is given for a particular
92 # identifier in order. For example:
94 # <% content_for :navigation do %>
95 # <li><%= link_to 'Home', :action => 'index' %></li>
98 # <%# Add some other content, or use a different template: %>
100 # <% content_for :navigation do %>
101 # <li><%= link_to 'Login', :action => 'login' %></li>
104 # Then, in another template or layout, this code would render both links in order:
106 # <ul><%= yield :navigation %></ul>
108 # Lastly, simple content can be passed as a parameter:
110 # <% content_for :script, javascript_include_tag(:defaults) %>
112 # WARNING: content_for is ignored in caches. So you shouldn't use it
113 # for elements that will be fragment cached.
115 # The deprecated way of accessing a content_for block is to use an instance variable
116 # named <tt>@content_for_#{name_of_the_content_block}</tt>. The preferred usage is now
117 # <tt><%= yield :footer %></tt>.
118 def content_for(name
, content
= nil, &block
)
119 ivar
= "@content_for_#{name}"
120 content
= capture(&block
) if block_given
?
121 instance_variable_set(ivar
, "#{instance_variable_get(ivar)}#{content}")
125 # Use an alternate output buffer for the duration of the block.
126 # Defaults to a new empty string.
127 def with_output_buffer(buf
= '') #:nodoc:
128 self.output_buffer
, old_buffer
= buf
, output_buffer
132 self.output_buffer
= old_buffer