aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG2
-rw-r--r--actionpack/lib/action_view/base.rb57
-rw-r--r--actionpack/test/controller/custom_handler_test.rb33
3 files changed, 77 insertions, 15 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index e153726ffc..8ac4dad690 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -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.
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 3f94a76cd0..e3b0821225 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -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)
+ 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 rhtml_render(extension, template, local_assigns)
+ b = evaluate_locals(local_assigns)
@@compiled_erb_templates[template] ||= ERB.new(template, nil, '-')
- @@compiled_erb_templates[template].result(binding)
+ @@compiled_erb_templates[template].result(b)
end
- def rxml_render(template, binding)
+ 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' \ No newline at end of file
diff --git a/actionpack/test/controller/custom_handler_test.rb b/actionpack/test/controller/custom_handler_test.rb
new file mode 100644
index 0000000000..8939d19166
--- /dev/null
+++ b/actionpack/test/controller/custom_handler_test.rb
@@ -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