From 9a5d6d6388a20f29c63f85a95d215b0b34ea9cfd Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Sat, 19 Feb 2005 17:22:37 +0000 Subject: 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 --- actionpack/CHANGELOG | 2 + actionpack/lib/action_view/base.rb | 57 +++++++++++++++++------ actionpack/test/controller/custom_handler_test.rb | 33 +++++++++++++ 3 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 actionpack/test/controller/custom_handler_test.rb 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 template_extension. # The hash in local_assigns 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 -- cgit v1.2.3