Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added conditional support to caches_action [José Valim] [#166 state:r…

…esolved]
  • Loading branch information...
commit 7708650f73ddb4db300ea2059c60c1d907a4384e 1 parent bca8751
@josh josh authored
View
37 actionpack/lib/action_controller/caching/actions.rb
@@ -9,7 +9,7 @@ module Caching
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
# caches_page :public
- # caches_action :show, :feed
+ # caches_action :index, :show, :feed
# end
#
# In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the
@@ -27,15 +27,19 @@ module Caching
# You can set modify the default action cache path by passing a :cache_path option. This will be passed directly to ActionCachePath.path_for. 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 :if to pass a Proc that specifies when the action should be cached.
+ #
# class ListsController < ApplicationController
# before_filter :authenticate, :except => :public
# caches_page :public
+ # caches_action :index, :if => Proc.new { |c| !c.request.format.json? } # cache if is not a JSON request
# caches_action :show, :cache_path => { :project => 1 }
- # caches_action :show, :cache_path => Proc.new { |controller|
- # controller.params[:user_id] ?
+ # caches_action :feed, :cache_path => Proc.new { |controller|
+ # controller.params[:user_id] ?
# controller.send(:user_list_url, c.params[:user_id], c.params[:id]) :
# controller.send(:list_url, c.params[:id]) }
# end
+ #
module Actions
def self.included(base) #:nodoc:
base.extend(ClassMethods)
@@ -49,7 +53,8 @@ module ClassMethods
# See ActionController::Caching::Actions for details.
def caches_action(*actions)
return unless cache_configured?
- around_filter(ActionCacheFilter.new(*actions))
+ options = actions.extract_options!
+ around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path)), {:only => actions}.merge(options))
end
end
@@ -67,16 +72,12 @@ def expire_action(options = {})
end
class ActionCacheFilter #:nodoc:
- def initialize(*actions, &block)
- @options = actions.extract_options!
- @actions = Set.new(actions)
+ def initialize(options, &block)
+ @options = options
end
def before(controller)
- return unless @actions.include?(controller.action_name.intern)
-
cache_path = ActionCachePath.new(controller, path_options_for(controller, @options))
-
if cache = controller.read_fragment(cache_path.path)
controller.rendered_action_cache = true
set_content_type!(controller, cache_path.extension)
@@ -88,7 +89,7 @@ def before(controller)
end
def after(controller)
- return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || !caching_allowed(controller)
+ return if controller.rendered_action_cache || !caching_allowed(controller)
controller.write_fragment(controller.action_cache_path.path, controller.response.body)
end
@@ -105,16 +106,16 @@ def caching_allowed(controller)
controller.request.get? && controller.response.headers['Status'].to_i == 200
end
end
-
+
class ActionCachePath
attr_reader :path, :extension
-
+
class << self
def path_for(controller, options)
new(controller, options).path
end
end
-
+
def initialize(controller, options = {})
@extension = extract_extension(controller.request.path)
path = controller.url_for(options).split('://').last
@@ -122,16 +123,16 @@ def initialize(controller, options = {})
add_extension!(path, @extension)
@path = URI.unescape(path)
end
-
+
private
def normalize!(path)
path << 'index' if path[-1] == ?/
end
-
+
def add_extension!(path, extension)
path << ".#{extension}" if extension
end
-
+
def extract_extension(file_path)
# Don't want just what comes after the last '.' to accommodate multi part extensions
# such as tar.gz.
@@ -140,4 +141,4 @@ def extract_extension(file_path)
end
end
end
-end
+end
View
80 actionpack/test/controller/caching_test.rb
@@ -6,6 +6,7 @@
FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
ActionController::Base.page_cache_directory = FILE_STORE_PATH
ActionController::Base.cache_store = :file_store, FILE_STORE_PATH
+ActionController::Base.view_paths = [ File.dirname(__FILE__) + '/../fixtures/' ]
class PageCachingTestController < ActionController::Base
caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? }
@@ -128,7 +129,7 @@ def test_should_cache_ok_at_custom_path
end
end
end
-
+
def test_page_caching_conditional_options
@request.env['HTTP_ACCEPT'] = 'application/json'
get :ok
@@ -151,12 +152,15 @@ def page_cached?(action)
class ActionCachingTestController < ActionController::Base
- caches_action :index, :redirected, :forbidden
+ caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? }
caches_action :show, :cache_path => 'http://test.host/custom/show'
caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
+ caches_action :with_layout
+
+ layout 'talk_from_action.erb'
def index
- @cache_this = Time.now.to_f.to_s
+ @cache_this = MockTime.now.to_f.to_s
render :text => @cache_this
end
@@ -169,14 +173,26 @@ def forbidden
headers["Status"] = "403 Forbidden"
end
+ def with_layout
+ @cache_this = MockTime.now.to_f.to_s
+ render :text => @cache_this, :layout => true
+ end
+
alias_method :show, :index
alias_method :edit, :index
+ alias_method :destroy, :index
def expire
expire_action :controller => 'action_caching_test', :action => 'index'
render :nothing => true
end
+end
+class MockTime < Time
+ # Let Time spicy to assure that Time.now != Time.now
+ def to_f
+ super+rand
+ end
end
class ActionCachingMockController
@@ -223,6 +239,36 @@ def test_simple_action_cache
assert_equal cached_time, @response.body
end
+ def test_simple_action_not_cached
+ get :destroy
+ cached_time = content_to_cache
+ assert_equal cached_time, @response.body
+ assert_cache_does_not_exist 'hostname.com/action_caching_test/destroy'
+ reset!
+
+ get :destroy
+ assert_not_equal cached_time, @response.body
+ end
+
+ def test_action_cache_with_layout
+ get :with_layout
+ cached_time = content_to_cache
+ assert_not_equal cached_time, @response.body
+ assert_cache_exists 'hostname.com/action_caching_test/with_layout'
+ reset!
+
+ get :with_layout
+ assert_not_equal cached_time, @response.body
+
+ assert_equal @response.body, read_fragment('hostname.com/action_caching_test/with_layout')
+ end
+
+ def test_action_cache_conditional_options
+ @request.env['HTTP_ACCEPT'] = 'application/json'
+ get :index
+ assert_cache_does_not_exist 'hostname.com/action_caching_test'
+ end
+
def test_action_cache_with_custom_cache_path
get :show
cached_time = content_to_cache
@@ -350,9 +396,22 @@ def reset!
end
def assert_cache_exists(path)
- full_path = File.join(FILE_STORE_PATH, "views", path + '.cache')
+ full_path = cache_path(path)
assert File.exist?(full_path), "#{full_path.inspect} does not exist."
end
+
+ def assert_cache_does_not_exist(path)
+ full_path = cache_path(path)
+ assert !File.exist?(full_path), "#{full_path.inspect} should not exist."
+ end
+
+ def cache_path(path)
+ File.join(FILE_STORE_PATH, 'views', path + '.cache')
+ end
+
+ def read_fragment(path)
+ @controller.read_fragment(path)
+ end
end
class FragmentCachingTestController < ActionController::Base
@@ -516,7 +575,7 @@ class FunctionalFragmentCachingTest < Test::Unit::TestCase
def setup
ActionController::Base.perform_caching = true
@store = ActiveSupport::Cache::MemoryStore.new
- ActionController::Base.cache_store = @store
+ ActionController::Base.cache_store = @store
@controller = FunctionalCachingController.new
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@@ -529,17 +588,17 @@ def test_fragment_caching
This bit's fragment cached
CACHED
assert_equal expected_body, @response.body
-
+
assert_equal "This bit's fragment cached", @store.read('views/test.host/functional_caching/fragment_cached')
end
-
+
def test_fragment_caching_in_partials
get :html_fragment_cached_with_partial
assert_response :success
assert_match /Fragment caching in a partial/, @response.body
assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/html_fragment_cached_with_partial')
end
-
+
def test_fragment_caching_in_rjs_partials
xhr :get, :js_fragment_cached_with_partial
assert_response :success
@@ -547,8 +606,3 @@ def test_fragment_caching_in_rjs_partials
assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/js_fragment_cached_with_partial')
end
end
-
-
-
-
-
Please sign in to comment.
Something went wrong with that request. Please try again.