Permalink
Browse files

Improve performance of action caching. Closes #8231 [skaes]

git-svn-id: http://svn-commit.rubyonrails.org/rails/branches/1-2-stable@7185 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent 40a188b commit e3670a0e24e56ade594f4f82a67e573e96f6e97d @NZKoz NZKoz committed Jul 14, 2007
Showing with 41 additions and 39 deletions.
  1. +2 −0 actionpack/CHANGELOG
  2. +36 −37 actionpack/lib/action_controller/caching.rb
  3. +3 −2 actionpack/test/controller/caching_test.rb
View
@@ -1,5 +1,7 @@
*SVN*
+* Improve performance of action caching. Closes #8231 [skaes]
+
* Fix errors with around_filters which do not yield, restore 1.1 behaviour with after filters. Closes #8891 [skaes]
After filters will *no longer* be run if an around_filter fails to yield, users relying on
@@ -1,5 +1,6 @@
require 'fileutils'
require 'uri'
+require 'set'
module ActionController #:nodoc:
# Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls
@@ -163,15 +164,24 @@ def caching_allowed
module Actions
def self.included(base) #:nodoc:
base.extend(ClassMethods)
- base.send(:attr_accessor, :rendered_action_cache)
+ base.class_eval do
+ attr_accessor :rendered_action_cache, :action_cache_path
+ alias_method_chain :protected_instance_variables, :action_caching
+ end
+ end
+
+ def protected_instance_variables_with_action_caching
+ protected_instance_variables_without_action_caching + %w(@action_cache_path)
end
module ClassMethods
# Declares that +actions+ should be cached.
# See ActionController::Caching::Actions for details.
def caches_action(*actions)
return unless perform_caching
- around_filter(ActionCacheFilter.new(*actions))
+ action_cache_filter = ActionCacheFilter.new(*actions)
+ before_filter action_cache_filter
+ after_filter action_cache_filter
end
end
@@ -187,70 +197,59 @@ def expire_action(options = {})
end
class ActionCacheFilter #:nodoc:
- def initialize(*actions, &block)
- @actions = actions
+ def initialize(*actions)
+ @actions = Set.new actions
end
def before(controller)
- return unless @actions.include?(controller.action_name.intern)
- action_cache_path = ActionCachePath.new(controller)
- if cache = controller.read_fragment(action_cache_path.path)
+ return unless @actions.include?(controller.action_name.to_sym)
+ cache_path = ActionCachePath.new(controller, {})
+ if cache = controller.read_fragment(cache_path.path)
controller.rendered_action_cache = true
- set_content_type!(action_cache_path)
+ set_content_type!(controller, cache_path.extension)
controller.send(:render_text, cache)
false
+ else
+ controller.action_cache_path = cache_path
end
end
def after(controller)
- return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache
- controller.write_fragment(ActionCachePath.path_for(controller), controller.response.body)
+ return if !@actions.include?(controller.action_name.to_sym) || controller.rendered_action_cache
+ controller.write_fragment(controller.action_cache_path.path, controller.response.body)
end
private
-
- def set_content_type!(action_cache_path)
- if extention = action_cache_path.extension
- content_type = Mime::EXTENSION_LOOKUP[extention]
- action_cache_path.controller.response.content_type = content_type.to_s
- end
+ def set_content_type!(controller, extension)
+ controller.response.content_type = Mime::EXTENSION_LOOKUP[extension].to_s if extension
end
end
class ActionCachePath
- attr_reader :controller, :options
+ attr_reader :path, :extension
class << self
- def path_for(*args, &block)
- new(*args).path
+ def path_for(controller, options)
+ new(controller, options).path
end
end
def initialize(controller, options = {})
- @controller = controller
- @options = options
- end
-
- def path
- return @path if @path
- @path = controller.url_for(options).split('://').last
- normalize!
- add_extension!
- URI.unescape(@path)
- end
-
- def extension
- @extension ||= extract_extension(controller.request.path)
+ @extension = extract_extension(controller.request.path)
+ path = controller.url_for(options).split('://').last
+ normalize!(path)
+ add_extension!(path, @extension)
+ @path = URI.unescape(path)
end
private
- def normalize!
- @path << 'index' if @path.last == '/'
+ def normalize!(path)
+ path << 'index' if path[-1] == ?/
end
- def add_extension!
- @path << ".#{extension}" if extension
+ def add_extension!(path, extension)
+ path << ".#{extension}" if extension
end
def extract_extension(file_path)
@@ -97,6 +97,7 @@ class ActionCachingTestController < ActionController::Base
caches_action :index
def index
+ sleep 0.01
@cache_this = Time.now.to_f.to_s
render :text => @cache_this
end
@@ -195,7 +196,7 @@ def test_cache_is_scoped_by_subdomain
def test_xml_version_of_resource_is_treated_as_different_cache
@mock_controller.mock_url_for = 'http://example.org/posts/'
@mock_controller.mock_path = '/posts/index.xml'
- path_object = @path_class.new(@mock_controller)
+ path_object = @path_class.new(@mock_controller, {})
assert_equal 'xml', path_object.extension
assert_equal 'example.org/posts/index.xml', path_object.path
end
@@ -204,7 +205,7 @@ def test_empty_path_is_normalized
@mock_controller.mock_url_for = 'http://example.org/'
@mock_controller.mock_path = '/'
- assert_equal 'example.org/index', @path_class.path_for(@mock_controller)
+ assert_equal 'example.org/index', @path_class.path_for(@mock_controller, {})
end
def test_file_extensions

0 comments on commit e3670a0

Please sign in to comment.