public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Search Repo:
Added conditional support to caches_action [José Valim] [#166 
state:resolved]
josh (author)
Wed May 14 10:33:54 -0700 2008
commit  7708650f73ddb4db300ea2059c60c1d907a4384e
tree    59618c18763e1d092cb9cac58cb45235819f1647
parent  bca8751e40a5594c4de2ca58e089b8d98e44632b
...
9
10
11
12
 
13
14
15
16
17
18
...
27
28
29
 
 
30
31
32
 
33
34
35
 
 
36
37
38
 
39
40
41
...
49
50
51
52
 
 
53
54
55
56
57
...
67
68
69
70
71
72
 
 
73
74
75
76
77
78
79
80
81
82
...
88
89
90
91
 
92
93
94
95
96
...
105
106
107
108
 
109
110
111
 
112
113
114
115
116
117
 
118
119
120
121
122
...
122
123
124
125
 
126
127
128
129
130
 
131
132
133
134
 
135
136
137
...
9
10
11
 
12
13
14
15
16
17
18
...
27
28
29
30
31
32
33
34
35
36
 
 
37
38
39
40
41
42
43
44
45
...
53
54
55
 
56
57
58
59
60
61
62
...
72
73
74
 
 
 
75
76
77
78
79
 
 
80
 
81
82
83
...
89
90
91
 
92
93
94
95
96
97
...
106
107
108
 
109
110
111
 
112
113
114
115
116
117
 
118
119
120
121
122
123
...
123
124
125
 
126
127
128
129
130
 
131
132
133
134
 
135
136
137
138
0
@@ -9,7 +9,7 @@
0
     # class ListsController < ApplicationController
0
     # before_filter :authenticate, :except => :public
0
     # caches_page :public
0
- # caches_action : :show, :feed
0
+ # caches_action :index, :show, :feed
0
     # end
0
     #
0
     # In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the
0
0
0
0
@@ -27,15 +27,19 @@
0
     # 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
0
     # for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance.
0
     #
0
+ # And you can also use :if to pass a Proc that specifies when the action should be cached.
0
+ #
0
     # class ListsController < ApplicationController
0
     # before_filter :authenticate, :except => :public
0
     # caches_page :public
0
+ # caches_action :index, :if => Proc.new { |c| !c.request.format.json? } # cache if is not a JSON request
0
     # caches_action :show, :cache_path => { :project => 1 }
0
- # caches_action :show, :cache_path => Proc.new { |controller|
0
- # controller.params[:user_id] ?
0
+ # caches_action :feed, :cache_path => Proc.new { |controller|
0
+ # controller.params[:user_id] ?
0
     # controller.send(:user_list_url, c.params[:user_id], c.params[:id]) :
0
     # controller.send(:list_url, c.params[:id]) }
0
     # end
0
+ #
0
     module Actions
0
       def self.included(base) #:nodoc:
0
         base.extend(ClassMethods)
0
@@ -49,7 +53,8 @@
0
         # See ActionController::Caching::Actions for details.
0
         def caches_action(*actions)
0
           return unless cache_configured?
0
- around_filter(ActionCacheFilter.new(*actions))
0
+ options = actions.extract_options!
0
+ around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path)), {:only => actions}.merge(options))
0
         end
0
       end
0
 
0
0
0
@@ -67,16 +72,12 @@
0
         end
0
 
0
       class ActionCacheFilter #:nodoc:
0
- def initialize(*actions, &block)
0
- @options = actions.extract_options!
0
- @actions = Set.new(actions)
0
+ def initialize(options, &block)
0
+ @options = options
0
         end
0
 
0
         def before(controller)
0
- return unless @actions.include?(controller.action_name.intern)
0
-
0
           cache_path = ActionCachePath.new(controller, path_options_for(controller, @options))
0
-
0
           if cache = controller.read_fragment(cache_path.path)
0
             controller.rendered_action_cache = true
0
             set_content_type!(controller, cache_path.extension)
