Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/trunk/actionpack/lib/action_controller/caching/sweeping.rb

Revision 8990, 3.8 kB (checked in by david, 9 months ago)

Fixed that sweepers defined by cache_sweeper will be added regardless of the perform_caching setting. Instead, control whether the sweeper should be run with the perform_caching setting. This makes testing easier when you want to turn perform_caching on/off [DHH]

Line 
1 module ActionController #:nodoc:
2   module Caching
3     # Sweepers are the terminators of the caching world and responsible for expiring caches when model objects change.
4     # They do this by being half-observers, half-filters and implementing callbacks for both roles. A Sweeper example:
5     #
6     #   class ListSweeper < ActionController::Caching::Sweeper
7     #     observe List, Item
8     #
9     #     def after_save(record)
10     #       list = record.is_a?(List) ? record : record.list
11     #       expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id)
12     #       expire_action(:controller => "lists", :action => "all")
13     #       list.shares.each { |share| expire_page(:controller => "lists", :action => "show", :id => share.url_key) }
14     #     end
15     #   end
16     #
17     # The sweeper is assigned in the controllers that wish to have its job performed using the <tt>cache_sweeper</tt> class method:
18     #
19     #   class ListsController < ApplicationController
20     #     caches_action :index, :show, :public, :feed
21     #     cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ]
22     #   end
23     #
24     # In the example above, four actions are cached and three actions are responsible for expiring those caches.
25     #
26     # You can also name an explicit class in the declaration of a sweeper, which is needed if the sweeper is in a module:
27     #
28     #   class ListsController < ApplicationController
29     #     caches_action :index, :show, :public, :feed
30     #     cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ]
31     #   end   
32     module Sweeping
33       def self.included(base) #:nodoc:
34         base.extend(ClassMethods)
35       end
36
37       module ClassMethods #:nodoc:
38         def cache_sweeper(*sweepers)
39           configuration = sweepers.extract_options!
40
41           sweepers.each do |sweeper|
42             ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base)
43             sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(Inflector.classify(sweeper)) : sweeper).instance
44
45             if sweeper_instance.is_a?(Sweeper)
46               around_filter(sweeper_instance, :only => configuration[:only])
47             else
48               after_filter(sweeper_instance, :only => configuration[:only])
49             end
50           end
51         end
52       end
53     end
54
55     if defined?(ActiveRecord) and defined?(ActiveRecord::Observer)
56       class Sweeper < ActiveRecord::Observer #:nodoc:
57         attr_accessor :controller
58
59         def before(controller)
60           self.controller = controller
61           callback(:before) if controller.perform_caching
62         end
63
64         def after(controller)
65           callback(:after) if controller.perform_caching
66           # Clean up, so that the controller can be collected after this request
67           self.controller = nil
68         end
69
70         protected
71           # gets the action cache path for the given options.
72           def action_path_for(options)
73             ActionController::Caching::Actions::ActionCachePath.path_for(controller, options)
74           end
75
76           # Retrieve instance variables set in the controller.
77           def assigns(key)
78             controller.instance_variable_get("@#{key}")
79           end
80
81         private
82           def callback(timing)
83             controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
84             action_callback_method_name     = "#{controller_callback_method_name}_#{controller.action_name}"
85
86             send!(controller_callback_method_name) if respond_to?(controller_callback_method_name, true)
87             send!(action_callback_method_name)     if respond_to?(action_callback_method_name, true)
88           end
89
90           def method_missing(method, *arguments)
91             return if @controller.nil?
92             @controller.send!(method, *arguments)
93           end
94       end
95     end
96   end
97 end
Note: See TracBrowser for help on using the browser.