Sweeping 清理cache:
- class ListsController < ApplicationController
- caches_action :index, :show, :public, :feed
- cache_sweeper :list_sweeper, :only => [ :edit, :destroy, :share ]
- end
可以單獨定義:
- class ListSweeper < ActionController::Caching::Sweeper
- observe List, Item
- def after_lists_controller_update
- #clear cache
- end
- def after_save(record)
- list = record.is_a?(List) ? record : record.list
- expire_page(:controller => "lists", :action => %w( show public feed ), :id => list.id)
- expire_action(:controller => "lists", :action => "all")
- list.shares.each { |share| expire_page(:controller => "lists", :action => "show", :id => share.url_key) }
- end
- end
也可以定義在Module裡:
- class ListsController < ApplicationController
- caches_action :index, :show, :public, :feed
- cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ]
- end
實作:
- module Sweeping
- def self.included(base) #:nodoc:
- base.extend(ClassMethods)
- end
- module ClassMethods #:nodoc:
- def cache_sweeper(*sweepers)
- configuration = sweepers.extract_options!
- sweepers.each do |sweeper|
- ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base) # 增加一個監聽器
- sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(sweeper.to_s.classify) : sweeper).instance # 根據sweeper名字定義一個執行個體
- if sweeper_instance.is_a?(Sweeper) # 增加為filter
- around_filter(sweeper_instance, :only => configuration[:only])
- else
- after_filter(sweeper_instance, :only => configuration[:only])
- end
- end
- end
- end
- end
關鍵看Sweeper的實作:
- if defined?(ActiveRecord) and defined?(ActiveRecord::Observer)
- class Sweeper < ActiveRecord::Observer #:nodoc:
- attr_accessor :controller
- def before(controller)
- self.controller = controller
- callback(:before) if controller.perform_caching
- end
- def after(controller)
- callback(:after) if controller.perform_caching
- # Clean up, so that the controller can be collected after this request
- self.controller = nil
- end
- protected
- # gets the action cache path for the given options.
- def action_path_for(options)
- ActionController::Caching::Actions::ActionCachePath.path_for(controller, options)
- end
- # Retrieve instance variables set in the controller.
- def assigns(key)
- controller.instance_variable_get("@#{key}")
- end
- private
- def callback(timing)
- # 生成 controller 回調方法的名字,以及目前正在調用的 action 的名字
- controller_callback_method_name = "#{timing}_#{controller.controller_name.underscore}"
- action_callback_method_name = "#{controller_callback_method_name}_#{controller.action_name}"
- # 如果有這些方法那麼調用
- send!(controller_callback_method_name) if respond_to?(controller_callback_method_name, true)
- send!(action_callback_method_name) if respond_to?(action_callback_method_name, true)
- end
- def method_missing(method, *arguments)
- return if @controller.nil?
- @controller.send!(method, *arguments)
- end
- end
- end