提交 64e3660f 编写于 作者: D David Heinemeier Hansson

Merge pull request #8818 from jamis/master

view_cache_dependency API
## Rails 4.0.0 (unreleased) ##
* Added view_cache_dependency API for declaring dependencies that affect
cache digest computation.
*Jamis Buck*
* `image_submit_tag` will set `alt` attribute from image source if not
specified.
......
......@@ -70,12 +70,30 @@ def self.page_cache_extension
config_accessor :perform_caching
self.perform_caching = true if perform_caching.nil?
class_attribute :_view_cache_dependencies
self._view_cache_dependencies = []
helper_method :view_cache_dependencies if respond_to?(:helper_method)
end
module ClassMethods
def view_cache_dependency(&dependency)
self._view_cache_dependencies += [dependency]
end
def view_cache_dependencies
_view_cache_dependencies.map { |dep| instance_exec &dep }.compact
end
end
def caching_allowed?
request.get? && response.status == 200
end
def view_cache_dependencies
self.class.view_cache_dependencies
end
protected
# Convenience accessor.
def cache(key, options = {}, &block)
......
......@@ -24,16 +24,17 @@ class Digestor
@@cache = ThreadSafe::Cache.new
def self.digest(name, format, finder, options = {})
@@cache["#{name}.#{format}"] ||= begin
cache_key = [name, format] + Array.wrap(options[:dependencies])
@@cache[cache_key.join('.')] ||= begin
klass = options[:partial] || name.include?("/_") ? PartialDigestor : Digestor
klass.new(name, format, finder).digest
klass.new(name, format, finder, options).digest
end
end
attr_reader :name, :format, :finder
attr_reader :name, :format, :finder, :options
def initialize(name, format, finder)
@name, @format, @finder = name, format, finder
def initialize(name, format, finder, options={})
@name, @format, @finder, @options = name, format, finder, options
end
def digest
......@@ -81,9 +82,11 @@ def source
end
def dependency_digest
dependencies.collect do |template_name|
template_digests = dependencies.collect do |template_name|
Digestor.digest(template_name, format, finder, partial: true)
end.join("-")
end
(template_digests + injected_dependencies).join("-")
end
def render_dependencies
......@@ -105,6 +108,10 @@ def render_dependencies
def explicit_dependencies
source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
end
def injected_dependencies
Array.wrap(options[:dependencies])
end
end
class PartialDigestor < Digestor # :nodoc:
......
......@@ -167,7 +167,7 @@ def fragment_name_with_digest(name) #:nodoc:
if @virtual_path
[
*Array(name.is_a?(Hash) ? controller.url_for(name).split("://").last : name),
Digestor.digest(@virtual_path, formats.last.to_sym, lookup_context)
Digestor.digest(@virtual_path, formats.last.to_sym, lookup_context, dependencies: view_cache_dependencies)
]
else
name
......
......@@ -296,6 +296,24 @@ def test_safe_buffer
end
end
class ViewCacheDependencyTest < ActionController::TestCase
class NoDependenciesController < ActionController::Base
end
class HasDependenciesController < ActionController::Base
view_cache_dependency { "trombone" }
view_cache_dependency { "flute" }
end
def test_view_cache_dependencies_are_empty_by_default
assert NoDependenciesController.view_cache_dependencies.empty?
end
def test_view_cache_dependencies_are_listed_in_declaration_order
assert_equal %w(trombone flute), HasDependenciesController.view_cache_dependencies
end
end
class DeprecatedPageCacheExtensionTest < ActiveSupport::TestCase
def test_page_cache_extension_binds_default_static_extension
deprecation_behavior = ActiveSupport::Deprecation.behavior
......
......@@ -138,6 +138,20 @@ def test_old_style_hash_in_render_invocation
end
end
def test_dependencies_via_options_results_in_different_digest
digest_plain = digest("comments/_comment")
digest_fridge = digest("comments/_comment", dependencies: ["fridge"])
digest_phone = digest("comments/_comment", dependencies: ["phone"])
digest_fridge_phone = digest("comments/_comment", dependencies: ["fridge", "phone"])
assert_not_equal digest_plain, digest_fridge
assert_not_equal digest_plain, digest_phone
assert_not_equal digest_plain, digest_fridge_phone
assert_not_equal digest_fridge, digest_phone
assert_not_equal digest_fridge, digest_fridge_phone
assert_not_equal digest_phone, digest_fridge_phone
end
private
def assert_logged(message)
old_logger = ActionView::Base.logger
......@@ -164,8 +178,8 @@ def assert_digest_difference(template_name)
ActionView::Digestor.cache.clear
end
def digest(template_name)
ActionView::Digestor.digest(template_name, :html, FixtureFinder.new)
def digest(template_name, options={})
ActionView::Digestor.digest(template_name, :html, FixtureFinder.new, options)
end
def change_template(template_name)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册