0
@@ -88,7 +89,7 @@
0
         end
0
 
0
         def after(controller)
0
- return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || !caching_allowed(controller)
0
+ return if controller.rendered_action_cache || !caching_allowed(controller)
0
           controller.write_fragment(controller.action_cache_path.path, controller.response.body)
0
         end
0
 
0
0
0
@@ -105,16 +106,16 @@
0
             controller.request.get? && controller.response.headers['Status'].to_i == 200
0
           end
0
       end
0
-
0
+
0
       class ActionCachePath
0
         attr_reader :path, :extension
0
-
0
+
0
         class << self
0
           def path_for(controller, options)
0
             new(controller, options).path
0
           end
0
         end
0
-
0
+
0
         def initialize(controller, options = {})
0
           @extension = extract_extension(controller.request.path)
0
           path = controller.url_for(options).split('://').last
0
0
0
@@ -122,16 +123,16 @@
0
           add_extension!(path, @extension)
0
           @path = URI.unescape(path)
0
         end
0
-
0
+
0
         private
0
           def normalize!(path)
0
             path << 'index' if path[-1] == ?/
0
           end
0
-
0
+
0
           def add_extension!(path, extension)
0
             path << ".#{extension}" if extension
0
           end
0
-
0
+
0
           def extract_extension(file_path)
0
             # Don't want just what comes after the last '.' to accommodate multi part extensions
0
             # such as tar.gz.
...
6
7
8
 
9
10
11
...
128
129
130
131
 
132
133
134
135
136
137
...
151
152
153
154
 
155
156
 
157
 
 
158
159
 
160
161
162
163
164
165
...
169
170
171
 
 
 
 
 
172
173
 
174
175
176
177
178
 
179
 
 
 
 
 
180
181
182
...
223
224
225
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
226
227
228
229
...
350
351
352
353
 
354
355
 
 
 
 
 
 
 
 
 
 
 
 
 
356
357
358
...
516
517
518
519
 
520
521
522
523
524
...
529
530
531
532
 
533
534
535
 
536
537
538
539
540
541
542
 
543
544
545
...
6
7
8
9
10
11
12
...
129
130
131
 
132
133
134
135
136
137
138
...
152
153
154
 
155
156
157
158
159
160
161
162
 
163
164
165
166
167
168
169
...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
...
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
...
396
397
398
 
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
...
575
576
577
 
578
579
580
581
582
583
...
588
589
590
 
591
592
593
 
594
595
596
597
598
599
600
 
601
602
603
604
0
@@ -6,6 +6,7 @@
0
 FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
0
 ActionController::Base.page_cache_directory = FILE_STORE_PATH
0
 ActionController::Base.cache_store = :file_store, FILE_STORE_PATH
0
+ActionController::Base.view_paths = [ File.dirname(__FILE__) + '/../fixtures/' ]
0
 
0
 class PageCachingTestController < ActionController::Base
0
   caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? }
0
@@ -128,7 +129,7 @@
0
       end
0
     end
0
   end
0
-
0
+
0
   def test_page_caching_conditional_options
0
     @request.env['HTTP_ACCEPT'] = 'application/json'
0
     get :ok
0
0
0
0
@@ -151,12 +152,15 @@
0
 
0
 
0
 class ActionCachingTestController < ActionController::Base
0
- caches_action :index, :redirected, :forbidden
0
+ caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? }
0
   caches_action :show, :cache_path => 'http://test.host/custom/show'
0
   caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
0
+ caches_action :with_layout
0
 
0
+ layout 'talk_from_action.erb'
0
+
0
   def index
0
- @cache_this = Time.now.to_f.to_s
0
+ @cache_this = MockTime.now.to_f.to_s
0
     render :text => @cache_this
0
   end
0
 
0
0
0
0
@@ -169,14 +173,26 @@
0
     headers["Status"] = "403 Forbidden"
0
   end
0
 
