aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@github.com>2019-01-22 09:28:08 -0800
committerGitHub <noreply@github.com>2019-01-22 09:28:08 -0800
commitdb4b77aca147ec3c7376d803fc6ccb14c9195352 (patch)
treee73fa5f4145cf294f983cb752cc49c8985616d48
parente26f0658da7ff7e9382d6040fe76c087ff1791e4 (diff)
parent0f081611e6746ebbf17ffc13e119b24c9ad7aa73 (diff)
downloadrails-db4b77aca147ec3c7376d803fc6ccb14c9195352.tar.gz
rails-db4b77aca147ec3c7376d803fc6ccb14c9195352.tar.bz2
rails-db4b77aca147ec3c7376d803fc6ccb14c9195352.zip
Merge pull request #34952 from rails/template-stuff
Template Handler Refactoring
-rw-r--r--actionpack/lib/action_controller/metal/basic_implicit_render.rb2
-rw-r--r--actionpack/lib/action_controller/metal/implicit_render.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb9
-rw-r--r--actionpack/test/controller/new_base/render_context_test.rb55
-rw-r--r--actionview/lib/action_view/base.rb18
-rw-r--r--actionview/lib/action_view/context.rb5
-rw-r--r--actionview/lib/action_view/rendering.rb4
-rw-r--r--actionview/lib/action_view/template.rb14
-rw-r--r--actionview/lib/action_view/template/handlers/erb/erubi.rb10
-rw-r--r--actionview/test/abstract_unit.rb2
-rw-r--r--actionview/test/template/template_test.rb2
11 files changed, 43 insertions, 82 deletions
diff --git a/actionpack/lib/action_controller/metal/basic_implicit_render.rb b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
index 2dc990f303..f9a758ff0e 100644
--- a/actionpack/lib/action_controller/metal/basic_implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/basic_implicit_render.rb
@@ -6,7 +6,7 @@ module ActionController
super.tap { default_render unless performed? }
end
- def default_render(*args)
+ def default_render
head :no_content
end
end
diff --git a/actionpack/lib/action_controller/metal/implicit_render.rb b/actionpack/lib/action_controller/metal/implicit_render.rb
index d3bb58f48b..8365ddca57 100644
--- a/actionpack/lib/action_controller/metal/implicit_render.rb
+++ b/actionpack/lib/action_controller/metal/implicit_render.rb
@@ -30,9 +30,9 @@ module ActionController
# :stopdoc:
include BasicImplicitRender
- def default_render(*args)
+ def default_render
if template_exists?(action_name.to_s, _prefixes, variants: request.variant)
- render(*args)
+ render
elsif any_templates?(action_name.to_s, _prefixes)
message = "#{self.class.name}\##{action_name} is missing a template " \
"for this request format and variant.\n" \
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index af41521c5c..28cde6704e 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -160,9 +160,16 @@ module ActionDispatch
@controller.singleton_class.include(_routes.url_helpers)
if @controller.respond_to? :view_context_class
- @controller.view_context_class = Class.new(@controller.view_context_class) do
+ view_context_class = Class.new(@controller.view_context_class) do
include _routes.url_helpers
end
+
+ custom_view_context = Module.new {
+ define_method(:view_context_class) do
+ view_context_class
+ end
+ }
+ @controller.extend(custom_view_context)
end
end
yield @routes
diff --git a/actionpack/test/controller/new_base/render_context_test.rb b/actionpack/test/controller/new_base/render_context_test.rb
deleted file mode 100644
index 5e570a1d79..0000000000
--- a/actionpack/test/controller/new_base/render_context_test.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-
-require "abstract_unit"
-
-# This is testing the decoupling of view renderer and view context
-# by allowing the controller to be used as view context. This is
-# similar to the way sinatra renders templates.
-module RenderContext
- class BasicController < ActionController::Base
- self.view_paths = [ActionView::FixtureResolver.new(
- "render_context/basic/hello_world.html.erb" => "<%= @value %> from <%= self.__controller_method__ %>",
- "layouts/basic.html.erb" => "?<%= yield %>?"
- )]
-
- # 1) Include ActionView::Context to bring the required dependencies
- include ActionView::Context
-
- # 2) Call _prepare_context that will do the required initialization
- before_action :_prepare_context
-
- def hello_world
- @value = "Hello"
- render action: "hello_world", layout: false
- end
-
- def with_layout
- @value = "Hello"
- render action: "hello_world", layout: "basic"
- end
-
- protected def __controller_method__
- "controller context!"
- end
-
- private
- # 3) Set view_context to self
- def view_context
- self
- end
- end
-
- class RenderContextTest < Rack::TestCase
- test "rendering using the controller as context" do
- get "/render_context/basic/hello_world"
- assert_body "Hello from controller context!"
- assert_status 200
- end
-
- test "rendering using the controller as context with layout" do
- get "/render_context/basic/with_layout"
- assert_body "?Hello from controller context!?"
- assert_status 200
- end
- end
-end
diff --git a/actionview/lib/action_view/base.rb b/actionview/lib/action_view/base.rb
index d41fe2a608..6cb342a0a9 100644
--- a/actionview/lib/action_view/base.rb
+++ b/actionview/lib/action_view/base.rb
@@ -10,6 +10,10 @@ require "action_view/template"
require "action_view/lookup_context"
module ActionView #:nodoc:
+ module CompiledTemplates #:nodoc:
+ # holds compiled template code
+ end
+
# = Action View Base
#
# Action View templates can be written in several ways.
@@ -141,6 +145,8 @@ module ActionView #:nodoc:
class Base
include Helpers, ::ERB::Util, Context
+ include CompiledTemplates
+
# Specify the proc used to decorate input tags that refer to attributes with errors.
cattr_accessor :field_error_proc, default: Proc.new { |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }
@@ -210,6 +216,18 @@ module ActionView #:nodoc:
_prepare_context
end
+ def run(method, locals, buffer, &block)
+ _old_output_buffer, _old_virtual_path = @output_buffer, @virtual_path
+ @output_buffer = buffer
+ send(method, locals, buffer, &block)
+ ensure
+ @output_buffer, @virtual_path = _old_output_buffer, _old_virtual_path
+ end
+
+ def compiled_method_container
+ CompiledTemplates
+ end
+
ActiveSupport.run_load_hooks(:action_view, self)
end
end
diff --git a/actionview/lib/action_view/context.rb b/actionview/lib/action_view/context.rb
index 3c605c3ee3..2b22c30a3a 100644
--- a/actionview/lib/action_view/context.rb
+++ b/actionview/lib/action_view/context.rb
@@ -1,10 +1,6 @@
# frozen_string_literal: true
module ActionView
- module CompiledTemplates #:nodoc:
- # holds compiled template code
- end
-
# = Action View Context
#
# Action View contexts are supplied to Action Controller to render a template.
@@ -16,7 +12,6 @@ module ActionView
# object that includes this module (although you can call _prepare_context
# defined below).
module Context
- include CompiledTemplates
attr_accessor :output_buffer, :view_flow
# Prepares the context by setting the appropriate instance variables.
diff --git a/actionview/lib/action_view/rendering.rb b/actionview/lib/action_view/rendering.rb
index cb4327cf16..205665a8c6 100644
--- a/actionview/lib/action_view/rendering.rb
+++ b/actionview/lib/action_view/rendering.rb
@@ -55,10 +55,8 @@ module ActionView
end
end
- attr_internal_writer :view_context_class
-
def view_context_class
- @_view_context_class ||= self.class.view_context_class
+ self.class.view_context_class
end
# An instance of a view class. The default view class is ActionView::Base.
diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb
index 070d82cf17..8ce8053011 100644
--- a/actionview/lib/action_view/template.rb
+++ b/actionview/lib/action_view/template.rb
@@ -155,10 +155,10 @@ module ActionView
# This method is instrumented as "!render_template.action_view". Notice that
# we use a bang in this instrumentation because you don't want to
# consume this in production. This is only slow if it's being listened to.
- def render(view, locals, buffer = nil, &block)
+ def render(view, locals, buffer = ActionView::OutputBuffer.new, &block)
instrument_render_template do
compile!(view)
- view.send(method_name, locals, buffer, &block)
+ view.run(method_name, locals, buffer, &block)
end
rescue => e
handle_render_error(view, e)
@@ -264,11 +264,7 @@ module ActionView
# re-compilation
return if @compiled
- if view.is_a?(ActionView::CompiledTemplates)
- mod = ActionView::CompiledTemplates
- else
- mod = view.singleton_class
- end
+ mod = view.compiled_method_container
instrument("!compile_template") do
compile(mod)
@@ -301,9 +297,7 @@ module ActionView
# encoding of the code
source = +<<-end_src
def #{method_name}(local_assigns, output_buffer)
- _old_virtual_path, @virtual_path = @virtual_path, #{@virtual_path.inspect};_old_output_buffer = @output_buffer;#{locals_code};#{code}
- ensure
- @virtual_path, @output_buffer = _old_virtual_path, _old_output_buffer
+ @virtual_path = #{@virtual_path.inspect};#{locals_code};#{code}
end
end_src
diff --git a/actionview/lib/action_view/template/handlers/erb/erubi.rb b/actionview/lib/action_view/template/handlers/erb/erubi.rb
index db75f028ed..e155bae89d 100644
--- a/actionview/lib/action_view/template/handlers/erb/erubi.rb
+++ b/actionview/lib/action_view/template/handlers/erb/erubi.rb
@@ -13,7 +13,7 @@ module ActionView
# Dup properties so that we don't modify argument
properties = Hash[properties]
- properties[:preamble] = "@output_buffer = output_buffer || ActionView::OutputBuffer.new;"
+ properties[:preamble] = ""
properties[:postamble] = "@output_buffer.to_s"
properties[:bufvar] = "@output_buffer"
properties[:escapefunc] = ""
@@ -22,8 +22,12 @@ module ActionView
end
def evaluate(action_view_erb_handler_context)
- pr = eval("proc { #{@src} }", binding, @filename || "(erubi)")
- action_view_erb_handler_context.instance_eval(&pr)
+ src = @src
+ view = Class.new(ActionView::Base) {
+ include action_view_erb_handler_context._routes.url_helpers
+ class_eval("define_method(:_template) { |local_assigns, output_buffer| #{src} }", @filename || "(erubi)", 0)
+ }.new(action_view_erb_handler_context)
+ view.run(:_template, {}, ActionView::OutputBuffer.new)
end
private
diff --git a/actionview/test/abstract_unit.rb b/actionview/test/abstract_unit.rb
index f90626ad9e..d71944e938 100644
--- a/actionview/test/abstract_unit.rb
+++ b/actionview/test/abstract_unit.rb
@@ -61,7 +61,7 @@ module RenderERBUtils
ActionView::Template::Handlers::ERB,
{})
- template.render(self, {}).strip
+ template.render(ActionView::Base.new, {}).strip
end
end
diff --git a/actionview/test/template/template_test.rb b/actionview/test/template/template_test.rb
index b348d1f17b..8257d97b7c 100644
--- a/actionview/test/template/template_test.rb
+++ b/actionview/test/template/template_test.rb
@@ -18,7 +18,7 @@ class TestERBTemplate < ActiveSupport::TestCase
attr_accessor :formats
end
- class Context
+ class Context < ActionView::Base
def initialize
@output_buffer = "original"
@virtual_path = nil