aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG2
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb95
2 files changed, 97 insertions, 0 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index e1e86d3e55..3470e0ae14 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Added CaptureHelper with CaptureHelper#capture and CaptureHelper#content_for. See documentation in helper #837 [Tobias Luetke]
+
* Fixed :anchor use in url_for #821 [Nicholas Seckar]
* Removed the reliance on PATH_INFO as it was causing problems for caching and inhibited the new non-vhost support #822 [Nicholas Seckar]
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
new file mode 100644
index 0000000000..aba4a85355
--- /dev/null
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -0,0 +1,95 @@
+module ActionView
+ module Helpers
+ # Capture lets you extract parts of code into instance variables 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 store the
+ # fragment in a instance variable similar to @content_for_layout.
+ #
+ # 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">
+ # <%= @content_for_script %>
+ # </script>
+ # </head>
+ # <body>
+ # <%= @content_for_layout %>
+ # </body>
+ # </html>
+ #
+ # view.rhtml
+ #
+ # This page shows an alert box!
+ #
+ # <% content_for("script") do %>
+ # alert('hello world')
+ # <% end %>
+ #
+ # Normal view text
+ 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.
+ #
+ # Example:
+ #
+ # <% @greeting = capture do %>
+ # Welcome To my shiny new web page!
+ # <% end %>
+ def capture(&block)
+ # execute the block
+ buffer = eval("_erbout", block.binding)
+ pos = buffer.length
+ block.call
+
+ # extract the block
+ data = buffer[pos..-1]
+
+ # replace it in the original with empty string
+ buffer[pos..-1] = ''
+
+ data
+ end
+
+ # Content_for will store the given block
+ # in an instance variable for later use in another template
+ # or in the layout.
+ #
+ # The name of the instance variable is content_for_<name>
+ # to stay consistent with @content_for_layout which is used
+ # by ActionView's layouts
+ #
+ # Example:
+ #
+ # <% content_for("header") do %>
+ # alert('hello world')
+ # <% end %>
+ #
+ # You can use @content_for_header anywhere in your templates
+ def content_for(name, &block)
+ base = controller.instance_variable_get(instance_var_name(name)) || ""
+ data = capture(&block)
+ controller.instance_variable_set(instance_var_name(name), base + data)
+ data
+ end
+
+ private
+
+ def instance_var_name(name) #:nodoc#
+ "@content_for_#{name}"
+ end
+ end
+ end
+end