0
+ def with_layout
0
+ @cache_this = MockTime.now.to_f.to_s
0
+ render :text => @cache_this, :layout => true
0
+ end
0
+
0
   alias_method :show, :index
0
   alias_method :edit, :index
0
+ alias_method :destroy, :index
0
 
0
   def expire
0
     expire_action :controller => 'action_caching_test', :action => 'index'
0
     render :nothing => true
0
   end
0
+end
0
 
0
+class MockTime < Time
0
+ # Let Time spicy to assure that Time.now != Time.now
0
+ def to_f
0
+ super+rand
0
+ end
0
 end
0
 
0
 class ActionCachingMockController
0
@@ -223,6 +239,36 @@
0
     assert_equal cached_time, @response.body
0
   end
0
 
0
+ def test_simple_action_not_cached
0
+ get :destroy
0
+ cached_time = content_to_cache
0
+ assert_equal cached_time, @response.body
0
+ assert_cache_does_not_exist 'hostname.com/action_caching_test/destroy'
0
+ reset!
0
+
0
+ get :destroy
0
+ assert_not_equal cached_time, @response.body
0
+ end
0
+
0
+ def test_action_cache_with_layout
0
+ get :with_layout
0
+ cached_time = content_to_cache
0
+ assert_not_equal cached_time, @response.body
0
+ assert_cache_exists 'hostname.com/action_caching_test/with_layout'
0
+ reset!
0
+
0
+ get :with_layout
0
+ assert_not_equal cached_time, @response.body
0
+
0
+ assert_equal @response.body, read_fragment('hostname.com/action_caching_test/with_layout')
0
+ end
0
+
0
+ def test_action_cache_conditional_options
0
+ @request.env['HTTP_ACCEPT'] = 'application/json'
0
+ get :index
0
+ assert_cache_does_not_exist 'hostname.com/action_caching_test'
0
+ end
0
+
0
   def test_action_cache_with_custom_cache_path
0
     get :show
0
     cached_time = content_to_cache
0
0
@@ -350,9 +396,22 @@
0
     end
0
 
0
     def assert_cache_exists(path)
0
- full_path = File.join(FILE_STORE_PATH, "views", path + '.cache')
0
+ full_path = cache_path(path)
0
       assert File.exist?(full_path), "#{full_path.inspect} does not exist."
0
     end
0
+
0
+ def assert_cache_does_not_exist(path)
0
+ full_path = cache_path(path)
0
+ assert !File.exist?(full_path), "#{full_path.inspect} should not exist."
0
+ end
0
+
0
+ def cache_path(path)
0
+ File.join(FILE_STORE_PATH, 'views', path + '.cache')
0
+ end
0
+
0
+ def read_fragment(path)
0
+ @controller.read_fragment(path)
0
+ end
0
 end
0
 
0
 class FragmentCachingTestController < ActionController::Base
0
@@ -516,7 +575,7 @@
0
   def setup
0
     ActionController::Base.perform_caching = true
0
     @store = ActiveSupport::Cache::MemoryStore.new
0
- ActionController::Base.cache_store = @store
0
+ ActionController::Base.cache_store = @store
0
     @controller = FunctionalCachingController.new
0
     @request = ActionController::TestRequest.new
0
     @response = ActionController::TestResponse.new
0
0
0
@@ -529,17 +588,17 @@
0
 This bit's fragment cached
0
 CACHED
0
     assert_equal expected_body, @response.body
0
-
0
+
0
     assert_equal "This bit's fragment cached", @store.read('views/test.host/functional_caching/fragment_cached')
0
   end
0
-
0
+
0
   def test_fragment_caching_in_partials
0
     get :html_fragment_cached_with_partial
0
     assert_response :success
0
     assert_match /Fragment caching in a partial/, @response.body
0
     assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/html_fragment_cached_with_partial')
0
   end
0
-
0
+
0
   def test_fragment_caching_in_rjs_partials
0
     xhr :get, :js_fragment_cached_with_partial
0
     assert_response :success

Comments

    No one has commented yet.