aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r--actionpack/lib/action_view/base.rb23
-rw-r--r--actionpack/lib/action_view/helpers/capture_helper.rb55
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb14
-rw-r--r--actionpack/lib/action_view/helpers/javascript_helper.rb28
-rw-r--r--actionpack/lib/action_view/helpers/prototype_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/record_tag_helper.rb5
-rw-r--r--actionpack/lib/action_view/helpers/tag_helper.rb18
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb18
-rw-r--r--actionpack/lib/action_view/partial_template.rb2
-rw-r--r--actionpack/lib/action_view/template.rb91
-rw-r--r--actionpack/lib/action_view/template_finder.rb34
-rw-r--r--actionpack/lib/action_view/template_handler.rb1
-rw-r--r--actionpack/lib/action_view/template_handlers.rb46
-rw-r--r--actionpack/lib/action_view/template_handlers/builder.rb7
-rw-r--r--actionpack/lib/action_view/template_handlers/compilable.rb4
-rw-r--r--actionpack/lib/action_view/template_handlers/erb.rb6
-rw-r--r--actionpack/lib/action_view/test_case.rb5
19 files changed, 157 insertions, 212 deletions
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index f398756550..c417cc07ac 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -156,10 +156,12 @@ module ActionView #:nodoc:
attr_reader :finder
attr_accessor :base_path, :assigns, :template_extension, :first_render
attr_accessor :controller
-
+
attr_writer :template_format
attr_accessor :current_render_extension
+ attr_accessor :output_buffer
+
# Specify trim mode for the ERB compiler. Defaults to '-'.
# See ERb documentation for suitable values.
@@erb_trim_mode = '-'
@@ -178,14 +180,11 @@ module ActionView #:nodoc:
# that alert()s the caught exception (and then re-raises it).
@@debug_rjs = false
cattr_accessor :debug_rjs
-
- @@erb_variable = '_erbout'
- cattr_accessor :erb_variable
-
+
attr_internal :request
delegate :request_forgery_protection_token, :template, :params, :session, :cookies, :response, :headers,
- :flash, :logger, :action_name, :to => :controller
+ :flash, :logger, :action_name, :controller_name, :to => :controller
module CompiledTemplates #:nodoc:
# holds compiled template code
@@ -253,12 +252,13 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
elsif options == :update
update_page(&block)
elsif options.is_a?(Hash)
+ use_full_path = options[:use_full_path]
options = options.reverse_merge(:locals => {}, :use_full_path => true)
if partial_layout = options.delete(:layout)
if block_given?
wrap_content_for_layout capture(&block) do
- concat(render(options.merge(:partial => partial_layout)), block.binding)
+ concat(render(options.merge(:partial => partial_layout)))
end
else
wrap_content_for_layout render(options) do
@@ -266,7 +266,7 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
end
end
elsif options[:file]
- render_file(options[:file], options[:use_full_path], options[:locals])
+ render_file(options[:file], use_full_path || false, options[:locals])
elsif options[:partial] && options[:collection]
render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals])
elsif options[:partial]
@@ -316,9 +316,10 @@ If you are rendering a subtemplate, you must now use controller-like partial syn
private
def wrap_content_for_layout(content)
- original_content_for_layout = @content_for_layout
- @content_for_layout = content
- returning(yield) { @content_for_layout = original_content_for_layout }
+ original_content_for_layout, @content_for_layout = @content_for_layout, content
+ yield
+ ensure
+ @content_for_layout = original_content_for_layout
end
# Evaluate the local assigns and pushes them to the view.
diff --git a/actionpack/lib/action_view/helpers/capture_helper.rb b/actionpack/lib/action_view/helpers/capture_helper.rb
index 9ea06568cf..9cd9d3d06a 100644
--- a/actionpack/lib/action_view/helpers/capture_helper.rb
+++ b/actionpack/lib/action_view/helpers/capture_helper.rb
@@ -31,20 +31,13 @@ module ActionView
# </body></html>
#
def capture(*args, &block)
- # execute the block
- begin
- buffer = eval(ActionView::Base.erb_variable, block.binding)
- rescue
- buffer = nil
- end
-
- if buffer.nil?
- capture_block(*args, &block).to_s
+ if output_buffer
+ with_output_buffer { block.call(*args) }
else
- capture_erb_with_buffer(buffer, *args, &block).to_s
+ 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>.
@@ -121,40 +114,18 @@ module ActionView
# 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)
- 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)
+ ivar = "@content_for_#{name}"
+ content = capture(&block) if block_given?
+ instance_variable_set(ivar, "#{instance_variable_get(ivar)}#{content}")
end
private
- def capture_block(*args, &block)
- block.call(*args)
- end
-
- def capture_erb(*args, &block)
- 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
- 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)"
+ def with_output_buffer(buf = '')
+ self.output_buffer, old_buffer = buf, output_buffer
+ yield
+ output_buffer
+ ensure
+ self.output_buffer = old_buffer
end
end
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 0791feb9ac..63a932320e 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -249,9 +249,9 @@ module ActionView
args.unshift object
end
- concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}), proc.binding)
+ concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}))
fields_for(object_name, *(args << options), &proc)
- concat('</form>', proc.binding)
+ concat('</form>')
end
def apply_form_for_options!(object_or_array, options) #:nodoc:
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index e0a097e367..b3f8e63c1b 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -304,7 +304,7 @@ module ActionView
#
# NOTE: Only the option tags are returned, you have to wrap this call in
# a regular HTML select tag.
- def time_zone_options_for_select(selected = nil, priority_zones = nil, model = TimeZone)
+ def time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)
zone_options = ""
zones = model.all
@@ -417,7 +417,7 @@ module ActionView
value = value(object)
content_tag("select",
add_options(
- time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || TimeZone),
+ time_zone_options_for_select(value || options[:default], priority_zones, options[:model] || ActiveSupport::TimeZone),
options, value
), html_options
)
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index ca58f4ba26..3a97f1390f 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -407,10 +407,10 @@ module ActionView
# # => <fieldset><legend>Your details</legend><p><input id="name" name="name" type="text" /></p></fieldset>
def field_set_tag(legend = nil, &block)
content = capture(&block)
- concat(tag(:fieldset, {}, true), block.binding)
- concat(content_tag(:legend, legend), block.binding) unless legend.blank?
- concat(content, block.binding)
- concat("</fieldset>", block.binding)
+ concat(tag(:fieldset, {}, true))
+ concat(content_tag(:legend, legend)) unless legend.blank?
+ concat(content)
+ concat("</fieldset>")
end
private
@@ -442,9 +442,9 @@ module ActionView
def form_tag_in_block(html_options, &block)
content = capture(&block)
- concat(form_tag_html(html_options), block.binding)
- concat(content, block.binding)
- concat("</form>", block.binding)
+ concat(form_tag_html(html_options))
+ concat(content)
+ concat("</form>")
end
def token_tag
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index 1ea3cbd74e..7404a251e4 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -172,20 +172,17 @@ module ActionView
# alert('All is good')
# <% end -%>
def javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
- if block_given?
- html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
- content = capture(&block)
- else
- content = content_or_options_with_block
- end
+ content =
+ if block_given?
+ html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
+ capture(&block)
+ else
+ content_or_options_with_block
+ end
- javascript_tag = content_tag("script", javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
-
- if block_given? && block_is_within_action_view?(block)
- concat(javascript_tag, block.binding)
- else
- javascript_tag
- end
+ tag = content_tag("script", javascript_cdata_section(content), html_options.merge(:type => Mime::JS))
+
+ block_given? ? concat(tag) : tag
end
def javascript_cdata_section(content) #:nodoc:
@@ -205,11 +202,6 @@ module ActionView
end
js_option
end
-
- private
- def block_is_within_action_view?(block)
- eval("defined? _erbout", block.binding)
- end
end
JavascriptHelper = JavaScriptHelper unless const_defined? :JavascriptHelper
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index 5a1012954e..a7c3b9ddc3 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -382,9 +382,9 @@ module ActionView
args.unshift object
end
- concat(form_remote_tag(options), proc.binding)
+ concat(form_remote_tag(options))
fields_for(object_name, *(args << options), &proc)
- concat('</form>', proc.binding)
+ concat('</form>')
end
alias_method :form_remote_for, :remote_form_for
diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb
index 66c596f3a9..9bb235175e 100644
--- a/actionpack/lib/action_view/helpers/record_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb
@@ -51,9 +51,8 @@ module ActionView
prefix = args.first.is_a?(Hash) ? nil : args.shift
options = args.first.is_a?(Hash) ? args.shift : {}
concat content_tag(tag_name, capture(&block),
- options.merge({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) })),
- block.binding
+ options.merge({ :class => "#{dom_class(record)} #{options[:class]}".strip, :id => dom_id(record, prefix) }))
end
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index 999cbfb52a..e1abec1847 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -1,5 +1,6 @@
require 'cgi'
require 'erb'
+require 'set'
module ActionView
module Helpers #:nodoc:
@@ -8,7 +9,8 @@ module ActionView
module TagHelper
include ERB::Util
- BOOLEAN_ATTRIBUTES = Set.new(%w(disabled readonly multiple))
+ BOOLEAN_ATTRIBUTES = %w(disabled readonly multiple).to_set
+ BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map(&:to_sym))
# Returns an empty HTML tag of type +name+ which by default is XHTML
# compliant. Set +open+ to true to create an open tag compatible
@@ -37,7 +39,7 @@ module ActionView
# tag("img", { :src => "open &amp; shut.png" }, false, false)
# # => <img src="open &amp; shut.png" />
def tag(name, options = nil, open = false, escape = true)
- "<#{name}#{tag_options(options, escape) if options}" + (open ? ">" : " />")
+ "<#{name}#{tag_options(options, escape) if options}#{open ? ">" : " />"}"
end
# Returns an HTML block tag of type +name+ surrounding the +content+. Add
@@ -66,12 +68,9 @@ module ActionView
def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
if block_given?
options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
- content = capture(&block)
- content_tag = content_tag_string(name, content, options, escape)
- block_is_within_action_view?(block) ? concat(content_tag, block.binding) : content_tag
+ concat(content_tag_string(name, capture(&block), options, escape))
else
- content = content_or_options_with_block
- content_tag_string(name, content, options, escape)
+ content_tag_string(name, content_or_options_with_block, options, escape)
end
end
@@ -114,7 +113,6 @@ module ActionView
if escape
options.each do |key, value|
next unless value
- key = key.to_s
value = BOOLEAN_ATTRIBUTES.include?(key) ? key : escape_once(value)
attrs << %(#{key}="#{value}")
end
@@ -124,10 +122,6 @@ module ActionView
" #{attrs.sort * ' '}" unless attrs.empty?
end
end
-
- def block_is_within_action_view?(block)
- eval("defined? _erbout", block.binding)
- end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 669a285424..a1a91f6b3d 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -15,18 +15,26 @@ module ActionView
#
# ==== Examples
# <%
- # concat "hello", binding
+ # concat "hello"
# # is the equivalent of <%= "hello" %>
#
# if (logged_in == true):
- # concat "Logged in!", binding
+ # concat "Logged in!"
# else
- # concat link_to('login', :action => login), binding
+ # concat link_to('login', :action => login)
# end
# # will either display "Logged in!" or a login link
# %>
- def concat(string, binding)
- eval(ActionView::Base.erb_variable, binding) << string
+ def concat(string, unused_binding = nil)
+ if unused_binding
+ ActiveSupport::Deprecation.warn("The binding argument of #concat is no longer needed. Please remove it from your views and helpers.")
+ end
+
+ if output_buffer && string
+ output_buffer << string
+ else
+ string
+ end
end
if RUBY_VERSION < '1.9'
diff --git a/actionpack/lib/action_view/partial_template.rb b/actionpack/lib/action_view/partial_template.rb
index 1fb3aaee02..0b374db888 100644
--- a/actionpack/lib/action_view/partial_template.rb
+++ b/actionpack/lib/action_view/partial_template.rb
@@ -22,10 +22,10 @@ module ActionView #:nodoc:
end
def render_member(object)
- @locals[@counter_name] += 1
@locals[:object] = @locals[@variable_name] = object
template = render_template
+ @locals[@counter_name] += 1
@locals.delete(@variable_name)
@locals.delete(:object)
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 369526188f..500ff713bb 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -1,5 +1,6 @@
module ActionView #:nodoc:
class Template #:nodoc:
+ extend TemplateHandlers
attr_accessor :locals
attr_reader :handler, :path, :extension, :filename, :path_without_extension, :method
@@ -13,7 +14,7 @@ module ActionView #:nodoc:
@view.first_render ||= @path
@source = nil # Don't read the source until we know that it is required
set_extension_and_file_name(use_full_path)
-
+
@locals = locals || {}
@handler = self.class.handler_class_for_extension(@extension).new(@view)
end
@@ -29,7 +30,7 @@ module ActionView #:nodoc:
raise TemplateError.new(self, @view.assigns, e)
end
end
-
+
def render
prepare!
@handler.render(self)
@@ -46,11 +47,11 @@ module ActionView #:nodoc:
def base_path_for_exception
@finder.find_base_path_for("#{@path_without_extension}.#{@extension}") || @finder.view_paths.first
end
-
+
def prepare!
@view.send :evaluate_assigns
@view.current_render_extension = @extension
-
+
if @handler.compilable?
@handler.compile_template(self) # compile the given template, if necessary
@method = @view.method_names[method_key] # Set the method name for this template and run it
@@ -58,70 +59,30 @@ module ActionView #:nodoc:
end
private
-
- def set_extension_and_file_name(use_full_path)
- @path_without_extension, @extension = @finder.path_and_extension(@path)
- if use_full_path
- if @extension
- @filename = @finder.pick_template(@path_without_extension, @extension)
+ def set_extension_and_file_name(use_full_path)
+ @path_without_extension, @extension = @finder.path_and_extension(@path)
+ if use_full_path
+ if @extension
+ @filename = @finder.pick_template(@path_without_extension, @extension)
+ else
+ @extension = @finder.pick_template_extension(@path).to_s
+ raise_missing_template_exception unless @extension
+
+ @filename = @finder.pick_template(@path, @extension)
+ @extension = @extension.gsub(/^.+\./, '') # strip off any formats
+ end
else
- @extension = @finder.pick_template_extension(@path).to_s
- raise_missing_template_exception unless @extension
-
- @filename = @finder.pick_template(@path, @extension)
- @extension = @extension.gsub(/^.+\./, '') # strip off any formats
+ @filename = @path
end
- else
- @filename = @path
- end
-
- raise_missing_template_exception if @filename.blank?
- end
-
- def raise_missing_template_exception
- full_template_path = @path.include?('.') ? @path : "#{@path}.#{@view.template_format}.erb"
- display_paths = @finder.view_paths.join(':')
- template_type = (@path =~ /layouts/i) ? 'layout' : 'template'
- raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}")
- end
- # Template Handlers
-
- @@template_handlers = HashWithIndifferentAccess.new
- @@default_template_handlers = nil
-
- # Register a class that knows how to handle template files with the given
- # extension. This can be used to implement new template types.
- # The constructor for the class must take the ActiveView::Base instance
- # as a parameter, and the class must implement a +render+ method that
- # takes the contents of the template to render as well as the Hash of
- # local assigns available to the template. The +render+ method ought to
- # return the rendered template as a string.
- def self.register_template_handler(extension, klass)
- @@template_handlers[extension.to_sym] = klass
- TemplateFinder.update_extension_cache_for(extension.to_s)
- end
-
- def self.template_handler_extensions
- @@template_handlers.keys.map(&:to_s).sort
- end
-
- def self.register_default_template_handler(extension, klass)
- register_template_handler(extension, klass)
- @@default_template_handlers = klass
- end
-
- def self.handler_class_for_extension(extension)
- (extension && @@template_handlers[extension.to_sym]) || @@default_template_handlers
- end
-
- register_default_template_handler :erb, TemplateHandlers::ERB
- register_template_handler :rjs, TemplateHandlers::RJS
- register_template_handler :builder, TemplateHandlers::Builder
+ raise_missing_template_exception if @filename.blank?
+ end
- # TODO: Depreciate old template extensions
- register_template_handler :rhtml, TemplateHandlers::ERB
- register_template_handler :rxml, TemplateHandlers::Builder
-
+ def raise_missing_template_exception
+ full_template_path = @path.include?('.') ? @path : "#{@path}.#{@view.template_format}.erb"
+ display_paths = @finder.view_paths.join(':')
+ template_type = (@path =~ /layouts/i) ? 'layout' : 'template'
+ raise(MissingTemplate, "Missing #{template_type} #{full_template_path} in view path #{display_paths}")
+ end
end
end
diff --git a/actionpack/lib/action_view/template_finder.rb b/actionpack/lib/action_view/template_finder.rb
index 83b7e27c09..7e9a310810 100644
--- a/actionpack/lib/action_view/template_finder.rb
+++ b/actionpack/lib/action_view/template_finder.rb
@@ -1,14 +1,5 @@
module ActionView #:nodoc:
class TemplateFinder #:nodoc:
-
- class InvalidViewPath < StandardError #:nodoc:
- attr_reader :unprocessed_path
- def initialize(path)
- @unprocessed_path = path
- super("Unprocessed view path found: #{@unprocessed_path.inspect}. Set your view paths with #append_view_path, #prepend_view_path, or #view_paths=.")
- end
- end
-
cattr_reader :processed_view_paths
@@processed_view_paths = Hash.new {|hash, key| hash[key] = []}
@@ -18,7 +9,6 @@ module ActionView #:nodoc:
}
class << self #:nodoc:
-
# This method is not thread safe. Mutex should be used whenever this is accessed from an instance method
def process_view_paths(*view_paths)
view_paths.flatten.compact.each do |dir|
@@ -35,7 +25,7 @@ module ActionView #:nodoc:
# Build extension cache
extension = file.split(".").last
- if template_handler_extensions.include?(extension)
+ if ActionView::Template.template_handler_extensions.include?(extension)
key = file.split(dir).last.sub(/^\//, '').sub(/\.(\w+)$/, '')
@@file_extension_cache[dir][key] << extension
end
@@ -44,19 +34,6 @@ module ActionView #:nodoc:
end
end
- def update_extension_cache_for(extension)
- @@processed_view_paths.keys.each do |dir|
- Dir.glob("#{dir}/**/*.#{extension}").each do |file|
- key = file.split(dir).last.sub(/^\//, '').sub(/\.(\w+)$/, '')
- @@file_extension_cache[dir][key] << extension
- end
- end
- end
-
- def template_handler_extensions
- ActionView::Template.template_handler_extensions
- end
-
def reload!
view_paths = @@processed_view_paths.keys
@@ -76,7 +53,7 @@ module ActionView #:nodoc:
@view_paths = args.flatten
@view_paths = @view_paths.respond_to?(:find) ? @view_paths.dup : [*@view_paths].compact
- check_view_paths(@view_paths)
+ self.class.process_view_paths(@view_paths)
end
def prepend_view_path(path)
@@ -166,12 +143,5 @@ module ActionView #:nodoc:
def find_template_extension_from_first_render
File.basename(@template.first_render.to_s)[/^[^.]+\.(.+)$/, 1]
end
-
- private
- def check_view_paths(view_paths)
- view_paths.each do |path|
- raise InvalidViewPath.new(path) unless @@processed_view_paths.has_key?(path)
- end
- end
end
end
diff --git a/actionpack/lib/action_view/template_handler.rb b/actionpack/lib/action_view/template_handler.rb
index ec407e3fb3..39e578e586 100644
--- a/actionpack/lib/action_view/template_handler.rb
+++ b/actionpack/lib/action_view/template_handler.rb
@@ -1,6 +1,5 @@
module ActionView
class TemplateHandler
-
def self.line_offset
0
end
diff --git a/actionpack/lib/action_view/template_handlers.rb b/actionpack/lib/action_view/template_handlers.rb
new file mode 100644
index 0000000000..1471e99e01
--- /dev/null
+++ b/actionpack/lib/action_view/template_handlers.rb
@@ -0,0 +1,46 @@
+require 'action_view/template_handler'
+require 'action_view/template_handlers/compilable'
+require 'action_view/template_handlers/builder'
+require 'action_view/template_handlers/erb'
+require 'action_view/template_handlers/rjs'
+
+module ActionView #:nodoc:
+ module TemplateHandlers #:nodoc:
+ def self.extended(base)
+ base.register_default_template_handler :erb, TemplateHandlers::ERB
+ base.register_template_handler :rjs, TemplateHandlers::RJS
+ base.register_template_handler :builder, TemplateHandlers::Builder
+
+ # TODO: Depreciate old template extensions
+ base.register_template_handler :rhtml, TemplateHandlers::ERB
+ base.register_template_handler :rxml, TemplateHandlers::Builder
+ end
+
+ @@template_handlers = {}
+ @@default_template_handlers = nil
+
+ # Register a class that knows how to handle template files with the given
+ # extension. This can be used to implement new template types.
+ # The constructor for the class must take the ActiveView::Base instance
+ # as a parameter, and the class must implement a +render+ method that
+ # takes the contents of the template to render as well as the Hash of
+ # local assigns available to the template. The +render+ method ought to
+ # return the rendered template as a string.
+ def register_template_handler(extension, klass)
+ @@template_handlers[extension.to_sym] = klass
+ end
+
+ def template_handler_extensions
+ @@template_handlers.keys.map(&:to_s).sort
+ end
+
+ def register_default_template_handler(extension, klass)
+ register_template_handler(extension, klass)
+ @@default_template_handlers = klass
+ end
+
+ def handler_class_for_extension(extension)
+ (extension && @@template_handlers[extension.to_sym]) || @@default_template_handlers
+ end
+ end
+end
diff --git a/actionpack/lib/action_view/template_handlers/builder.rb b/actionpack/lib/action_view/template_handlers/builder.rb
index f76d89777a..ee02ce1a6f 100644
--- a/actionpack/lib/action_view/template_handlers/builder.rb
+++ b/actionpack/lib/action_view/template_handlers/builder.rb
@@ -11,10 +11,11 @@ module ActionView
def compile(template)
content_type_handler = (@view.send!(:controller).respond_to?(:response) ? "controller.response" : "controller")
+
"#{content_type_handler}.content_type ||= Mime::XML\n" +
- "xml = ::Builder::XmlMarkup.new(:indent => 2)\n" +
- template.source +
- "\nxml.target!\n"
+ "xml = ::Builder::XmlMarkup.new(:indent => 2)\n" +
+ template.source +
+ "\nxml.target!\n"
end
def cache_fragment(block, name = {}, options = nil)
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
index 25bd0fea7f..1aef81ba1a 100644
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ b/actionpack/lib/action_view/template_handlers/compilable.rb
@@ -106,7 +106,7 @@ module ActionView
locals_code << "#{key} = local_assigns[:#{key}]\n"
end
- "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend"
+ "def #{render_symbol}(local_assigns)\nold_output_buffer = output_buffer;#{locals_code}#{body}\nensure\nself.output_buffer = old_output_buffer\nend"
end
# Return true if the given template was compiled for a superset of the keys in local_assigns
@@ -125,4 +125,4 @@ module ActionView
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/template_handlers/erb.rb b/actionpack/lib/action_view/template_handlers/erb.rb
index 15a9064461..ad4ccc7c42 100644
--- a/actionpack/lib/action_view/template_handlers/erb.rb
+++ b/actionpack/lib/action_view/template_handlers/erb.rb
@@ -43,13 +43,11 @@ module ActionView
include Compilable
def compile(template)
- ::ERB.new(template.source, nil, @view.erb_trim_mode).src
+ ::ERB.new(template.source, nil, @view.erb_trim_mode, '@output_buffer').src
end
def cache_fragment(block, name = {}, options = nil) #:nodoc:
- @view.fragment_for(block, name, options) do
- eval(ActionView::Base.erb_variable, block.binding)
- end
+ @view.fragment_for(block, name, options) { @view.response.template.output_buffer ||= '' }
end
end
end
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 16fedd9732..1a3c93c283 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -37,6 +37,8 @@ module ActionView
if helper_class && !self.class.ancestors.include?(helper_class)
self.class.send(:include, helper_class)
end
+
+ self.output_buffer = ''
end
class TestController < ActionController::Base
@@ -48,6 +50,9 @@ module ActionView
end
end
+ protected
+ attr_accessor :output_buffer
+
private
def method_missing(selector, *args)
controller = TestController.new