aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/caching.rb
diff options
context:
space:
mode:
authorMarcel Molina <marcel@vernix.org>2006-08-03 23:59:38 +0000
committerMarcel Molina <marcel@vernix.org>2006-08-03 23:59:38 +0000
commitd17bd6a0432dde66056e4dd417741731bcb9d323 (patch)
tree19fd6dfe4611d60c97f09e80a2bbacc5dc5ba3c9 /actionpack/lib/action_controller/caching.rb
parent58ebf302b206ed30568da60d7f3b124b26e9325b (diff)
downloadrails-d17bd6a0432dde66056e4dd417741731bcb9d323.tar.gz
rails-d17bd6a0432dde66056e4dd417741731bcb9d323.tar.bz2
rails-d17bd6a0432dde66056e4dd417741731bcb9d323.zip
Make action caching aware of different formats for the same action so that, e.g. foo.xml is cached separately from foo.html. Implicitly set content type when reading in cached content with mime revealing extensions so the entire onous isn't on the webserver. PDI MORE CACHING TESTS [Marcel Molina Jr.]
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@4656 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack/lib/action_controller/caching.rb')
-rw-r--r--actionpack/lib/action_controller/caching.rb70
1 files changed, 64 insertions, 6 deletions
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index 1556fd26ba..33193e56fe 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -155,6 +155,10 @@ module ActionController #:nodoc:
# the current host and the path. So a page that is accessed at http://david.somewhere.com/lists/show/1 will result in a fragment named
# "david.somewhere.com/lists/show/1". This allows the cacher to differentiate between "david.somewhere.com/lists/" and
# "jamis.somewhere.com/lists/" -- which is a helpful way of assisting the subdomain-as-account-key pattern.
+ #
+ # Different representations of the same resource, e.g. <tt>http://david.somewhere.com/lists</tt> and <tt>http://david.somewhere.com/lists.xml</tt>
+ # are treated like separate requests and are so are cached separately. Keep in mine when expiring an action cache that <tt>:action => 'lists'</tt> is not the same
+ # as <tt>:action => 'list', :format => :xml</tt>.
module Actions
def self.included(base) #:nodoc:
base.extend(ClassMethods)
@@ -172,22 +176,24 @@ module ActionController #:nodoc:
return unless perform_caching
if options[:action].is_a?(Array)
options[:action].dup.each do |action|
- expire_fragment(url_for(options.merge({ :action => action })).split("://").last)
+ expire_fragment(ActionCachePath.path_for(self, options.merge({ :action => action })))
end
else
- expire_fragment(url_for(options).split("://").last)
+ expire_fragment(ActionCachePath.path_for(self, options))
end
end
- class ActionCacheFilter #:nodoc:
- def initialize(*actions)
+ class ActionCacheFilter #:nodoc:
+ def initialize(*actions, &block)
@actions = actions
end
def before(controller)
return unless @actions.include?(controller.action_name.intern)
- if cache = controller.read_fragment(controller.url_for.split("://").last)
+ action_cache_path = ActionCachePath.new(controller)
+ if cache = controller.read_fragment(action_cache_path.path)
controller.rendered_action_cache = true
+ set_content_type!(action_cache_path)
controller.send(:render_text, cache)
false
end
@@ -195,8 +201,60 @@ module ActionController #:nodoc:
def after(controller)
return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache
- controller.write_fragment(controller.url_for.split("://").last, controller.response.body)
+ controller.write_fragment(ActionCachePath.path_for(controller), 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.headers['Content-Type'] = content_type.to_s
+ end
+ end
+
+ end
+
+ class ActionCachePath
+ attr_reader :controller, :options
+
+ class << self
+ def path_for(*args, &block)
+ new(*args).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)
+ end
+
+ private
+ def normalize!
+ @path << 'index' if @path.last == '/'
+ end
+
+ def add_extension!
+ @path << ".#{extension}" if extension
+ end
+
+ def extract_extension(file_path)
+ # Don't want just what comes after the last '.' to accomodate multi part extensions
+ # such as tar.gz.
+ file_path[/^[^.]+\.(.+)$/, 1]
+ end
end
end