mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Bust the template digest cache key when details are changed
Since the lookup details will influence which template is resolved, they need to be included in the cache key -- otherwise two different templates may erroneously share the same digest value.
This commit is contained in:
parent
cb8174c57f
commit
77e79ecd92
3 changed files with 39 additions and 2 deletions
|
@ -13,6 +13,12 @@
|
||||||
|
|
||||||
*Josh Lauer*, *Justin Ridgewell*
|
*Josh Lauer*, *Justin Ridgewell*
|
||||||
|
|
||||||
|
* Fixed a bug where the lookup details were not being taken into account
|
||||||
|
when caching the digest of a template - changes to the details now
|
||||||
|
cause a different cache key to be used.
|
||||||
|
|
||||||
|
*Daniel Schierbeck*
|
||||||
|
|
||||||
* Added an `extname` hash option for `javascript_include_tag` method.
|
* Added an `extname` hash option for `javascript_include_tag` method.
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
|
|
|
@ -10,7 +10,10 @@ module ActionView
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def digest(name, format, finder, options = {})
|
def digest(name, format, finder, options = {})
|
||||||
cache_key = ([name, format] + Array.wrap(options[:dependencies])).join('.')
|
details_key = finder.details_key.hash
|
||||||
|
dependencies = Array.wrap(options[:dependencies])
|
||||||
|
cache_key = ([name, details_key, format] + dependencies).join('.')
|
||||||
|
|
||||||
# this is a correctly done double-checked locking idiom
|
# this is a correctly done double-checked locking idiom
|
||||||
# (ThreadSafe::Cache's lookups have volatile semantics)
|
# (ThreadSafe::Cache's lookups have volatile semantics)
|
||||||
@@cache[cache_key] || @@digest_monitor.synchronize do
|
@@cache[cache_key] || @@digest_monitor.synchronize do
|
||||||
|
|
|
@ -15,6 +15,16 @@ end
|
||||||
class FixtureFinder
|
class FixtureFinder
|
||||||
FIXTURES_DIR = "#{File.dirname(__FILE__)}/../fixtures/digestor"
|
FIXTURES_DIR = "#{File.dirname(__FILE__)}/../fixtures/digestor"
|
||||||
|
|
||||||
|
attr_reader :details
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@details = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
def details_key
|
||||||
|
details.hash
|
||||||
|
end
|
||||||
|
|
||||||
def find(logical_name, keys, partial, options)
|
def find(logical_name, keys, partial, options)
|
||||||
FixtureTemplate.new("digestor/#{partial ? logical_name.gsub(%r|/([^/]+)$|, '/_\1') : logical_name}.#{options[:formats].first}.erb")
|
FixtureTemplate.new("digestor/#{partial ? logical_name.gsub(%r|/([^/]+)$|, '/_\1') : logical_name}.#{options[:formats].first}.erb")
|
||||||
end
|
end
|
||||||
|
@ -140,6 +150,20 @@ class TemplateDigestorTest < ActionView::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_details_are_included_in_cache_key
|
||||||
|
# Cache the template digest.
|
||||||
|
old_digest = digest("events/_event")
|
||||||
|
|
||||||
|
# Change the template; the cached digest remains unchanged.
|
||||||
|
change_template("events/_event")
|
||||||
|
|
||||||
|
# The details are changed, so a new cache key is generated.
|
||||||
|
finder.details[:foo] = "bar"
|
||||||
|
|
||||||
|
# The cache is busted.
|
||||||
|
assert_not_equal old_digest, digest("events/_event")
|
||||||
|
end
|
||||||
|
|
||||||
def test_extra_whitespace_in_render_partial
|
def test_extra_whitespace_in_render_partial
|
||||||
assert_digest_difference("messages/edit") do
|
assert_digest_difference("messages/edit") do
|
||||||
change_template("messages/_form")
|
change_template("messages/_form")
|
||||||
|
@ -220,7 +244,11 @@ class TemplateDigestorTest < ActionView::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def digest(template_name, options={})
|
def digest(template_name, options={})
|
||||||
ActionView::Digestor.digest(template_name, :html, FixtureFinder.new, options)
|
ActionView::Digestor.digest(template_name, :html, finder, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def finder
|
||||||
|
@finder ||= FixtureFinder.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_template(template_name)
|
def change_template(template_name)
|
||||||
|
|
Loading…
Reference in a new issue