actionpack-page_caching 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of actionpack-page_caching might be problematic. Click here for more details.

@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+ before_install:
3
+ - gem install bundler
4
+ rvm:
5
+ - 1.9.3
6
+ notifications:
7
+ email: false
8
+ irc:
9
+ on_success: change
10
+ on_failure: always
11
+ channels:
12
+ - "irc.freenode.org#rails-contrib"
13
+ campfire:
14
+ on_success: change
15
+ on_failure: always
16
+ rooms:
17
+ - secure: "eRCx+FMvH50pmLu0GZTF7NN+2X+CesgodYUlHvCr5EXQ0ZO/YUmeW8vAh/N8\njSrLWYpk/4P/JA63JGWsvFor/zpkTnfwzX3LWgw04GV0V3T9jsn9CD2Coiu6\nFll5u4fUCUwpfbB4RlCkjvFdQmW+F9mmbRGMCDO5CmuPHOyyPH0="
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rails', '~> 4.0.0.beta1'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 David Heinemeier Hansson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,69 @@
1
+ actionpack-page_caching
2
+ =======================
3
+
4
+ Static page caching for Action Pack (removed from core in Rails 4.0)
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'actionpack-page_caching'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install actionpack-page_caching
20
+
21
+ Usage
22
+ -----
23
+
24
+ Page caching is an approach to caching where the entire action output of is
25
+ stored as a HTML file that the web server can serve without going through
26
+ Action Pack. This is the fastest way to cache your content as opposed to going
27
+ dynamically through the process of generating the content. Unfortunately, this
28
+ incredible speed-up is only available to stateless pages where all visitors are
29
+ treated the same. Content management systems -- including weblogs and wikis --
30
+ have many pages that are a great fit for this approach, but account-based systems
31
+ where people log in and manipulate their own data are often less likely candidates.
32
+
33
+ Specifying which actions to cache is done through the `caches_page` class method:
34
+
35
+ class WeblogController < ActionController::Base
36
+ caches_page :show, :new
37
+ end
38
+
39
+ This will generate cache files such as `weblog/show/5.html` and
40
+ `weblog/new.html`, which match the URLs used that would normally trigger
41
+ dynamic page generation. Page caching works by configuring a web server to first
42
+ check for the existence of files on disk, and to serve them directly when found,
43
+ without passing the request through to Action Pack. This is much faster than
44
+ handling the full dynamic request in the usual way.
45
+
46
+ Expiration of the cache is handled by deleting the cached file, which results
47
+ in a lazy regeneration approach where the cache is not restored before another
48
+ hit is made against it. The API for doing so mimics the options from `url_for`
49
+ and friends:
50
+
51
+ class WeblogController < ActionController::Base
52
+ def update
53
+ List.update(params[:list][:id], params[:list])
54
+ expire_page action: 'show', id: params[:list][:id]
55
+ redirect_to action: 'show', id: params[:list][:id]
56
+ end
57
+ end
58
+
59
+ Additionally, you can expire caches using [Sweepers](http://edgeapi.rubyonrails.org/classes/ActionController/Caching/Sweeping.html)
60
+ that act on changes in the model to determine when a cache is supposed to be expired.
61
+
62
+ Contributing
63
+ ------------
64
+
65
+ 1. Fork it.
66
+ 2. Create your feature branch (`git checkout -b my-new-feature`).
67
+ 3. Commit your changes (`git commit -am 'Add some feature'`).
68
+ 4. Push to the branch (`git push origin my-new-feature`).
69
+ 5. Create a new Pull Request.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs = ['test']
7
+ t.pattern = 'test/**/*_test.rb'
8
+ t.ruby_opts = ['-w']
9
+ end
10
+
11
+ task default: :test
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'actionpack-page_caching'
5
+ gem.version = '1.0.0'
6
+ gem.author = 'David Heinemeier Hansson'
7
+ gem.email = '[email protected]'
8
+ gem.description = 'Static page caching for Action Pack (removed from core in Rails 4.0)'
9
+ gem.summary = 'Static page caching for Action Pack (removed from core in Rails 4.0)'
10
+ gem.homepage = 'https://github.com/rails/actionpack-page_caching'
11
+
12
+ gem.files = `git ls-files`.split($/)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.require_paths = ['lib']
16
+
17
+ gem.add_dependency 'actionpack', '>= 4.0.0.beta', '< 5.0'
18
+
19
+ gem.add_development_dependency 'mocha'
20
+ end
@@ -0,0 +1,194 @@
1
+ require 'fileutils'
2
+ require 'active_support/core_ext/class/attribute_accessors'
3
+
4
+ module ActionController
5
+ module Caching
6
+ # Page caching is an approach to caching where the entire action output of is
7
+ # stored as a HTML file that the web server can serve without going through
8
+ # Action Pack. This is the fastest way to cache your content as opposed to going
9
+ # dynamically through the process of generating the content. Unfortunately, this
10
+ # incredible speed-up is only available to stateless pages where all visitors are
11
+ # treated the same. Content management systems -- including weblogs and wikis --
12
+ # have many pages that are a great fit for this approach, but account-based systems
13
+ # where people log in and manipulate their own data are often less likely candidates.
14
+ #
15
+ # Specifying which actions to cache is done through the +caches_page+ class method:
16
+ #
17
+ # class WeblogController < ActionController::Base
18
+ # caches_page :show, :new
19
+ # end
20
+ #
21
+ # This will generate cache files such as <tt>weblog/show/5.html</tt> and
22
+ # <tt>weblog/new.html</tt>, which match the URLs used that would normally trigger
23
+ # dynamic page generation. Page caching works by configuring a web server to first
24
+ # check for the existence of files on disk, and to serve them directly when found,
25
+ # without passing the request through to Action Pack. This is much faster than
26
+ # handling the full dynamic request in the usual way.
27
+ #
28
+ # Expiration of the cache is handled by deleting the cached file, which results
29
+ # in a lazy regeneration approach where the cache is not restored before another
30
+ # hit is made against it. The API for doing so mimics the options from +url_for+ and friends:
31
+ #
32
+ # class WeblogController < ActionController::Base
33
+ # def update
34
+ # List.update(params[:list][:id], params[:list])
35
+ # expire_page action: 'show', id: params[:list][:id]
36
+ # redirect_to action: 'show', id: params[:list][:id]
37
+ # end
38
+ # end
39
+ #
40
+ # Additionally, you can expire caches using Sweepers that act on changes in
41
+ # the model to determine when a cache is supposed to be expired.
42
+ module Pages
43
+ extend ActiveSupport::Concern
44
+
45
+ included do
46
+ # The cache directory should be the document root for the web server and is
47
+ # set using <tt>Base.page_cache_directory = "/document/root"</tt>. For Rails,
48
+ # this directory has already been set to Rails.public_path (which is usually
49
+ # set to <tt>Rails.root + "/public"</tt>). Changing this setting can be useful
50
+ # to avoid naming conflicts with files in <tt>public/</tt>, but doing so will
51
+ # likely require configuring your web server to look in the new location for
52
+ # cached files.
53
+ class_attribute :page_cache_directory
54
+ self.page_cache_directory ||= ''
55
+
56
+ # The compression used for gzip. If +false+ (default), the page is not compressed.
57
+ # If can be a symbol showing the ZLib compression method, for example, <tt>:best_compression</tt>
58
+ # or <tt>:best_speed</tt> or an integer configuring the compression level.
59
+ class_attribute :page_cache_compression
60
+ self.page_cache_compression ||= false
61
+ end
62
+
63
+ module ClassMethods
64
+ # Expires the page that was cached with the +path+ as a key.
65
+ #
66
+ # expire_page '/lists/show'
67
+ def expire_page(path)
68
+ return unless perform_caching
69
+ path = page_cache_path(path)
70
+
71
+ instrument_page_cache :expire_page, path do
72
+ File.delete(path) if File.exist?(path)
73
+ File.delete(path + '.gz') if File.exist?(path + '.gz')
74
+ end
75
+ end
76
+
77
+ # Manually cache the +content+ in the key determined by +path+.
78
+ #
79
+ # cache_page "I'm the cached content", '/lists/show'
80
+ def cache_page(content, path, extension = nil, gzip = Zlib::BEST_COMPRESSION)
81
+ return unless perform_caching
82
+ path = page_cache_path(path, extension)
83
+
84
+ instrument_page_cache :write_page, path do
85
+ FileUtils.makedirs(File.dirname(path))
86
+ File.open(path, 'wb+') { |f| f.write(content) }
87
+ if gzip
88
+ Zlib::GzipWriter.open(path + '.gz', gzip) { |f| f.write(content) }
89
+ end
90
+ end
91
+ end
92
+
93
+ # Caches the +actions+ using the page-caching approach that'll store
94
+ # the cache in a path within the +page_cache_directory+ that
95
+ # matches the triggering url.
96
+ #
97
+ # You can also pass a <tt>:gzip</tt> option to override the class configuration one.
98
+ #
99
+ # # cache the index action
100
+ # caches_page :index
101
+ #
102
+ # # cache the index action except for JSON requests
103
+ # caches_page :index, if: Proc.new { !request.format.json? }
104
+ #
105
+ # # don't gzip images
106
+ # caches_page :image, gzip: false
107
+ def caches_page(*actions)
108
+ return unless perform_caching
109
+ options = actions.extract_options!
110
+
111
+ gzip_level = options.fetch(:gzip, page_cache_compression)
112
+ gzip_level = case gzip_level
113
+ when Symbol
114
+ Zlib.const_get(gzip_level.upcase)
115
+ when Fixnum
116
+ gzip_level
117
+ when false
118
+ nil
119
+ else
120
+ Zlib::BEST_COMPRESSION
121
+ end
122
+
123
+ after_filter({only: actions}.merge(options)) do |c|
124
+ c.cache_page(nil, nil, gzip_level)
125
+ end
126
+ end
127
+
128
+ private
129
+ def page_cache_file(path, extension)
130
+ name = (path.empty? || path == '/') ? '/index' : URI.parser.unescape(path.chomp('/'))
131
+ unless (name.split('/').last || name).include? '.'
132
+ name << (extension || self.default_static_extension)
133
+ end
134
+ return name
135
+ end
136
+
137
+ def page_cache_path(path, extension = nil)
138
+ page_cache_directory.to_s + page_cache_file(path, extension)
139
+ end
140
+
141
+ def instrument_page_cache(name, path)
142
+ ActiveSupport::Notifications.instrument("#{name}.action_controller", path: path){ yield }
143
+ end
144
+ end
145
+
146
+ # Expires the page that was cached with the +options+ as a key.
147
+ #
148
+ # expire_page controller: 'lists', action: 'show'
149
+ def expire_page(options = {})
150
+ return unless self.class.perform_caching
151
+
152
+ if options.is_a?(Hash)
153
+ if options[:action].is_a?(Array)
154
+ options[:action].each do |action|
155
+ self.class.expire_page(url_for(options.merge(only_path: true, action: action)))
156
+ end
157
+ else
158
+ self.class.expire_page(url_for(options.merge(only_path: true)))
159
+ end
160
+ else
161
+ self.class.expire_page(options)
162
+ end
163
+ end
164
+
165
+ # Manually cache the +content+ in the key determined by +options+. If no content is provided,
166
+ # the contents of response.body is used. If no options are provided, the url of the current
167
+ # request being handled is used.
168
+ #
169
+ # cache_page "I'm the cached content", controller: 'lists', action: 'show'
170
+ def cache_page(content = nil, options = nil, gzip = Zlib::BEST_COMPRESSION)
171
+ return unless self.class.perform_caching && caching_allowed?
172
+
173
+ path = case options
174
+ when Hash
175
+ url_for(options.merge(only_path: true, format: params[:format]))
176
+ when String
177
+ options
178
+ else
179
+ request.path
180
+ end
181
+
182
+ if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present?
183
+ extension = ".#{type_symbol}"
184
+ end
185
+
186
+ self.class.cache_page(content || response.body, path, extension, gzip)
187
+ end
188
+
189
+ def caching_allowed?
190
+ (request.get? || request.head?) && response.status == 200
191
+ end
192
+ end
193
+ end
194
+ end
@@ -0,0 +1,9 @@
1
+ module ActionController
2
+ module Caching
3
+ eager_autoload do
4
+ autoload :Pages
5
+ end
6
+
7
+ include Pages
8
+ end
9
+ end
@@ -0,0 +1 @@
1
+ require 'action_controller/page_caching'
@@ -0,0 +1,22 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+ require 'action_controller'
4
+ require 'action_controller/page_caching'
5
+
6
+ SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
7
+
8
+ module ActionController
9
+ class Base
10
+ include SharedTestRoutes.url_helpers
11
+ end
12
+
13
+ class TestCase
14
+ def setup
15
+ @routes = SharedTestRoutes
16
+
17
+ @routes.draw do
18
+ get ':controller(/:action)'
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,265 @@
1
+ require 'abstract_unit'
2
+
3
+ CACHE_DIR = 'test_cache'
4
+ # Don't change '/../temp/' cavalierly or you might hose something you don't want hosed
5
+ FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
6
+
7
+ class CachingMetalController < ActionController::Metal
8
+ abstract!
9
+
10
+ include ActionController::Caching
11
+
12
+ self.page_cache_directory = FILE_STORE_PATH
13
+ self.cache_store = :file_store, FILE_STORE_PATH
14
+ end
15
+
16
+ class PageCachingMetalTestController < CachingMetalController
17
+ caches_page :ok
18
+
19
+ def ok
20
+ self.response_body = 'ok'
21
+ end
22
+ end
23
+
24
+ class PageCachingMetalTest < ActionController::TestCase
25
+ tests PageCachingMetalTestController
26
+
27
+ def setup
28
+ super
29
+
30
+ FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
31
+ FileUtils.mkdir_p(FILE_STORE_PATH)
32
+ end
33
+
34
+ def teardown
35
+ FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
36
+ end
37
+
38
+ def test_should_cache_get_with_ok_status
39
+ get :ok
40
+ assert_response :ok
41
+ assert File.exist?("#{FILE_STORE_PATH}/page_caching_metal_test/ok.html"), 'get with ok status should have been cached'
42
+ end
43
+ end
44
+
45
+ ActionController::Base.page_cache_directory = FILE_STORE_PATH
46
+
47
+ class CachingController < ActionController::Base
48
+ abstract!
49
+
50
+ self.cache_store = :file_store, FILE_STORE_PATH
51
+ end
52
+
53
+ class PageCachingTestController < CachingController
54
+ self.page_cache_compression = :best_compression
55
+
56
+ caches_page :ok, :no_content, if: Proc.new { |c| !c.request.format.json? }
57
+ caches_page :found, :not_found
58
+ caches_page :about_me
59
+ caches_page :default_gzip
60
+ caches_page :no_gzip, gzip: false
61
+ caches_page :gzip_level, gzip: :best_speed
62
+
63
+ def ok
64
+ head :ok
65
+ end
66
+
67
+ def no_content
68
+ head :no_content
69
+ end
70
+
71
+ def found
72
+ redirect_to action: 'ok'
73
+ end
74
+
75
+ def not_found
76
+ head :not_found
77
+ end
78
+
79
+ def custom_path
80
+ render text: 'Super soaker'
81
+ cache_page('Super soaker', '/index.html')
82
+ end
83
+
84
+ def default_gzip
85
+ render text: 'Text'
86
+ end
87
+
88
+ def no_gzip
89
+ render text: 'PNG'
90
+ end
91
+
92
+ def gzip_level
93
+ render text: 'Big text'
94
+ end
95
+
96
+ def expire_custom_path
97
+ expire_page('/index.html')
98
+ head :ok
99
+ end
100
+
101
+ def trailing_slash
102
+ render text: 'Sneak attack'
103
+ end
104
+
105
+ def about_me
106
+ respond_to do |format|
107
+ format.html { render text: 'I am html' }
108
+ format.xml { render text: 'I am xml' }
109
+ end
110
+ end
111
+ end
112
+
113
+ class PageCachingTest < ActionController::TestCase
114
+ def setup
115
+ super
116
+
117
+ @request = ActionController::TestRequest.new
118
+ @request.host = 'hostname.com'
119
+ @request.env.delete('PATH_INFO')
120
+
121
+ @controller = PageCachingTestController.new
122
+ @controller.perform_caching = true
123
+ @controller.cache_store = :file_store, FILE_STORE_PATH
124
+
125
+ @response = ActionController::TestResponse.new
126
+
127
+ @params = { controller: 'posts', action: 'index', only_path: true }
128
+
129
+ FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
130
+ FileUtils.mkdir_p(FILE_STORE_PATH)
131
+ end
132
+
133
+ def teardown
134
+ FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
135
+ @controller.perform_caching = false
136
+ end
137
+
138
+ def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route
139
+ with_routing do |set|
140
+ set.draw do
141
+ get 'posts.:format', to: 'posts#index', as: :formatted_posts
142
+ get '/', to: 'posts#index', as: :main
143
+ end
144
+ @params[:format] = 'rss'
145
+ assert_equal '/posts.rss', @routes.url_for(@params)
146
+ @params[:format] = nil
147
+ assert_equal '/', @routes.url_for(@params)
148
+ end
149
+ end
150
+
151
+ def test_should_cache_head_with_ok_status
152
+ head :ok
153
+ assert_response :ok
154
+ assert_page_cached :ok, 'head with ok status should have been cached'
155
+ end
156
+
157
+ def test_should_cache_get_with_ok_status
158
+ get :ok
159
+ assert_response :ok
160
+ assert_page_cached :ok, 'get with ok status should have been cached'
161
+ end
162
+
163
+ def test_should_cache_with_custom_path
164
+ get :custom_path
165
+ assert File.exist?("#{FILE_STORE_PATH}/index.html")
166
+ end
167
+
168
+ def test_should_expire_cache_with_custom_path
169
+ get :custom_path
170
+ assert File.exist?("#{FILE_STORE_PATH}/index.html")
171
+
172
+ get :expire_custom_path
173
+ assert !File.exist?("#{FILE_STORE_PATH}/index.html")
174
+ end
175
+
176
+ def test_should_gzip_cache
177
+ get :custom_path
178
+ assert File.exist?("#{FILE_STORE_PATH}/index.html.gz")
179
+
180
+ get :expire_custom_path
181
+ assert !File.exist?("#{FILE_STORE_PATH}/index.html.gz")
182
+ end
183
+
184
+ def test_should_allow_to_disable_gzip
185
+ get :no_gzip
186
+ assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/no_gzip.html")
187
+ assert !File.exist?("#{FILE_STORE_PATH}/page_caching_test/no_gzip.html.gz")
188
+ end
189
+
190
+ def test_should_use_config_gzip_by_default
191
+ @controller.expects(:cache_page).with(nil, nil, Zlib::BEST_COMPRESSION)
192
+ get :default_gzip
193
+ end
194
+
195
+ def test_should_set_gzip_level
196
+ @controller.expects(:cache_page).with(nil, nil, Zlib::BEST_SPEED)
197
+ get :gzip_level
198
+ end
199
+
200
+ def test_should_cache_without_trailing_slash_on_url
201
+ @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash'
202
+ assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
203
+ end
204
+
205
+ def test_should_obey_http_accept_attribute
206
+ @request.env['HTTP_ACCEPT'] = 'text/xml'
207
+ get :about_me
208
+ assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/about_me.xml")
209
+ assert_equal 'I am xml', @response.body
210
+ end
211
+
212
+ def test_cached_page_should_not_have_trailing_slash_even_if_url_has_trailing_slash
213
+ @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash/'
214
+ assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
215
+ end
216
+
217
+ def test_should_cache_ok_at_custom_path
218
+ @request.env['PATH_INFO'] = '/index.html'
219
+ get :ok
220
+ assert_response :ok
221
+ assert File.exist?("#{FILE_STORE_PATH}/index.html")
222
+ end
223
+
224
+ [:ok, :no_content, :found, :not_found].each do |status|
225
+ [:get, :post, :patch, :put, :delete].each do |method|
226
+ unless method == :get && status == :ok
227
+ define_method "test_shouldnt_cache_#{method}_with_#{status}_status" do
228
+ send(method, status)
229
+ assert_response status
230
+ assert_page_not_cached status, "#{method} with #{status} status shouldn't have been cached"
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ def test_page_caching_conditional_options
237
+ get :ok, format: 'json'
238
+ assert_page_not_cached :ok
239
+ end
240
+
241
+ def test_page_caching_directory_set_as_pathname
242
+ begin
243
+ ActionController::Base.page_cache_directory = Pathname.new(FILE_STORE_PATH)
244
+ get :ok
245
+ assert_response :ok
246
+ assert_page_cached :ok
247
+ ensure
248
+ ActionController::Base.page_cache_directory = FILE_STORE_PATH
249
+ end
250
+ end
251
+
252
+ private
253
+
254
+ def assert_page_cached(action, message = "#{action} should have been cached")
255
+ assert page_cached?(action), message
256
+ end
257
+
258
+ def assert_page_not_cached(action, message = "#{action} shouldn't have been cached")
259
+ assert !page_cached?(action), message
260
+ end
261
+
262
+ def page_cached?(action)
263
+ File.exist? "#{FILE_STORE_PATH}/page_caching_test/#{action}.html"
264
+ end
265
+ end
@@ -0,0 +1,54 @@
1
+ require 'abstract_unit'
2
+ require 'active_support/log_subscriber/test_helper'
3
+ require 'action_controller/log_subscriber'
4
+
5
+ module Another
6
+ class LogSubscribersController < ActionController::Base
7
+ abstract!
8
+
9
+ self.perform_caching = true
10
+
11
+ def with_page_cache
12
+ cache_page('Super soaker', '/index.html')
13
+ render nothing: true
14
+ end
15
+ end
16
+ end
17
+
18
+ class ACLogSubscriberTest < ActionController::TestCase
19
+ tests Another::LogSubscribersController
20
+ include ActiveSupport::LogSubscriber::TestHelper
21
+
22
+ def setup
23
+ super
24
+
25
+ @routes = SharedTestRoutes
26
+ @routes.draw do
27
+ get ':controller(/:action)'
28
+ end
29
+
30
+ @cache_path = File.expand_path('../temp/test_cache', File.dirname(__FILE__))
31
+ ActionController::Base.page_cache_directory = @cache_path
32
+ @controller.cache_store = :file_store, @cache_path
33
+ ActionController::LogSubscriber.attach_to :action_controller
34
+ end
35
+
36
+ def teardown
37
+ ActiveSupport::LogSubscriber.log_subscribers.clear
38
+ FileUtils.rm_rf(@cache_path)
39
+ end
40
+
41
+ def set_logger(logger)
42
+ ActionController::Base.logger = logger
43
+ end
44
+
45
+ def test_with_page_cache
46
+ get :with_page_cache
47
+ wait
48
+
49
+ logs = @logger.logged(:info)
50
+ assert_equal 3, logs.size
51
+ assert_match(/Write page/, logs[1])
52
+ assert_match(/\/index\.html/, logs[1])
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: actionpack-page_caching
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Heinemeier Hansson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: actionpack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 4.0.0.beta
22
+ - - <
23
+ - !ruby/object:Gem::Version
24
+ version: '5.0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 4.0.0.beta
33
+ - - <
34
+ - !ruby/object:Gem::Version
35
+ version: '5.0'
36
+ - !ruby/object:Gem::Dependency
37
+ name: mocha
38
+ requirement: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ description: Static page caching for Action Pack (removed from core in Rails 4.0)
53
54
+ executables: []
55
+ extensions: []
56
+ extra_rdoc_files: []
57
+ files:
58
+ - .gitignore
59
+ - .travis.yml
60
+ - Gemfile
61
+ - LICENSE.txt
62
+ - README.md
63
+ - Rakefile
64
+ - actionpack-page_caching.gemspec
65
+ - lib/action_controller/caching/pages.rb
66
+ - lib/action_controller/page_caching.rb
67
+ - lib/actionpack/page_caching.rb
68
+ - test/abstract_unit.rb
69
+ - test/caching_test.rb
70
+ - test/log_subscriber_test.rb
71
+ homepage: https://github.com/rails/actionpack-page_caching
72
+ licenses: []
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ segments:
84
+ - 0
85
+ hash: -3221289291449312417
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ segments:
93
+ - 0
94
+ hash: -3221289291449312417
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 1.8.23
98
+ signing_key:
99
+ specification_version: 3
100
+ summary: Static page caching for Action Pack (removed from core in Rails 4.0)
101
+ test_files:
102
+ - test/abstract_unit.rb
103
+ - test/caching_test.rb
104
+ - test/log_subscriber_test.rb
OSZAR »