vendor/rails/actionpack/lib/action_view/helpers/capture_helper.rb in radiant-0.6.4 vs vendor/rails/actionpack/lib/action_view/helpers/capture_helper.rb in radiant-0.6.5
- old
+ new
@@ -1,106 +1,140 @@
module ActionView
module Helpers
- # Capture lets you extract parts of code which
- # can be used in other points of the template or even layout file.
- #
- # == Capturing a block into an instance variable
- #
- # <% @script = capture do %>
- # [some html...]
- # <% end %>
- #
- # == Add javascript to header using content_for
- #
- # content_for("name") is a wrapper for capture which will
- # make the fragment available by name to a yielding layout or template.
- #
- # layout.rhtml:
- #
- # <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
- # <head>
- # <title>layout with js</title>
- # <script type="text/javascript">
- # <%= yield :script %>
- # </script>
- # </head>
- # <body>
- # <%= yield %>
- # </body>
- # </html>
- #
- # view.rhtml
- #
- # This page shows an alert box!
- #
- # <% content_for("script") do %>
- # alert('hello world')
- # <% end %>
- #
- # Normal view text
+ # 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
- # Capture allows you to extract a part of the template into an
- # instance variable. You can use this instance variable anywhere
- # in your templates and even in your layout.
+ # 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.
#
- # Example of capture being used in a .rhtml page:
+ # ==== Examples
+ # The capture method can be used in ERb templates...
#
# <% @greeting = capture do %>
- # Welcome To my shiny new web page!
+ # Welcome to my shiny new web page! The date and time is
+ # <%= Time.now %>
# <% end %>
#
- # Example of capture being used in a .rxml page:
+ # ...and Builder (RXML) templates.
#
- # @greeting = capture do
- # 'Welcome To my shiny new web page!'
+ # @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)
# execute the block
begin
- buffer = eval("_erbout", block.binding)
+ buffer = eval(ActionView::Base.erb_variable, block.binding)
rescue
buffer = nil
end
if buffer.nil?
- capture_block(*args, &block)
+ capture_block(*args, &block).to_s
else
- capture_erb_with_buffer(buffer, *args, &block)
+ capture_erb_with_buffer(buffer, *args, &block).to_s
end
end
- # Calling content_for stores the block of markup for later use.
- # Subsequently, you can make calls to it by name with <tt>yield</tt>
- # in another template or in the layout.
+ # 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>.
#
- # Example:
+ # ==== Examples
#
- # <% content_for("header") do %>
- # alert('hello world')
+ # <% content_for :not_authorized do %>
+ # alert('You are not authorized to do that!')
# <% end %>
#
- # You can use yield :header anywhere in your templates.
+ # You can then use <tt>yield :not_authorized</tt> anywhere in your templates.
#
- # <%= yield :header %>
+ # <%= yield :not_authorized if current_user.nil? %>
#
- # NOTE: Beware that content_for is ignored in caches. So you shouldn't use it
- # for elements that are going to be fragment cached.
+ # You can also use this syntax alongside an existing call to <tt>yield</tt> in a layout. For example:
#
- # The deprecated way of accessing a content_for block was to use a instance variable
- # named @@content_for_#{name_of_the_content_block}@. So <tt><%= content_for('footer') %></tt>
- # would be avaiable as <tt><%= @content_for_footer %></tt>. The preferred notation now is
+ # <%# 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>. So <tt><%= content_for :footer %></tt>
+ # would be available as <tt><%= @content_for_footer %></tt>. The preferred usage is now
# <tt><%= yield :footer %></tt>.
def content_for(name, content = nil, &block)
- eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)"
+ existing_content_for = instance_variable_get("@content_for_#{name}").to_s
+ new_content_for = existing_content_for + (block_given? ? capture(&block) : content)
+ instance_variable_set("@content_for_#{name}", new_content_for)
end
private
def capture_block(*args, &block)
block.call(*args)
end
def capture_erb(*args, &block)
- buffer = eval("_erbout", block.binding)
+ buffer = eval(ActionView::Base.erb_variable, block.binding)
capture_erb_with_buffer(buffer, *args, &block)
end
def capture_erb_with_buffer(buffer, *args, &block)
pos = buffer.length