diff options
-rw-r--r-- | actionpack/CHANGELOG.md | 5 | ||||
-rw-r--r-- | actionpack/lib/action_controller/caching.rb | 18 | ||||
-rw-r--r-- | actionpack/lib/action_view/digestor.rb | 21 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/cache_helper.rb | 2 | ||||
-rw-r--r-- | actionpack/test/controller/caching_test.rb | 18 | ||||
-rw-r--r-- | actionpack/test/template/digestor_test.rb | 18 |
6 files changed, 72 insertions, 10 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 6515a7b392..1a8f187979 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,10 @@ ## 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. diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb index 2892e093af..e31743bcc7 100644 --- a/actionpack/lib/action_controller/caching.rb +++ b/actionpack/lib/action_controller/caching.rb @@ -70,12 +70,30 @@ module ActionController 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) diff --git a/actionpack/lib/action_view/digestor.rb b/actionpack/lib/action_view/digestor.rb index f3f6b425a8..4507861dcc 100644 --- a/actionpack/lib/action_view/digestor.rb +++ b/actionpack/lib/action_view/digestor.rb @@ -24,16 +24,17 @@ module ActionView @@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 @@ module ActionView 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 @@ module ActionView def explicit_dependencies source.scan(EXPLICIT_DEPENDENCY).flatten.uniq end + + def injected_dependencies + Array.wrap(options[:dependencies]) + end end class PartialDigestor < Digestor # :nodoc: diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index 995aa10afb..8fc78ea7fb 100644 --- a/actionpack/lib/action_view/helpers/cache_helper.rb +++ b/actionpack/lib/action_view/helpers/cache_helper.rb @@ -167,7 +167,7 @@ module ActionView 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 diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb index 2428cd7433..eb5eeb0423 100644 --- a/actionpack/test/controller/caching_test.rb +++ b/actionpack/test/controller/caching_test.rb @@ -296,6 +296,24 @@ class CacheHelperOutputBufferTest < ActionController::TestCase 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 diff --git a/actionpack/test/template/digestor_test.rb b/actionpack/test/template/digestor_test.rb index 02b1fd87a8..849e2981a6 100644 --- a/actionpack/test/template/digestor_test.rb +++ b/actionpack/test/template/digestor_test.rb @@ -138,6 +138,20 @@ class TemplateDigestorTest < ActionView::TestCase 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 @@ class TemplateDigestorTest < ActionView::TestCase 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) |