mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
144 lines
5.2 KiB
Ruby
144 lines
5.2 KiB
Ruby
module ActionView
|
|
module Helpers
|
|
# 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.
|
|
module CaptureHelper
|
|
# 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>
|
|
#
|
|
def capture(*args, &block)
|
|
# Return captured buffer in erb.
|
|
if block_called_from_erb?(block)
|
|
with_output_buffer { block.call(*args) }
|
|
else
|
|
# Return block result otherwise, but protect buffer also.
|
|
with_output_buffer { return block.call(*args) }
|
|
end
|
|
end
|
|
|
|
# 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 or the layout
|
|
# by passing the identifier as an argument to <tt>yield</tt>.
|
|
#
|
|
# ==== Examples
|
|
#
|
|
# <% content_for :not_authorized do %>
|
|
# alert('You are not authorized to do that!')
|
|
# <% end %>
|
|
#
|
|
# You can then use <tt>yield :not_authorized</tt> anywhere in your templates.
|
|
#
|
|
# <%= yield :not_authorized if current_user.nil? %>
|
|
#
|
|
# You can also use this syntax alongside an existing call to <tt>yield</tt> 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 <tt>script</tt> 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_remote 'Logout', :action => 'logout' %>
|
|
#
|
|
# <% content_for :script do %>
|
|
# <%= javascript_include_tag :defaults %>
|
|
# <% end %>
|
|
#
|
|
# That will place <script> tags for Prototype, Scriptaculous, and application.js (if it exists)
|
|
# 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><%= yield :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.
|
|
#
|
|
# The deprecated way of accessing a content_for block is to use an instance variable
|
|
# named <tt>@content_for_#{name_of_the_content_block}</tt>. The preferred usage is now
|
|
# <tt><%= yield :footer %></tt>.
|
|
def content_for(name, content = nil, &block)
|
|
ivar = "@content_for_#{name}"
|
|
content = capture(&block) if block_given?
|
|
instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}")
|
|
nil
|
|
end
|
|
|
|
# Use an alternate output buffer for the duration of the block.
|
|
# Defaults to a new empty string.
|
|
def with_output_buffer(buf = '') #:nodoc:
|
|
self.output_buffer, old_buffer = buf, output_buffer
|
|
yield
|
|
output_buffer
|
|
ensure
|
|
self.output_buffer = old_buffer
|
|
end
|
|
|
|
# Add the output buffer to the response body and start a new one.
|
|
def flush_output_buffer #:nodoc:
|
|
if output_buffer && output_buffer != ''
|
|
response.body_parts << output_buffer
|
|
self.output_buffer = ''
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|