diff --git a/actionpack/lib/action_dispatch/middleware/debug_view.rb b/actionpack/lib/action_dispatch/middleware/debug_view.rb
index 5a7010a1c2edab0cc10e62c66b25bc4d7a0e0489..f16484d1eaa95916b82f542d2f4b97fa11436bc4 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_view.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_view.rb
@@ -15,6 +15,10 @@ def initialize(assigns)
super(renderer, assigns)
end
+ def compiled_method_container
+ self.class
+ end
+
def debug_params(params)
clean_params = params.clone
clean_params.delete("action")
diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 5e17e65bde2c40a3313636f530bc393d4dfc7b13..5e7b271fb9c18fc244e565b1f61ad284e1beffa7 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,3 +1,13 @@
+* ActionView::Template.finalize_compiled_template_methods is deprecated with
+ no replacement.
+
+ *tenderlove*
+
+* config.action_view.finalize_compiled_template_methods is deprecated with
+ no replacement.
+
+ *tenderlove*
+
* Ensure unique DOM IDs for collection inputs with float values.
Fixes #34974
diff --git a/actionview/lib/action_view.rb b/actionview/lib/action_view.rb
index 6ff2d70e3559d27698c1a630050bc0414d27a126..8cb4648a67871ef876c25fa67b102d9fc123a333 100644
--- a/actionview/lib/action_view.rb
+++ b/actionview/lib/action_view.rb
@@ -35,7 +35,6 @@ module ActionView
eager_autoload do
autoload :Base
autoload :Context
- autoload :CompiledTemplates, "action_view/context"
autoload :Digestor
autoload :Helpers
autoload :LookupContext
diff --git a/actionview/lib/action_view/base.rb b/actionview/lib/action_view/base.rb
index b143e13c96372c1e3f52a2316dc0a4d163d50932..420136d6deb17e75bb0f0c0ae7e04b74e4383b71 100644
--- a/actionview/lib/action_view/base.rb
+++ b/actionview/lib/action_view/base.rb
@@ -11,10 +11,6 @@
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.
@@ -146,8 +142,6 @@ module CompiledTemplates #: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| "
#{html_tag}
".html_safe }
@@ -186,6 +180,20 @@ def cache_template_loading=(value)
def xss_safe? #:nodoc:
true
end
+
+ def with_empty_template_cache # :nodoc:
+ subclass = Class.new(self) {
+ # We can't implement these as self.class because subclasses will
+ # share the same template cache as superclasses, so "changed?" won't work
+ # correctly.
+ define_method(:compiled_method_container) { subclass }
+ define_singleton_method(:compiled_method_container) { subclass }
+ }
+ end
+
+ def changed?(other) # :nodoc:
+ compiled_method_container != other.compiled_method_container
+ end
end
attr_reader :view_renderer
@@ -260,7 +268,11 @@ def run(method, locals, buffer, &block)
end
def compiled_method_container
- CompiledTemplates
+ raise NotImplementedError, <<~msg
+ Subclasses of ActionView::Base must implement `compiled_method_container`
+ or use the class method `with_empty_template_cache` for constructing
+ an ActionView::Base subclass that has an empty cache.
+ msg
end
ActiveSupport.run_load_hooks(:action_view, self)
diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb
index c2f6439e26189cecc02f64c33a385e38e607489d..c3bb0a49fc94ed01036872e1c34b598c23b750e5 100644
--- a/actionview/lib/action_view/lookup_context.rb
+++ b/actionview/lib/action_view/lookup_context.rb
@@ -68,12 +68,17 @@ def self.get(details)
end
def self.clear
+ @view_context_class = nil
@details_keys.clear
end
def self.digest_caches
@details_keys.values
end
+
+ def self.view_context_class(klass)
+ @view_context_class ||= klass.with_empty_template_cache
+ end
end
# Add caching behavior on top of Details.
diff --git a/actionview/lib/action_view/railtie.rb b/actionview/lib/action_view/railtie.rb
index 12d06bf376905b16e773656b91bbe53267b5ed7d..a25e1d3d0295f4bcc22db673a0d59fa7e7086b3f 100644
--- a/actionview/lib/action_view/railtie.rb
+++ b/actionview/lib/action_view/railtie.rb
@@ -6,11 +6,13 @@
module ActionView
# = Action View Railtie
class Railtie < Rails::Engine # :nodoc:
+ NULL_OPTION = Object.new
+
config.action_view = ActiveSupport::OrderedOptions.new
config.action_view.embed_authenticity_token_in_remote_forms = nil
config.action_view.debug_missing_translation = true
config.action_view.default_enforce_utf8 = nil
- config.action_view.finalize_compiled_template_methods = true
+ config.action_view.finalize_compiled_template_methods = NULL_OPTION
config.eager_load_namespaces << ActionView
@@ -48,8 +50,11 @@ class Railtie < Rails::Engine # :nodoc:
initializer "action_view.finalize_compiled_template_methods" do |app|
ActiveSupport.on_load(:action_view) do
- ActionView::Template.finalize_compiled_template_methods =
- app.config.action_view.delete(:finalize_compiled_template_methods)
+ option = app.config.action_view.delete(:finalize_compiled_template_methods)
+
+ if option != NULL_OPTION
+ ActiveSupport::Deprecation.warn "action_view.finalize_compiled_template_methods is deprecated and has no effect"
+ end
end
end
diff --git a/actionview/lib/action_view/rendering.rb b/actionview/lib/action_view/rendering.rb
index 205665a8c60a667ceacbd44f4216582cb593ed49..cf7d1105e059efa2e2d1a2abc421d3d99fc4b48c 100644
--- a/actionview/lib/action_view/rendering.rb
+++ b/actionview/lib/action_view/rendering.rb
@@ -35,24 +35,36 @@ def process(*) #:nodoc:
end
module ClassMethods
- def view_context_class
- @view_context_class ||= begin
- supports_path = supports_path?
- routes = respond_to?(:_routes) && _routes
- helpers = respond_to?(:_helpers) && _helpers
-
- Class.new(ActionView::Base) do
- if routes
- include routes.url_helpers(supports_path)
- include routes.mounted_helpers
- end
-
- if helpers
- include helpers
- end
+ def _routes
+ end
+
+ def _helpers
+ end
+
+ def build_view_context_class(klass, supports_path, routes, helpers)
+ Class.new(klass) do
+ if routes
+ include routes.url_helpers(supports_path)
+ include routes.mounted_helpers
+ end
+
+ if helpers
+ include helpers
end
end
end
+
+ def view_context_class
+ klass = ActionView::LookupContext::DetailsKey.view_context_class(ActionView::Base)
+
+ @view_context_class ||= build_view_context_class(klass, supports_path?, _routes, _helpers)
+
+ if klass.changed?(@view_context_class)
+ @view_context_class = build_view_context_class(klass, supports_path?, _routes, _helpers)
+ end
+
+ @view_context_class
+ end
end
def view_context_class
diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb
index 8a5407c6228faf55958cf45915351a872869b099..37f476e5547bf5e177f641b8648d98859b6bcd8f 100644
--- a/actionview/lib/action_view/template.rb
+++ b/actionview/lib/action_view/template.rb
@@ -2,6 +2,7 @@
require "active_support/core_ext/object/try"
require "active_support/core_ext/kernel/singleton_class"
+require "active_support/deprecation"
require "thread"
require "delegate"
@@ -10,7 +11,13 @@ module ActionView
class Template
extend ActiveSupport::Autoload
- mattr_accessor :finalize_compiled_template_methods, default: true
+ def self.finalize_compiled_template_methods
+ ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods is deprecated and has no effect"
+ end
+
+ def self.finalize_compiled_template_methods=(_)
+ ActiveSupport::Deprecation.warn "ActionView::Template.finalize_compiled_template_methods= is deprecated and has no effect"
+ end
# === Encodings in ActionView::Template
#
@@ -118,16 +125,6 @@ class Template
attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
- # This finalizer is needed (and exactly with a proc inside another proc)
- # otherwise templates leak in development.
- Finalizer = proc do |method_name, mod| # :nodoc:
- proc do
- mod.module_eval do
- remove_possible_method method_name
- end
- end
- end
-
attr_reader :variable
def initialize(source, identifier, handler, details)
@@ -337,9 +334,6 @@ def #{method_name}(local_assigns, output_buffer)
end
mod.module_eval(source, identifier, 0)
- if finalize_compiled_template_methods
- ObjectSpace.define_finalizer(self, Finalizer[method_name, mod])
- end
end
def handle_render_error(view, e)
diff --git a/actionview/test/abstract_unit.rb b/actionview/test/abstract_unit.rb
index acc2ed029b567a40795751433ab45c4f36c924a7..b649b3c9ddbd2d7d1c774e7fe63c9da80ffcf20a 100644
--- a/actionview/test/abstract_unit.rb
+++ b/actionview/test/abstract_unit.rb
@@ -48,7 +48,8 @@ def view
@view ||= begin
path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH)
view_paths = ActionView::PathSet.new([path])
- ActionView::Base.with_view_paths(view_paths)
+ view = ActionView::Base.with_empty_template_cache
+ view.with_view_paths(view_paths)
end
end
@@ -61,7 +62,8 @@ def render_erb(string)
ActionView::Template.handler_for_extension(:erb),
{})
- template.render(ActionView::Base.empty, {}).strip
+ view = ActionView::Base.with_empty_template_cache
+ template.render(view.empty, {}).strip
end
end
diff --git a/actionview/test/activerecord/multifetch_cache_test.rb b/actionview/test/activerecord/multifetch_cache_test.rb
index 229b4e56d0020515e0d1776899edb92c54cb9f60..f56168bda57570ef15297d6082ec3344e7aedc30 100644
--- a/actionview/test/activerecord/multifetch_cache_test.rb
+++ b/actionview/test/activerecord/multifetch_cache_test.rb
@@ -10,8 +10,10 @@ class MultifetchCacheTest < ActiveRecordTestCase
def setup
view_paths = ActionController::Base.view_paths
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
- @view = Class.new(ActionView::Base) do
+ @view = Class.new(ActionView::Base.with_empty_template_cache) do
def view_cache_dependencies
[]
end
diff --git a/actionview/test/template/compiled_templates_test.rb b/actionview/test/template/compiled_templates_test.rb
index ded4786e62abe15e40f1312fe01274b313ab7b1d..6375555bb4c3a8b6a1b8859a7f80c3db31f3ec33 100644
--- a/actionview/test/template/compiled_templates_test.rb
+++ b/actionview/test/template/compiled_templates_test.rb
@@ -3,7 +3,18 @@
require "abstract_unit"
class CompiledTemplatesTest < ActiveSupport::TestCase
- teardown do
+ attr_reader :view_class
+
+ def setup
+ super
+ view_paths = ActionController::Base.view_paths
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
+ @view_class = ActionView::Base.with_empty_template_cache
+ end
+
+ def teardown
+ super
ActionView::LookupContext::DetailsKey.clear
end
@@ -72,13 +83,13 @@ def render(*args)
def render_with_cache(*args)
view_paths = ActionController::Base.view_paths
- ActionView::Base.with_view_paths(view_paths, {}).render(*args)
+ view_class.with_view_paths(view_paths, {}).render(*args)
end
def render_without_cache(*args)
path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH)
view_paths = ActionView::PathSet.new([path])
- ActionView::Base.with_view_paths(view_paths, {}).render(*args)
+ view_class.with_view_paths(view_paths, {}).render(*args)
end
def modify_template(template, content)
diff --git a/actionview/test/template/log_subscriber_test.rb b/actionview/test/template/log_subscriber_test.rb
index 9fcf80bb24060ab6d51bc89b24b8a19dbab924a3..4574b798d9ed8d4eb3bd6fe8d6924f1f1c8df1bc 100644
--- a/actionview/test/template/log_subscriber_test.rb
+++ b/actionview/test/template/log_subscriber_test.rb
@@ -11,10 +11,13 @@ class AVLogSubscriberTest < ActiveSupport::TestCase
def setup
super
- view_paths = ActionController::Base.view_paths
+ view_paths = ActionController::Base.view_paths
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
+
lookup_context = ActionView::LookupContext.new(view_paths, {}, ["test"])
renderer = ActionView::Renderer.new(lookup_context)
- @view = ActionView::Base.new(renderer, {})
+ @view = ActionView::Base.with_empty_template_cache.new(renderer, {})
ActionView::LogSubscriber.attach_to :action_view
diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb
index f89d087c346662b2404941aba512d299ef2fcfca..b8d8717db4ff06d32c8fe7463d930ddf6ff22e50 100644
--- a/actionview/test/template/render_test.rb
+++ b/actionview/test/template/render_test.rb
@@ -9,7 +9,8 @@ class TestController < ActionController::Base
module RenderTestCases
def setup_view(paths)
@assigns = { secret: "in the sauce" }
- @view = Class.new(ActionView::Base) do
+
+ @view = Class.new(ActionView::Base.with_empty_template_cache) do
def view_cache_dependencies; []; end
def combined_fragment_cache_key(key)
@@ -17,7 +18,9 @@ def combined_fragment_cache_key(key)
end
end.with_view_paths(paths, @assigns)
- @controller_view = TestController.new.view_context
+ controller = TestController.new
+
+ @controller_view = controller.view_context_class.with_empty_template_cache.new(controller.view_renderer, controller.view_assigns, controller)
# Reload and register danish language for testing
I18n.backend.store_translations "da", {}
@@ -629,6 +632,8 @@ class CachedViewRenderTest < ActiveSupport::TestCase
# Ensure view path cache is primed
def setup
view_paths = ActionController::Base.view_paths
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
assert_equal ActionView::OptimizedFileSystemResolver, view_paths.first.class
setup_view(view_paths)
end
@@ -645,6 +650,9 @@ class LazyViewRenderTest < ActiveSupport::TestCase
# Test the same thing as above, but make sure the view path
# is not eager loaded
def setup
+ view_paths = ActionController::Base.view_paths
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH)
view_paths = ActionView::PathSet.new([path])
assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first
@@ -704,6 +712,8 @@ class CachedCustomer < Customer; end
setup do
view_paths = ActionController::Base.view_paths
assert_equal ActionView::OptimizedFileSystemResolver, view_paths.first.class
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
ActionView::PartialRenderer.collection_cache = ActiveSupport::Cache::MemoryStore.new
diff --git a/actionview/test/template/streaming_render_test.rb b/actionview/test/template/streaming_render_test.rb
index dda209501303b20f8b1b391e9e08961a738c89cc..4567ee31b45cffbba56a363ff0ce12fcb69a440f 100644
--- a/actionview/test/template/streaming_render_test.rb
+++ b/actionview/test/template/streaming_render_test.rb
@@ -8,8 +8,11 @@ class TestController < ActionController::Base
class SetupFiberedBase < ActiveSupport::TestCase
def setup
view_paths = ActionController::Base.view_paths
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
+
@assigns = { secret: "in the sauce", name: nil }
- @view = ActionView::Base.with_view_paths(view_paths, @assigns)
+ @view = ActionView::Base.with_empty_template_cache.with_view_paths(view_paths, @assigns)
@controller_view = TestController.new.view_context
end
diff --git a/actionview/test/template/template_test.rb b/actionview/test/template/template_test.rb
index 8257d97b7c966bdca8726c48c9f6100132148f8e..a069c8f2d053c52da04e4f2e4888bf8441815188 100644
--- a/actionview/test/template/template_test.rb
+++ b/actionview/test/template/template_test.rb
@@ -19,7 +19,8 @@ def find_template(*args)
end
class Context < ActionView::Base
- def initialize
+ def initialize(*)
+ super
@output_buffer = "original"
@virtual_path = nil
end
@@ -63,7 +64,8 @@ def render(locals = {})
end
def setup
- @context = Context.new
+ @context = Context.with_empty_template_cache.empty
+ super
end
def test_basic_template
diff --git a/actionview/test/template/translation_helper_test.rb b/actionview/test/template/translation_helper_test.rb
index d04e68e182ca5d13030b50c1eaeb5909b1f5d246..23fc9850c46e2d553f461abb5f8b556a9a9216d9 100644
--- a/actionview/test/template/translation_helper_test.rb
+++ b/actionview/test/template/translation_helper_test.rb
@@ -36,7 +36,10 @@ class TranslationHelperTest < ActiveSupport::TestCase
}
}
)
- @view = ::ActionView::Base.with_view_paths(ActionController::Base.view_paths, {})
+ view_paths = ActionController::Base.view_paths
+ view_paths.each(&:clear_cache)
+ ActionView::LookupContext.fallbacks.each(&:clear_cache)
+ @view = ::ActionView::Base.with_empty_template_cache.with_view_paths(view_paths, {})
end
teardown do
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 2911b1f7c30911c127a37021022beba4fc976aa4..e7129dd274ec9d32ff6213e1a5d0751d9de6e0b9 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -590,13 +590,6 @@ Defaults to `'signed cookie'`.
* `config.action_view.default_enforce_utf8` determines whether forms are generated with a hidden tag that forces older versions of Internet Explorer to submit forms encoded in UTF-8. This defaults to `false`.
-* `config.action_view.finalize_compiled_template_methods` determines
- whether the methods on `ActionView::CompiledTemplates` that templates
- compile themselves to are removed when template instances are
- destroyed by the garbage collector. This helps prevent memory leaks in
- development mode, but for large test suites, disabling this option in
- the test environment can improve performance. This defaults to `true`.
-
### Configuring Action Mailbox
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
index 223aa5618725fc618b503bc755b8e6cc2bd0324c..63ed3fa952c7e5c04c9c36ae674a5a0ba47db2cb 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
@@ -48,7 +48,4 @@ Rails.application.configure do
# Raises error for missing translations.
# config.action_view.raise_on_missing_translations = true
-
- # Prevent expensive template finalization at end of test suite runs.
- config.action_view.finalize_compiled_template_methods = false
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 7006b0855f72bb926f68048012e0b33963f498fa..37fba72ee344fb9375a1a758062e0e9e44b99512 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -2094,7 +2094,9 @@ class ::DummySerializer < ActiveJob::Serializers::ObjectSerializer; end
test "ActionView::Template.finalize_compiled_template_methods is true by default" do
app "test"
- assert_equal true, ActionView::Template.finalize_compiled_template_methods
+ assert_deprecated do
+ ActionView::Template.finalize_compiled_template_methods
+ end
end
test "ActionView::Template.finalize_compiled_template_methods can be configured via config.action_view.finalize_compiled_template_methods" do
@@ -2106,7 +2108,9 @@ class ::DummySerializer < ActiveJob::Serializers::ObjectSerializer; end
app "test"
- assert_equal false, ActionView::Template.finalize_compiled_template_methods
+ assert_deprecated do
+ ActionView::Template.finalize_compiled_template_methods
+ end
end
test "ActiveJob::Base.return_false_on_aborted_enqueue is true by default" do