Added ActionView::Base.register_template_handler for easy integration of an alternative template language to ERb and Builder. See test/controller/custom_handler_test.rb for a usage example #656 [Jamis Buck]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@694 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
This commit is contained in:
David Heinemeier Hansson
2005-02-19 17:22:37 +00:00
parent 9be37c9b20
commit 9a5d6d6388
3 changed files with 78 additions and 16 deletions

View File

@@ -1,5 +1,7 @@
*SVN*
* Added ActionView::Base.register_template_handler for easy integration of an alternative template language to ERb and Builder. See test/controller/custom_handler_test.rb for a usage example #656 [Jamis Buck]
* Added AssetTagHelper that provides methods for linking a HTML page together with other assets, such as javascripts, stylesheets, and feeds.
* Added FormTagHelper that provides a number of methods for creating form tags that doesn't rely on conventions with an object assigned to the template like FormHelper does. With the FormTagHelper, you provide the names and values yourself.

View File

@@ -130,6 +130,7 @@ module ActionView #:nodoc:
@@compiled_erb_templates = {}
@@loaded_templates = {}
@@template_handlers = {}
def self.load_helpers(helper_dir)#:nodoc:
Dir.foreach(helper_dir) do |helper_file|
@@ -151,6 +152,10 @@ module ActionView #:nodoc:
end
end
def self.register_template_handler(extension, klass)
@@template_handlers[extension] = klass
end
def initialize(base_path = nil, assigns_for_first_render = {}, controller = nil)#:nodoc:
@base_path, @assigns = base_path, assigns_for_first_render
@controller = controller
@@ -193,26 +198,32 @@ module ActionView #:nodoc:
# Renders the +template+ which is given as a string as either rhtml or rxml depending on <tt>template_extension</tt>.
# The hash in <tt>local_assigns</tt> is made available as local variables.
def render_template(template_extension, template, local_assigns = {})
b = binding
local_assigns.each { |key, value| eval "#{key} = local_assigns[\"#{key}\"]", b }
@assigns.each { |key, value| instance_variable_set "@#{key}", value }
xml = Builder::XmlMarkup.new(:indent => 2)
send(pick_rendering_method(template_extension), template, binding)
send(pick_rendering_method(template_extension), template_extension,
template, local_assigns)
end
def pick_template_extension(template_path)#:nodoc:
if erb_template_exists?(template_path)
if match = delegate_template_exists?(template_path)
match.first
elsif erb_template_exists?(template_path)
"rhtml"
elsif builder_template_exists?(template_path)
"rxml"
else
raise ActionViewError, "No rhtml or rxml template found for #{template_path}"
raise ActionViewError, "No rhtml, rxml, or delegate template found for #{template_path}"
end
end
def pick_rendering_method(template_extension)#:nodoc:
(template_extension == "rxml" ? "rxml" : "rhtml") + "_render"
if @@template_handlers[template_extension]
"delegate_render"
else
(template_extension == "rxml" ? "rxml" : "rhtml") + "_render"
end
end
def delegate_template_exists?(template_path)#:nodoc:
@@template_handlers.find { |k,| template_exists?(template_path, k) }
end
def erb_template_exists?(template_path)#:nodoc:
@@ -224,7 +235,7 @@ module ActionView #:nodoc:
end
def file_exists?(template_path)#:nodoc:
erb_template_exists?(template_path) || builder_template_exists?(template_path)
erb_template_exists?(template_path) || builder_template_exists?(template_path) || delegate_template_exists?(template_path)
end
# Returns true is the file may be rendered implicitly.
@@ -250,16 +261,32 @@ module ActionView #:nodoc:
@@loaded_templates[template_path]
end
def rhtml_render(template, binding)
@@compiled_erb_templates[template] ||= ERB.new(template, nil, '-')
@@compiled_erb_templates[template].result(binding)
def evaluate_locals(local_assigns = {})
b = binding
local_assigns.each { |key, value| eval "#{key} = local_assigns[\"#{key}\"]", b }
@assigns.each { |key, value| instance_variable_set "@#{key}", value }
xml = Builder::XmlMarkup.new(:indent => 2)
b
end
def rxml_render(template, binding)
def rhtml_render(extension, template, local_assigns)
b = evaluate_locals(local_assigns)
@@compiled_erb_templates[template] ||= ERB.new(template, nil, '-')
@@compiled_erb_templates[template].result(b)
end
def rxml_render(extension, template, local_assigns)
@controller.headers["Content-Type"] ||= 'text/xml'
eval(template, binding)
eval(template, evaluate_locals(local_assigns))
end
def delegate_render(extension, template, local_assigns)
delegator = @@template_handlers[extension].new(self)
delegator.render(template, local_assigns)
end
end
end
require 'action_view/template_error'
require 'action_view/template_error'

View File

@@ -0,0 +1,33 @@
require File.dirname(__FILE__) + '/../abstract_unit'
class CustomHandler
def initialize( view )
@view = view
end
def render( template, local_assigns )
[ template,
local_assigns,
@view ]
end
end
class CustomHandlerTest < Test::Unit::TestCase
def setup
ActionView::Base.register_template_handler "foo", CustomHandler
@view = ActionView::Base.new
end
def test_custom_render
result = @view.render_template( "foo", "hello <%= one %>", "one" => "two" )
assert_equal(
[ "hello <%= one %>", { "one" => "two" }, @view ],
result )
end
def test_unhandled_extension
# uses the ERb handler by default if the extension isn't recognized
result = @view.render_template( "bar", "hello <%= one %>", "one" => "two" )
assert_equal "hello two", result
end
end