aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/caching
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_controller/caching')
-rw-r--r--actionpack/lib/action_controller/caching/actions.rb17
-rw-r--r--actionpack/lib/action_controller/caching/fragments.rb44
-rw-r--r--actionpack/lib/action_controller/caching/pages.rb18
-rw-r--r--actionpack/lib/action_controller/caching/sweeping.rb24
4 files changed, 47 insertions, 56 deletions
diff --git a/actionpack/lib/action_controller/caching/actions.rb b/actionpack/lib/action_controller/caching/actions.rb
index ba96735e56..eb3aa05a25 100644
--- a/actionpack/lib/action_controller/caching/actions.rb
+++ b/actionpack/lib/action_controller/caching/actions.rb
@@ -40,14 +40,14 @@ module ActionController #:nodoc:
#
# You can modify the default action cache path by passing a
# <tt>:cache_path</tt> option. This will be passed directly to
- # <tt>ActionCachePath.path_for</tt>. This is handy for actions with
+ # <tt>ActionCachePath.new</tt>. This is handy for actions with
# multiple possible routes that should be cached differently. If a
# block is given, it is called with the current controller instance.
#
# And you can also use <tt>:if</tt> (or <tt>:unless</tt>) to pass a
# proc that specifies when the action should be cached.
#
- # As of Rails 3.0, you can also pass <tt>:expires_in</tt> with a time
+ # As of Rails 3.0, you can also pass <tt>:expires_in</tt> with a time
# interval (in seconds) to schedule expiration of the cached item.
#
# The following example depicts some of the points made above:
@@ -132,7 +132,9 @@ module ActionController #:nodoc:
options.values_at(:cache_path, :store_options, :layout)
end
- def filter(controller)
+ def around(controller)
+ cache_layout = @cache_layout.respond_to?(:call) ? @cache_layout.call(controller) : @cache_layout
+
path_options = if @cache_path.respond_to?(:call)
controller.instance_exec(controller, &@cache_path)
else
@@ -144,13 +146,13 @@ module ActionController #:nodoc:
body = controller.read_fragment(cache_path.path, @store_options)
unless body
- controller.action_has_layout = false unless @cache_layout
+ controller.action_has_layout = false unless cache_layout
yield
controller.action_has_layout = true
body = controller._save_fragment(cache_path.path, @store_options)
end
- body = controller.render_to_string(:text => body, :layout => true) unless @cache_layout
+ body = controller.render_to_string(:text => body, :layout => true) unless cache_layout
controller.response_body = body
controller.content_type = Mime[cache_path.extension || :html]
@@ -170,14 +172,15 @@ module ActionController #:nodoc:
options.reverse_merge!(:format => @extension) if options.is_a?(Hash)
end
- path = controller.url_for(options).split(%r{://}).last
+ path = controller.url_for(options).split('://', 2).last
@path = normalize!(path)
end
private
def normalize!(path)
+ ext = URI.parser.escape(extension) if extension
path << 'index' if path[-1] == ?/
- path << ".#{extension}" if extension and !path.split('?').first.ends_with?(".#{extension}")
+ path << ".#{ext}" if extension and !path.split('?', 2).first.ends_with?(".#{ext}")
URI.parser.unescape(path)
end
end
diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb
index abeb49d16f..9c77b0ccf4 100644
--- a/actionpack/lib/action_controller/caching/fragments.rb
+++ b/actionpack/lib/action_controller/caching/fragments.rb
@@ -5,48 +5,18 @@ module ActionController #:nodoc:
# useful when certain elements of an action change frequently or
# depend on complicated state while other parts rarely change or
# can be shared amongst multiple parties. The caching is done using
- # the <tt>cache</tt> helper available in the Action View. A
- # template with fragment caching might look like:
+ # the <tt>cache</tt> helper available in the Action View. See
+ # ActionView::Helpers::CacheHelper for more information.
#
- # <b>Hello <%= @name %></b>
+ # While it's strongly recommended that you use key-based cache
+ # expiration (see links in CacheHelper for more information),
+ # it is also possible to manually expire caches. For example:
#
- # <% cache do %>
- # All the topics in the system:
- # <%= render :partial => "topic", :collection => Topic.all %>
- # <% end %>
- #
- # This cache will bind the name of the action that called it, so if
- # this code was part of the view for the topics/list action, you
- # would be able to invalidate it using:
- #
- # expire_fragment(:controller => "topics", :action => "list")
- #
- # This default behavior is limited if you need to cache multiple
- # fragments per action or if the action itself is cached using
- # <tt>caches_action</tt>. To remedy this, there is an option to
- # qualify the name of the cached fragment by using the
- # <tt>:action_suffix</tt> option:
- #
- # <% cache(:action => "list", :action_suffix => "all_topics") do %>
- #
- # That would result in a name such as
- # <tt>/topics/list/all_topics</tt>, avoiding conflicts with the
- # action cache and with any fragments that use a different suffix.
- # Note that the URL doesn't have to really exist or be callable
- # - the url_for system is just used to generate unique cache names
- # that we can refer to when we need to expire the cache.
- #
- # The expiration call for this example is:
- #
- # expire_fragment(:controller => "topics",
- # :action => "list",
- # :action_suffix => "all_topics")
+ # expire_fragment("name_of_cache")
module Fragments
# Given a key (as described in <tt>expire_fragment</tt>), returns
# a key suitable for use in reading, writing, or expiring a
- # cached fragment. If the key is a hash, the generated key is the
- # return value of url_for on that hash (without the protocol).
- # All keys are prefixed with <tt>views/</tt> and uses
+ # cached fragment. All keys are prefixed with <tt>views/</tt> and uses
# ActiveSupport::Cache.expand_cache_key for the expansion.
def fragment_cache_key(key)
ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views)
diff --git a/actionpack/lib/action_controller/caching/pages.rb b/actionpack/lib/action_controller/caching/pages.rb
index 159f718029..73b8cd383c 100644
--- a/actionpack/lib/action_controller/caching/pages.rb
+++ b/actionpack/lib/action_controller/caching/pages.rb
@@ -60,7 +60,8 @@ module ActionController #:nodoc:
end
module ClassMethods
- # Expires the page that was cached with the +path+ as a key. Example:
+ # Expires the page that was cached with the +path+ as a key.
+ #
# expire_page "/lists/show"
def expire_page(path)
return unless perform_caching
@@ -72,7 +73,8 @@ module ActionController #:nodoc:
end
end
- # Manually cache the +content+ in the key determined by +path+. Example:
+ # Manually cache the +content+ in the key determined by +path+.
+ #
# cache_page "I'm the cached content", "/lists/show"
def cache_page(content, path, extension = nil, gzip = Zlib::BEST_COMPRESSION)
return unless perform_caching
@@ -93,13 +95,11 @@ module ActionController #:nodoc:
#
# You can also pass a :gzip option to override the class configuration one.
#
- # Usage:
- #
# # cache the index action
# caches_page :index
#
# # cache the index action except for JSON requests
- # caches_page :index, :if => Proc.new { |c| !c.request.format.json? }
+ # caches_page :index, :if => Proc.new { !request.format.json? }
#
# # don't gzip images
# caches_page :image, :gzip => false
@@ -110,7 +110,7 @@ module ActionController #:nodoc:
gzip_level = options.fetch(:gzip, page_cache_compression)
gzip_level = case gzip_level
when Symbol
- Zlib.const_get(gzip_level.to_s.upcase)
+ Zlib.const_get(gzip_level.upcase)
when Fixnum
gzip_level
when false
@@ -142,7 +142,8 @@ module ActionController #:nodoc:
end
end
- # Expires the page that was cached with the +options+ as a key. Example:
+ # Expires the page that was cached with the +options+ as a key.
+ #
# expire_page :controller => "lists", :action => "show"
def expire_page(options = {})
return unless self.class.perform_caching
@@ -161,7 +162,8 @@ module ActionController #:nodoc:
end
# Manually cache the +content+ in the key determined by +options+. If no content is provided, the contents of response.body is used.
- # If no options are provided, the url of the current request being handled is used. Example:
+ # If no options are provided, the url of the current request being handled is used.
+ #
# cache_page "I'm the cached content", :controller => "lists", :action => "show"
def cache_page(content = nil, options = nil, gzip = Zlib::BEST_COMPRESSION)
return unless self.class.perform_caching && caching_allowed?
diff --git a/actionpack/lib/action_controller/caching/sweeping.rb b/actionpack/lib/action_controller/caching/sweeping.rb
index 49cf70ec21..271d5f06b8 100644
--- a/actionpack/lib/action_controller/caching/sweeping.rb
+++ b/actionpack/lib/action_controller/caching/sweeping.rb
@@ -1,6 +1,6 @@
module ActionController #:nodoc:
module Caching
- # Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.
+ # Sweepers are the terminators of the caching world and responsible for expiring caches when Active Record objects change.
# They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:
#
# class ListSweeper < ActionController::Caching::Sweeper
@@ -54,6 +54,11 @@ module ActionController #:nodoc:
class Sweeper < ActiveRecord::Observer #:nodoc:
attr_accessor :controller
+ def initialize(*args)
+ super
+ @controller = nil
+ end
+
def before(controller)
self.controller = controller
callback(:before) if controller.perform_caching
@@ -63,8 +68,14 @@ module ActionController #:nodoc:
def after(controller)
self.controller = controller
callback(:after) if controller.perform_caching
- # Clean up, so that the controller can be collected after this request
- self.controller = nil
+ end
+
+ def around(controller)
+ before(controller)
+ yield
+ after(controller)
+ ensure
+ clean_up
end
protected
@@ -79,6 +90,11 @@ module ActionController #:nodoc:
end
private
+ def clean_up
+ # Clean up, so that the controller can be collected after this request
+ self.controller = nil
+ end
+
def callback(timing)
controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}"
@@ -88,7 +104,7 @@ module ActionController #:nodoc:
end
def method_missing(method, *arguments, &block)
- return unless @controller
+ return super unless @controller
@controller.__send__(method, *arguments, &block)
end
end