1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Merge pull request #35623 from jhawthorn/actionview_cache

Make Template::Resolver always cache
This commit is contained in:
Aaron Patterson 2019-03-15 14:19:17 -07:00 committed by GitHub
commit d7e4cb87d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 13 additions and 98 deletions

View file

@ -22,11 +22,11 @@ module ActionView
# to ensure that references to the template object can be marshalled as well. This means forgoing
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
def marshal_dump # :nodoc:
[ @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant ]
[ @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
end
def marshal_load(array) # :nodoc:
@identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant = *array
@identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
@compile_mutex = Mutex.new
end
end

View file

@ -122,10 +122,10 @@ module ActionView
extend Template::Handlers
attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
attr_reader :source, :identifier, :handler, :original_encoding
attr_reader :variable, :format, :variant, :locals, :virtual_path
def initialize(source, identifier, handler, format: nil, variant: nil, locals: nil, virtual_path: nil, updated_at: Time.now)
def initialize(source, identifier, handler, format: nil, variant: nil, locals: nil, virtual_path: nil)
unless locals
ActiveSupport::Deprecation.warn "ActionView::Template#initialize requires a locals parameter"
locals = []
@ -144,7 +144,6 @@ module ActionView
$1.to_sym
end
@updated_at = updated_at
@format = format
@variant = variant
@compile_mutex = Mutex.new
@ -261,11 +260,11 @@ module ActionView
# to ensure that references to the template object can be marshalled as well. This means forgoing
# the marshalling of the compiler mutex and instantiating that again on unmarshalling.
def marshal_dump # :nodoc:
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant ]
[ @source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant ]
end
def marshal_load(array) # :nodoc:
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @updated_at, @format, @variant = *array
@source, @identifier, @handler, @compiled, @locals, @virtual_path, @format, @variant = *array
@compile_mutex = Mutex.new
end

View file

@ -63,26 +63,11 @@ module ActionView
# Cache the templates returned by the block
def cache(key, name, prefix, partial, locals)
if Resolver.caching?
@data[key][name][prefix][partial][locals] ||= canonical_no_templates(yield)
else
fresh_templates = yield
cached_templates = @data[key][name][prefix][partial][locals]
if templates_have_changed?(cached_templates, fresh_templates)
@data[key][name][prefix][partial][locals] = canonical_no_templates(fresh_templates)
else
cached_templates || NO_TEMPLATES
end
end
end
def cache_query(query) # :nodoc:
if Resolver.caching?
@query_cache[query] ||= canonical_no_templates(yield)
else
yield
end
end
def clear
@ -112,19 +97,6 @@ module ActionView
def canonical_no_templates(templates)
templates.empty? ? NO_TEMPLATES : templates
end
def templates_have_changed?(cached_templates, fresh_templates)
# if either the old or new template list is empty, we don't need to (and can't)
# compare modification times, and instead just check whether the lists are different
if cached_templates.blank? || fresh_templates.blank?
return fresh_templates.blank? != cached_templates.blank?
end
cached_templates_max_updated_at = cached_templates.map(&:updated_at).max
# if a template has changed, it will be now be newer than all the cached templates
fresh_templates.any? { |t| t.updated_at > cached_templates_max_updated_at }
end
end
cattr_accessor :caching, default: true
@ -218,8 +190,7 @@ module ActionView
virtual_path: path.virtual,
format: format,
variant: variant,
locals: locals,
updated_at: mtime(template)
locals: locals
)
end
end
@ -272,11 +243,6 @@ module ActionView
entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
end
# Returns the file mtime from the filesystem.
def mtime(p)
File.mtime(p)
end
# Extract handler, formats and variant from path. If a format cannot be found neither
# from the path, or the handler, we should return the array of formats given
# to the resolver.

View file

@ -31,16 +31,14 @@ module ActionView #:nodoc:
query = /^(#{Regexp.escape(path)})#{query}$/
templates = []
@hash.each do |_path, array|
source, updated_at = array
@hash.each do |_path, source|
next unless query.match?(_path)
handler, format, variant = extract_handler_and_format_and_variant(_path)
templates << Template.new(source, _path, handler,
virtual_path: path.virtual,
format: format,
variant: variant,
locals: locals,
updated_at: updated_at
locals: locals
)
end

View file

@ -326,12 +326,14 @@ class TemplateDigestorTest < ActionView::TestCase
def assert_digest_difference(template_name, options = {})
previous_digest = digest(template_name, options)
finder.view_paths.each(&:clear_cache)
finder.digest_cache.clear
yield
assert_not_equal previous_digest, digest(template_name, options), "digest didn't change"
finder.digest_cache.clear
finder.view_paths.each(&:clear_cache)
end
def digest(template_name, options = {})

View file

@ -235,56 +235,6 @@ class LookupContextTest < ActiveSupport::TestCase
end
end
class LookupContextWithFalseCaching < ActiveSupport::TestCase
def setup
@resolver = ActionView::FixtureResolver.new("test/_foo.erb" => ["Foo", Time.utc(2000)])
@lookup_context = ActionView::LookupContext.new(@resolver, {})
end
test "templates are always found in the resolver but timestamp is checked before being compiled" do
ActionView::Resolver.stub(:caching?, false) do
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source
# Now we are going to change the template, but it won't change the returned template
# since the timestamp is the same.
@resolver.data["test/_foo.erb"][0] = "Bar"
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source
# Now update the timestamp.
@resolver.data["test/_foo.erb"][1] = Time.now.utc
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Bar", template.source
end
end
test "if no template was found in the second lookup, with no cache, raise error" do
ActionView::Resolver.stub(:caching?, false) do
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source
@resolver.data.clear
assert_raise ActionView::MissingTemplate do
@lookup_context.find("foo", %w(test), true)
end
end
end
test "if no template was cached in the first lookup, retrieval should work in the second call" do
ActionView::Resolver.stub(:caching?, false) do
@resolver.data.clear
assert_raise ActionView::MissingTemplate do
@lookup_context.find("foo", %w(test), true)
end
@resolver.data["test/_foo.erb"] = ["Foo", Time.utc(2000)]
template = @lookup_context.find("foo", %w(test), true)
assert_equal "Foo", template.source
end
end
end
class TestMissingTemplate < ActiveSupport::TestCase
def setup
@lookup_context = ActionView::LookupContext.new("/Path/to/views", {})