From 6351e0a541698bdaca348ad78bc9f7b25f6d56d6 Mon Sep 17 00:00:00 2001 From: Rick Olson Date: Thu, 12 Apr 2007 20:25:32 +0000 Subject: The default respond_to blocks don't set a specific extension anymore, so that both 'show.rjs' and 'show.js.rjs' will work. [Rick] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@6517 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/CHANGELOG | 2 + actionpack/lib/action_controller/base.rb | 2 +- actionpack/lib/action_controller/mime_responds.rb | 21 +++-- actionpack/lib/action_controller/request.rb | 4 +- actionpack/lib/action_view/base.rb | 93 ++++++++++++----------- actionpack/test/controller/mime_responds_test.rb | 12 +-- actionpack/test/controller/render_test.rb | 6 ++ actionpack/test/controller/request_test.rb | 12 ++- 8 files changed, 93 insertions(+), 59 deletions(-) (limited to 'actionpack') diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index f16d90af69..9cb6db6b0b 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,7 @@ *SVN* +* The default respond_to blocks don't set a specific extension anymore, so that both 'show.rjs' and 'show.js.rjs' will work. [Rick] + * Allow layouts with extension of .html.erb. Closes #8032 [Josh Knowles] * Change default respond_to templates for xml and rjs formats. [Rick] diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 7262472586..8e01af406c 100755 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1225,7 +1225,7 @@ module ActionController #:nodoc: def assert_existence_of_template_file(template_name) unless template_exists?(template_name) || ignore_missing_templates - full_template_path = @template.send(:full_template_path, template_name, "#{@template.send(:template_format)}.erb") + full_template_path = template_name.include?('.') ? template_name : @template.send(:full_template_path, template_name, "#{@template.send(:template_format)}.erb") template_type = (template_name =~ /layouts/i) ? 'layout' : 'template' raise(MissingTemplate, "Missing #{template_type} #{full_template_path}") end diff --git a/actionpack/lib/action_controller/mime_responds.rb b/actionpack/lib/action_controller/mime_responds.rb index e4d1dbbccc..0b4c4b6793 100644 --- a/actionpack/lib/action_controller/mime_responds.rb +++ b/actionpack/lib/action_controller/mime_responds.rb @@ -107,11 +107,17 @@ module ActionController #:nodoc: end class Responder #:nodoc: - default_block_format = %(Proc.new { render :action => "\#{action_name}%s", :content_type => Mime::%s }) - DEFAULT_BLOCKS = {} - DEFAULT_BLOCKS[:html] = default_block_format % ['', 'HTML'] - DEFAULT_BLOCKS[:js] = default_block_format % ['.js.rjs', 'JS'] - DEFAULT_BLOCKS[:xml] = default_block_format % ['.xml.builder', 'XML'] + default_block_format = <<-END + Proc.new { + @template.template_format = '%s' + render :action => "\#{action_name}", :content_type => Mime::%s + } + END + + DEFAULT_BLOCKS = [:html, :js, :xml].inject({}) do |memo, ext| + default_block = default_block_format % [ext, ext.to_s.upcase] + memo.update(ext => default_block) + end def initialize(block_binding) @block_binding = block_binding @@ -132,7 +138,10 @@ module ActionController #:nodoc: if block_given? @responses[mime_type] = Proc.new do - eval "response.content_type = '#{mime_type.to_s}'", @block_binding + eval <<-END, @block_binding + @template.template_format = '#{mime_type.to_sym}' + response.content_type = '#{mime_type.to_s}' + END block.call end else diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb index 5279315023..eed1563aba 100755 --- a/actionpack/lib/action_controller/request.rb +++ b/actionpack/lib/action_controller/request.rb @@ -9,6 +9,8 @@ module ActionController # such as { 'RAILS_ENV' => 'production' }. attr_reader :env + attr_accessor :format + # Returns the HTTP request method as a lowercase symbol (:get, for example). Note, HEAD is returned as :get # since the two are supposedly to be functionaly equivilent for all purposes except that HEAD won't return a response # body (which Rails also takes care of elsewhere). @@ -91,7 +93,7 @@ module ActionController # GET /posts/5.xhtml | request.format => Mime::HTML # GET /posts/5 | request.format => request.accepts.first (usually Mime::HTML for browsers) def format - parameters[:format] ? Mime::Type.lookup_by_extension(parameters[:format]) : accepts.first + @format ||= parameters[:format] ? Mime::Type.lookup_by_extension(parameters[:format]) : accepts.first end # Returns true if the request's "X-Requested-With" header contains diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 95dc135d60..1a4234b2c9 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -158,6 +158,8 @@ module ActionView #:nodoc: attr_reader :logger, :response, :headers, :view_paths attr_internal :cookies, :flash, :headers, :params, :request, :response, :session + + attr_writer :template_format # Specify trim mode for the ERB compiler. Defaults to '-'. # See ERb documentation for suitable values. @@ -207,6 +209,14 @@ module ActionView #:nodoc: # used by pick_template_extension determines whether ext1 or ext2 will be stored. @@cached_template_extension = {} + # Order of template handers checked by #file_exists? depending on the current #template_format + DEFAULT_TEMPLATE_HANDLER_PREFERENCE = %w(erb rhtml builder rxml javascript delegate) + TEMPLATE_HANDLER_PREFERENCES = { + :js => %w(javascript erb rhtml builder rxml delegate), + :xml => %w(builder rxml erb rhtml javascript delegate), + :delegate => %w(delegate) + } + class ObjectWrapper < Struct.new(:value) #:nodoc: end @@ -229,6 +239,7 @@ module ActionView #:nodoc: # 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_HANDLER_PREFERENCES[extension.to_sym] = TEMPLATE_HANDLER_PREFERENCES[:delegate] @@template_handlers[extension] = klass end @@ -331,54 +342,57 @@ module ActionView #:nodoc: end def pick_template_extension(template_path)#:nodoc: - formatted_template_path = "#{template_path}.#{template_format}" if @@cache_template_extensions - @@cached_template_extension[formatted_template_path] ||= find_template_extension_for(template_path, formatted_template_path) + formatted_template_path = "#{template_path}.#{template_format}" + @@cached_template_extension[formatted_template_path] ||= find_template_extension_for(template_path) else - find_template_extension_for(template_path, formatted_template_path) + find_template_extension_for(template_path) end end def delegate_template_exists?(template_path)#:nodoc: - @@template_handlers.find { |k,| template_exists?(template_path, k) } + delegate = @@template_handlers.find { |k,| template_exists?(template_path, k) } + delegate && delegate.first.to_sym end - - def one_of(template_path, *extensions)#:nodoc: - extensions.detect{|ext| template_exists?(template_path, ext)} - end - + def erb_template_exists?(template_path)#:nodoc: - one_of(template_path, :erb, :rhtml) + template_exists?(template_path, :erb) && :erb end - alias :rhtml_template_exists? :erb_template_exists? - + def builder_template_exists?(template_path)#:nodoc: - one_of(template_path, :builder, :rxml) + template_exists?(template_path, :builder) && :builder end - alias :rxml_template_exists? :builder_template_exists? - - def javascript_template_exists?(template_path)#:nodoc: - template_exists?(template_path, :rjs) + + def rhtml_template_exists?(template_path)#:nodoc: + template_exists?(template_path, :rhtml) && :rhtml end - def formatted_template_exists?(formatted_template_exists) - [:erb, :builder, :rjs].each do |ext| - return ext if template_exists?(formatted_template_exists, ext) - end - nil + def rxml_template_exists?(template_path)#:nodoc: + template_exists?(template_path, :rxml) && :rxml + end + + def javascript_template_exists?(template_path)#:nodoc: + template_exists?(template_path, :rjs) && :rjs end def file_exists?(template_path)#:nodoc: template_file_name, template_file_extension = path_and_extension(template_path) if template_file_extension - template_exists?(template_file_name, template_file_extension) + template_exists?(template_file_name, template_file_extension) && template_file_extension else formatted_template_path = "#{template_path}.#{template_format}" - cached_template_extension(formatted_template_path) || - formatted_template_exists?(formatted_template_path) || - %w(erb rhtml builder rxml javascript delegate).any? do |template_type| - send("#{template_type}_template_exists?", template_path) + return true if cached_template_extension(formatted_template_path) + template_handler_preferences.each do |template_type| + if extension = send("#{template_type}_template_exists?", formatted_template_path) + return "#{template_format}.#{extension}" + end + end + template_handler_preferences.each do |template_type| + if extension = send("#{template_type}_template_exists?", template_path) + return extension end + end + nil end end @@ -387,15 +401,13 @@ module ActionView #:nodoc: template_path.split('/').last[0,1] != '_' end + # symbolized version of the :format parameter of the request, or :html by default. def template_format - if @template_format != false - # check controller.respond_to?(:request) in case its an ActionMailer::Base, or some other sneaky class. - @template_format = controller.respond_to?(:request) ? false : :html - if controller && controller.respond_to?(:request) && controller.request && controller.request.format - @template_format = controller.request.format == Mime::ALL ? :html : controller.request.format.to_sym - end - end - @template_format + @template_format ||= controller.request.parameters[:format].to_sym rescue :html + end + + def template_handler_preferences + TEMPLATE_HANDLER_PREFERENCES[template_format] || DEFAULT_TEMPLATE_HANDLER_PREFERENCE end private @@ -434,14 +446,9 @@ module ActionView #:nodoc: end # Determines the template's file extension, such as rhtml, rxml, or rjs. - def find_template_extension_for(template_path, formatted_template_path = nil) - formatted_template_path ||= "#{template_path}.#{template_format}" - if match = delegate_template_exists?(template_path) - match.first.to_sym - elsif extension = formatted_template_exists?(formatted_template_path): "#{template_format}.#{extension}" - elsif extension = erb_template_exists?(template_path): extension - elsif extension = builder_template_exists?(template_path): extension - elsif javascript_template_exists?(template_path): :rjs + def find_template_extension_for(template_path) + if extension = file_exists?(template_path) + return extension else raise ActionViewError, "No erb, builder, rhtml, rxml, rjs or delegate template found for #{template_path} in #{@view_paths.inspect}" end diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb index aa31d5b649..d8d7c64ce0 100644 --- a/actionpack/test/controller/mime_responds_test.rb +++ b/actionpack/test/controller/mime_responds_test.rb @@ -288,11 +288,13 @@ class MimeControllerTest < Test::Unit::TestCase assert_equal 'Either JS or XML', @response.body end - def test_all_types_with_layout + def test_rjs_type_skips_layout @request.env["HTTP_ACCEPT"] = "text/javascript" get :all_types_with_layout assert_equal 'RJS for all_types_with_layout', @response.body - + end + + def test_html_type_with_layout @request.env["HTTP_ACCEPT"] = "text/html" get :all_types_with_layout assert_equal 'HTML for all_types_with_layout', @response.body @@ -343,14 +345,14 @@ class MimeControllerTest < Test::Unit::TestCase unless args.empty? @action = args.first[:action] end - response.body = @action + response.body = "#{@action} - #{@template.template_format}" end end get :using_defaults - assert_equal "using_defaults", @response.body + assert_equal "using_defaults - html", @response.body get :using_defaults, :format => "xml" - assert_equal "using_defaults.xml.builder", @response.body + assert_equal "using_defaults - xml", @response.body end end diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 7175b4f798..cba21fc4cb 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -361,6 +361,12 @@ class RenderTest < Test::Unit::TestCase get :formatted_xml_erb assert_equal 'passed formatted html erb', @response.body end + + def test_should_render_formatted_html_erb_template_with_faulty_accepts_header + @request.env["HTTP_ACCEPT"] = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appliction/x-shockwave-flash, */*" + get :formatted_xml_erb + assert_equal 'passed formatted html erb', @response.body + end protected def assert_deprecated_render(&block) diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb index 4914df679c..b939f6f975 100644 --- a/actionpack/test/controller/request_test.rb +++ b/actionpack/test/controller/request_test.rb @@ -309,16 +309,22 @@ class RequestTest < Test::Unit::TestCase assert @request.head? end - def test_format + def test_xml_format @request.instance_eval { @parameters = { :format => 'xml' } } assert_equal Mime::XML, @request.format - + end + + def test_xhtml_format @request.instance_eval { @parameters = { :format => 'xhtml' } } assert_equal Mime::HTML, @request.format - + end + + def test_txt_format @request.instance_eval { @parameters = { :format => 'txt' } } assert_equal Mime::TEXT, @request.format + end + def test_nil_format @request.instance_eval { @parameters = { :format => nil } } @request.env["HTTP_ACCEPT"] = "text/javascript" assert_equal Mime::JS, @request.format -- cgit v1.2.3