Skip to content
This repository
tag: v1.2.0_RC1
Fetching contributors…

Cannot retrieve contributors at this time

file 128 lines (118 sloc) 3.929 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
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
    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 of capture being used in a .rhtml page:
      #
      # <% @greeting = capture do %>
      # Welcome To my shiny new web page!
      # <% end %>
      #
      # Example of capture being used in a .rxml page:
      #
      # @greeting = capture do
      # 'Welcome To my shiny new web page!'
      # end
      def capture(*args, &block)
        # execute the block
        begin
          buffer = eval("_erbout", block.binding)
        rescue
          buffer = nil
        end
        
        if buffer.nil?
          capture_block(*args, &block)
        else
          capture_erb_with_buffer(buffer, *args, &block)
        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.
      #
      # Example:
      #
      # <% content_for("header") do %>
      # alert('hello world')
      # <% end %>
      #
      # You can use yield :header anywhere in your templates.
      #
      # <%= yield :header %>
      #
      # NOTE: Beware that content_for is ignored in caches. So you shouldn't use it
      # for elements that are going to be fragment cached.
      #
      # 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
      # <tt><%= yield :footer %></tt>.
      def content_for(name, content = nil, &block)
        eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)"
      end

      private
        def capture_block(*args, &block)
          block.call(*args)
        end
      
        def capture_erb(*args, &block)
          buffer = eval("_erbout", block.binding)
          capture_erb_with_buffer(buffer, *args, &block)
        end
      
        def capture_erb_with_buffer(buffer, *args, &block)
          pos = buffer.length
          block.call(*args)
        
          # extract the block
          data = buffer[pos..-1]
        
          # replace it in the original with empty string
          buffer[pos..-1] = ''
        
          data
        end
      
        def erb_content_for(name, &block)
          eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_erb(&block)"
        end
      
        def block_content_for(name, &block)
          eval "@content_for_#{name} = (@content_for_#{name} || '') + capture_block(&block)"
        end
    end
  end
end
Something went wrong with that request. Please try again.