diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index b4ab3481d5..e88e5aefc0 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -12,7 +12,6 @@ module AbstractController # This is a class to fix I18n global state. Whenever you provide I18n.locale during a request, # it will trigger the lookup_context and consequently expire the cache. - # TODO Add some deprecation warnings to remove I18n.locale from controllers class I18nProxy < ::I18n::Config #:nodoc: attr_reader :i18n_config, :lookup_context diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb index f7bdbd6917..24d9e9ffb5 100644 --- a/actionpack/lib/action_view/render/partials.rb +++ b/actionpack/lib/action_view/render/partials.rb @@ -371,13 +371,15 @@ module ActionView end def _render_partial(options, &block) #:nodoc: - if defined?(@renderer) - @renderer.setup(options, block) - else - @renderer = PartialRenderer.new(self, options, block) - end + _wrap_formats(options[:partial]) do + if defined?(@renderer) + @renderer.setup(options, block) + else + @renderer = PartialRenderer.new(self, options, block) + end - @renderer.render + @renderer.render + end end end diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index 0771b40c37..8e599c71df 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -21,9 +21,11 @@ module ActionView elsif options.key?(:partial) _render_partial(options) else - template = _determine_template(options) - lookup_context.freeze_formats(template.formats, true) - _render_template(template, options[:layout], options) + _wrap_formats(options[:template] || options[:file]) do + template = _determine_template(options) + lookup_context.freeze_formats(template.formats, true) + _render_template(template, options[:layout], options) + end end when :update update_page(&block) @@ -32,6 +34,19 @@ module ActionView end end + # Checks if the given path contains a format and if so, change + # the lookup context to take this new format into account. + def _wrap_formats(value) + return yield unless value.is_a?(String) + @@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/ + + if value.sub!(@@formats_regexp, "") + update_details(:formats => [$1.to_sym]){ yield } + else + yield + end + end + # Determine the template to be rendered using the given options. def _determine_template(options) #:nodoc: keys = (options[:locals] ||= {}).keys diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index 7e65654d0b..c15a0eb568 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -121,7 +121,7 @@ module ActionView @method_names = {} @locals = details[:locals] || [] @formats = Array.wrap(details[:format] || :html).map(&:to_sym) - @virtual_path = details[:virtual_path].try(:sub, ".#{@formats.first}", "") + @virtual_path = details[:virtual_path] @compiled = false end @@ -286,7 +286,7 @@ module ActionView pieces = @virtual_path.split("/") name = pieces.pop partial = name.sub!(/^_/, "") - view.find_template(name, pieces.join, partial || false, @locals) + view.find_template(name, pieces.join, partial || false, ["unlikely_local_key"]) end def method_name diff --git a/actionpack/test/controller/new_base/render_partial_test.rb b/actionpack/test/controller/new_base/render_partial_test.rb index 5c7e66dba2..d800ea264d 100644 --- a/actionpack/test/controller/new_base/render_partial_test.rb +++ b/actionpack/test/controller/new_base/render_partial_test.rb @@ -5,10 +5,17 @@ module RenderPartial class BasicController < ActionController::Base self.view_paths = [ActionView::FixtureResolver.new( - "render_partial/basic/_basic.html.erb" => "BasicPartial!", - "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>" + "render_partial/basic/_basic.html.erb" => "BasicPartial!", + "render_partial/basic/basic.html.erb" => "<%= @test_unchanged = 'goodbye' %><%= render :partial => 'basic' %><%= @test_unchanged %>", + "render_partial/basic/with_json.html.erb" => "<%= render 'with_json.json' %>", + "render_partial/basic/_with_json.json.erb" => "<%= render 'final' %>", + "render_partial/basic/_final.json.erb" => "{ final: json }" )] + def html_with_json_inside_json + render :action => "with_json" + end + def changing @test_unchanged = 'hello' render :action => "basic" @@ -22,6 +29,12 @@ module RenderPartial get :changing assert_response("goodbyeBasicPartial!goodbye") end + + test "rendering a template with renders another partial with other format that renders other partial in the same format" do + get :html_with_json_inside_json + assert_content_type "text/html; charset=utf-8" + assert_response "{ final: json }" + end end end diff --git a/actionpack/test/controller/new_base/render_template_test.rb b/actionpack/test/controller/new_base/render_template_test.rb index fea98d6bbd..8f5f51d70b 100644 --- a/actionpack/test/controller/new_base/render_template_test.rb +++ b/actionpack/test/controller/new_base/render_template_test.rb @@ -8,13 +8,20 @@ module RenderTemplate "shared.html.erb" => "Elastica", "locals.html.erb" => "The secret is <%= secret %>", "xml_template.xml.builder" => "xml.html do\n xml.p 'Hello'\nend", - "with_raw.html.erb" => "Hello <%=raw 'this is raw' %>" + "with_raw.html.erb" => "Hello <%=raw 'this is raw' %>", + "test/with_json.html.erb" => "<%= render :template => 'test/with_json.json' %>", + "test/with_json.json.erb" => "<%= render :template => 'test/final' %>", + "test/final.json.erb" => "{ final: json }" )] def index render :template => "test/basic" end + def html_with_json_inside_json + render :template => "test/with_json" + end + def index_without_key render "test/basic" end @@ -88,6 +95,12 @@ module RenderTemplate assert_body "Hello this is raw" assert_status 200 end + + test "rendering a template with renders another template with other format that renders other template in the same format" do + get :html_with_json_inside_json + assert_content_type "text/html; charset=utf-8" + assert_response "{ final: json }" + end end class WithLayoutController < ::ApplicationController