actionpack-page_caching 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack-page_caching might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.codeclimate.yml +7 -0
- data/.gitignore +3 -15
- data/.rubocop.yml +116 -0
- data/.travis.yml +39 -0
- data/CHANGELOG.md +31 -6
- data/Gemfile +2 -2
- data/README.md +62 -17
- data/Rakefile +5 -5
- data/actionpack-page_caching.gemspec +14 -13
- data/gemfiles/Gemfile-4-0-stable +4 -3
- data/gemfiles/Gemfile-4-1-stable +6 -0
- data/gemfiles/Gemfile-4-2-stable +10 -0
- data/gemfiles/Gemfile-5-0-stable +5 -0
- data/gemfiles/Gemfile-edge +4 -3
- data/lib/action_controller/caching/pages.rb +182 -76
- data/lib/action_controller/page_caching.rb +1 -1
- data/lib/actionpack/page_caching.rb +1 -1
- data/lib/actionpack/page_caching/railtie.rb +5 -5
- data/test/abstract_unit.rb +9 -19
- data/test/caching_test.rb +345 -86
- data/test/log_subscriber_test.rb +20 -17
- metadata +23 -17
data/gemfiles/Gemfile-edge
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
|
-
gemspec path:
|
3
|
+
gemspec path: ".."
|
4
4
|
|
5
|
-
gem
|
5
|
+
gem "rails", github: "rails/rails", branch: "master"
|
6
|
+
gem "arel", github: "rails/arel", branch: "master"
|
@@ -1,5 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "fileutils"
|
2
|
+
require "uri"
|
3
|
+
require "active_support/core_ext/class/attribute_accessors"
|
4
|
+
require "active_support/core_ext/string/strip"
|
3
5
|
|
4
6
|
module ActionController
|
5
7
|
module Caching
|
@@ -32,8 +34,8 @@ module ActionController
|
|
32
34
|
# class WeblogController < ActionController::Base
|
33
35
|
# def update
|
34
36
|
# List.update(params[:list][:id], params[:list])
|
35
|
-
# expire_page action:
|
36
|
-
# redirect_to action:
|
37
|
+
# expire_page action: "show", id: params[:list][:id]
|
38
|
+
# redirect_to action: "show", id: params[:list][:id]
|
37
39
|
# end
|
38
40
|
# end
|
39
41
|
#
|
@@ -51,7 +53,7 @@ module ActionController
|
|
51
53
|
# likely require configuring your web server to look in the new location for
|
52
54
|
# cached files.
|
53
55
|
class_attribute :page_cache_directory
|
54
|
-
self.page_cache_directory ||=
|
56
|
+
self.page_cache_directory ||= ""
|
55
57
|
|
56
58
|
# The compression used for gzip. If +false+ (default), the page is not compressed.
|
57
59
|
# If can be a symbol showing the ZLib compression method, for example, <tt>:best_compression</tt>
|
@@ -60,33 +62,137 @@ module ActionController
|
|
60
62
|
self.page_cache_compression ||= false
|
61
63
|
end
|
62
64
|
|
65
|
+
class PageCache #:nodoc:
|
66
|
+
def initialize(cache_directory, default_extension, controller = nil)
|
67
|
+
@cache_directory = cache_directory
|
68
|
+
@default_extension = default_extension
|
69
|
+
@controller = controller
|
70
|
+
end
|
71
|
+
|
72
|
+
def expire(path)
|
73
|
+
instrument :expire_page, path do
|
74
|
+
delete(cache_path(path))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def cache(content, path, extension = nil, gzip = Zlib::BEST_COMPRESSION)
|
79
|
+
instrument :write_page, path do
|
80
|
+
write(content, cache_path(path, extension), gzip)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
def cache_directory
|
86
|
+
case @cache_directory
|
87
|
+
when Proc
|
88
|
+
handle_proc_cache_directory
|
89
|
+
when Symbol
|
90
|
+
handle_symbol_cache_directory
|
91
|
+
else
|
92
|
+
handle_default_cache_directory
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def handle_proc_cache_directory
|
97
|
+
if @controller
|
98
|
+
@controller.instance_exec(&@cache_directory)
|
99
|
+
else
|
100
|
+
raise_runtime_error
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def handle_symbol_cache_directory
|
105
|
+
if @controller
|
106
|
+
@controller.send(@cache_directory)
|
107
|
+
else
|
108
|
+
raise_runtime_error
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def handle_callable_cache_directory
|
113
|
+
if @controller
|
114
|
+
@cache_directory.call(@controller.request)
|
115
|
+
else
|
116
|
+
raise_runtime_error
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def handle_default_cache_directory
|
121
|
+
if @cache_directory.respond_to?(:call)
|
122
|
+
handle_callable_cache_directory
|
123
|
+
else
|
124
|
+
@cache_directory.to_s
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def raise_runtime_error
|
129
|
+
raise RuntimeError, <<-MSG.strip_heredoc
|
130
|
+
Dynamic page_cache_directory used with class-level cache_page method
|
131
|
+
|
132
|
+
You have specified either a Proc, Symbol or callable object for page_cache_directory
|
133
|
+
which needs to be executed within the context of a request. If you need to call the
|
134
|
+
cache_page method from a class-level context then set the page_cache_directory to a
|
135
|
+
static value and override the setting at the instance-level using before_action.
|
136
|
+
MSG
|
137
|
+
end
|
138
|
+
|
139
|
+
def default_extension
|
140
|
+
@default_extension
|
141
|
+
end
|
142
|
+
|
143
|
+
def cache_file(path, extension)
|
144
|
+
if path.empty? || path == "/"
|
145
|
+
name = "/index"
|
146
|
+
else
|
147
|
+
name = URI.parser.unescape(path.chomp("/"))
|
148
|
+
end
|
149
|
+
|
150
|
+
if File.extname(name).empty?
|
151
|
+
name + (extension || default_extension)
|
152
|
+
else
|
153
|
+
name
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def cache_path(path, extension = nil)
|
158
|
+
File.join(cache_directory, cache_file(path, extension))
|
159
|
+
end
|
160
|
+
|
161
|
+
def delete(path)
|
162
|
+
File.delete(path) if File.exist?(path)
|
163
|
+
File.delete(path + ".gz") if File.exist?(path + ".gz")
|
164
|
+
end
|
165
|
+
|
166
|
+
def write(content, path, gzip)
|
167
|
+
FileUtils.makedirs(File.dirname(path))
|
168
|
+
File.open(path, "wb+") { |f| f.write(content) }
|
169
|
+
|
170
|
+
if gzip
|
171
|
+
Zlib::GzipWriter.open(path + ".gz", gzip) { |f| f.write(content) }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def instrument(name, path)
|
176
|
+
ActiveSupport::Notifications.instrument("#{name}.action_controller", path: path) { yield }
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
63
180
|
module ClassMethods
|
64
181
|
# Expires the page that was cached with the +path+ as a key.
|
65
182
|
#
|
66
|
-
# expire_page
|
183
|
+
# expire_page "/lists/show"
|
67
184
|
def expire_page(path)
|
68
|
-
|
69
|
-
|
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')
|
185
|
+
if perform_caching
|
186
|
+
page_cache.expire(path)
|
74
187
|
end
|
75
188
|
end
|
76
189
|
|
77
190
|
# Manually cache the +content+ in the key determined by +path+.
|
78
191
|
#
|
79
|
-
# cache_page "I'm the cached content",
|
192
|
+
# cache_page "I'm the cached content", "/lists/show"
|
80
193
|
def cache_page(content, path, extension = nil, gzip = Zlib::BEST_COMPRESSION)
|
81
|
-
|
82
|
-
|
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
|
194
|
+
if perform_caching
|
195
|
+
page_cache.cache(content, path, extension, gzip)
|
90
196
|
end
|
91
197
|
end
|
92
198
|
|
@@ -105,60 +211,50 @@ module ActionController
|
|
105
211
|
# # don't gzip images
|
106
212
|
# caches_page :image, gzip: false
|
107
213
|
def caches_page(*actions)
|
108
|
-
|
109
|
-
|
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
|
214
|
+
if perform_caching
|
215
|
+
options = actions.extract_options!
|
122
216
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
217
|
+
gzip_level = options.fetch(:gzip, page_cache_compression)
|
218
|
+
gzip_level = \
|
219
|
+
case gzip_level
|
220
|
+
when Symbol
|
221
|
+
Zlib.const_get(gzip_level.upcase)
|
222
|
+
when Integer
|
223
|
+
gzip_level
|
224
|
+
when false
|
225
|
+
nil
|
226
|
+
else
|
227
|
+
Zlib::BEST_COMPRESSION
|
228
|
+
end
|
127
229
|
|
128
|
-
|
129
|
-
|
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)
|
230
|
+
after_action({ only: actions }.merge(options)) do |c|
|
231
|
+
c.cache_page(nil, nil, gzip_level)
|
133
232
|
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
233
|
end
|
234
|
+
end
|
140
235
|
|
141
|
-
|
142
|
-
|
236
|
+
private
|
237
|
+
def page_cache
|
238
|
+
PageCache.new(page_cache_directory, default_static_extension)
|
143
239
|
end
|
144
240
|
end
|
145
241
|
|
146
242
|
# Expires the page that was cached with the +options+ as a key.
|
147
243
|
#
|
148
|
-
# expire_page controller:
|
244
|
+
# expire_page controller: "lists", action: "show"
|
149
245
|
def expire_page(options = {})
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
246
|
+
if perform_caching?
|
247
|
+
case options
|
248
|
+
when Hash
|
249
|
+
case options[:action]
|
250
|
+
when Array
|
251
|
+
options[:action].each { |action| expire_page(options.merge(action: action)) }
|
252
|
+
else
|
253
|
+
page_cache.expire(url_for(options.merge(only_path: true)))
|
156
254
|
end
|
157
255
|
else
|
158
|
-
|
256
|
+
page_cache.expire(options)
|
159
257
|
end
|
160
|
-
else
|
161
|
-
self.class.expire_page(options)
|
162
258
|
end
|
163
259
|
end
|
164
260
|
|
@@ -166,29 +262,39 @@ module ActionController
|
|
166
262
|
# the contents of response.body is used. If no options are provided, the url of the current
|
167
263
|
# request being handled is used.
|
168
264
|
#
|
169
|
-
# cache_page "I'm the cached content", controller:
|
265
|
+
# cache_page "I'm the cached content", controller: "lists", action: "show"
|
170
266
|
def cache_page(content = nil, options = nil, gzip = Zlib::BEST_COMPRESSION)
|
171
|
-
|
267
|
+
if perform_caching? && caching_allowed?
|
268
|
+
path = \
|
269
|
+
case options
|
270
|
+
when Hash
|
271
|
+
url_for(options.merge(only_path: true, format: params[:format]))
|
272
|
+
when String
|
273
|
+
options
|
274
|
+
else
|
275
|
+
request.path
|
276
|
+
end
|
172
277
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
when String
|
177
|
-
options
|
178
|
-
else
|
179
|
-
request.path
|
180
|
-
end
|
278
|
+
if (type = Mime::LOOKUP[self.content_type]) && (type_symbol = type.symbol).present?
|
279
|
+
extension = ".#{type_symbol}"
|
280
|
+
end
|
181
281
|
|
182
|
-
|
183
|
-
extension = ".#{type_symbol}"
|
282
|
+
page_cache.cache(content || response.body, path, extension, gzip)
|
184
283
|
end
|
185
|
-
|
186
|
-
self.class.cache_page(content || response.body, path, extension, gzip)
|
187
284
|
end
|
188
285
|
|
189
286
|
def caching_allowed?
|
190
287
|
(request.get? || request.head?) && response.status == 200
|
191
288
|
end
|
289
|
+
|
290
|
+
def perform_caching?
|
291
|
+
self.class.perform_caching
|
292
|
+
end
|
293
|
+
|
294
|
+
private
|
295
|
+
def page_cache
|
296
|
+
PageCache.new(page_cache_directory, default_static_extension, self)
|
297
|
+
end
|
192
298
|
end
|
193
299
|
end
|
194
300
|
end
|
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require "actionpack/page_caching/railtie"
|
@@ -1,16 +1,16 @@
|
|
1
|
-
require
|
1
|
+
require "rails/railtie"
|
2
2
|
|
3
3
|
module ActionPack
|
4
4
|
module PageCaching
|
5
5
|
class Railtie < Rails::Railtie
|
6
|
-
initializer
|
6
|
+
initializer "action_pack.page_caching" do
|
7
7
|
ActiveSupport.on_load(:action_controller) do
|
8
|
-
require
|
8
|
+
require "action_controller/page_caching"
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
initializer
|
13
|
-
app.config.action_controller.page_cache_directory ||= app.config.paths[
|
12
|
+
initializer "action_pack.page_caching.set_config", before: "action_controller.set_configs" do |app|
|
13
|
+
app.config.action_controller.page_cache_directory ||= app.config.paths["public"].first
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
data/test/abstract_unit.rb
CHANGED
@@ -1,22 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "bundler/setup"
|
2
|
+
require "minitest/autorun"
|
3
|
+
require "action_controller"
|
4
|
+
require "action_controller/page_caching"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class Base
|
10
|
-
include SharedTestRoutes.url_helpers
|
11
|
-
end
|
12
|
-
|
13
|
-
class TestCase
|
14
|
-
def setup
|
15
|
-
@routes = SharedTestRoutes
|
6
|
+
if ActiveSupport.respond_to?(:test_order)
|
7
|
+
ActiveSupport.test_order = :random
|
8
|
+
end
|
16
9
|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
10
|
+
if ActionController::Base.respond_to?(:enable_fragment_cache_logging=)
|
11
|
+
ActionController::Base.enable_fragment_cache_logging = true
|
22
12
|
end
|
data/test/caching_test.rb
CHANGED
@@ -1,12 +1,69 @@
|
|
1
|
-
require
|
1
|
+
require "abstract_unit"
|
2
|
+
require "mocha/setup"
|
2
3
|
|
3
|
-
CACHE_DIR =
|
4
|
-
# Don't change
|
5
|
-
|
4
|
+
CACHE_DIR = "test_cache"
|
5
|
+
# Don't change "../tmp" cavalierly or you might hose something you don't want hosed
|
6
|
+
TEST_TMP_DIR = File.expand_path("../tmp", __FILE__)
|
7
|
+
FILE_STORE_PATH = File.join(TEST_TMP_DIR, CACHE_DIR)
|
8
|
+
|
9
|
+
module PageCachingTestHelpers
|
10
|
+
def setup
|
11
|
+
super
|
12
|
+
|
13
|
+
@routes = ActionDispatch::Routing::RouteSet.new
|
14
|
+
|
15
|
+
FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
|
16
|
+
FileUtils.mkdir_p(FILE_STORE_PATH)
|
17
|
+
end
|
18
|
+
|
19
|
+
def teardown
|
20
|
+
super
|
21
|
+
|
22
|
+
FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
|
23
|
+
@controller.perform_caching = false
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def assert_page_cached(action, options = {})
|
29
|
+
expected = options[:content] || action.to_s
|
30
|
+
path = cache_file(action, options)
|
31
|
+
|
32
|
+
assert File.exist?(path), "The cache file #{path} doesn't exist"
|
33
|
+
|
34
|
+
if File.extname(path) == ".gz"
|
35
|
+
actual = Zlib::GzipReader.open(path) { |f| f.read }
|
36
|
+
else
|
37
|
+
actual = File.read(path)
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_equal expected, actual, "The cached content doesn't match the expected value"
|
41
|
+
end
|
42
|
+
|
43
|
+
def assert_page_not_cached(action, options = {})
|
44
|
+
path = cache_file(action, options)
|
45
|
+
assert !File.exist?(path), "The cache file #{path} still exists"
|
46
|
+
end
|
47
|
+
|
48
|
+
def cache_file(action, options = {})
|
49
|
+
path = options[:path] || FILE_STORE_PATH
|
50
|
+
controller = options[:controller] || self.class.name.underscore
|
51
|
+
format = options[:format] || "html"
|
52
|
+
|
53
|
+
"#{path}/#{controller}/#{action}.#{format}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def draw(&block)
|
57
|
+
@routes = ActionDispatch::Routing::RouteSet.new
|
58
|
+
@routes.draw(&block)
|
59
|
+
@controller.extend(@routes.url_helpers)
|
60
|
+
end
|
61
|
+
end
|
6
62
|
|
7
63
|
class CachingMetalController < ActionController::Metal
|
8
64
|
abstract!
|
9
65
|
|
66
|
+
include AbstractController::Callbacks
|
10
67
|
include ActionController::Caching
|
11
68
|
|
12
69
|
self.page_cache_directory = FILE_STORE_PATH
|
@@ -17,28 +74,22 @@ class PageCachingMetalTestController < CachingMetalController
|
|
17
74
|
caches_page :ok
|
18
75
|
|
19
76
|
def ok
|
20
|
-
self.response_body =
|
77
|
+
self.response_body = "ok"
|
21
78
|
end
|
22
79
|
end
|
23
80
|
|
24
81
|
class PageCachingMetalTest < ActionController::TestCase
|
82
|
+
include PageCachingTestHelpers
|
25
83
|
tests PageCachingMetalTestController
|
26
84
|
|
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
85
|
def test_should_cache_get_with_ok_status
|
86
|
+
draw do
|
87
|
+
get "/page_caching_metal_test/ok", to: "page_caching_metal_test#ok"
|
88
|
+
end
|
89
|
+
|
39
90
|
get :ok
|
40
91
|
assert_response :ok
|
41
|
-
|
92
|
+
assert_page_cached :ok
|
42
93
|
end
|
43
94
|
end
|
44
95
|
|
@@ -48,6 +99,17 @@ class CachingController < ActionController::Base
|
|
48
99
|
abstract!
|
49
100
|
|
50
101
|
self.cache_store = :file_store, FILE_STORE_PATH
|
102
|
+
|
103
|
+
protected
|
104
|
+
if ActionPack::VERSION::STRING < "4.1"
|
105
|
+
def render(options)
|
106
|
+
if options.key?(:html)
|
107
|
+
super({ text: options.delete(:html) }.merge(options))
|
108
|
+
else
|
109
|
+
super
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
51
113
|
end
|
52
114
|
|
53
115
|
class PageCachingTestController < CachingController
|
@@ -61,7 +123,7 @@ class PageCachingTestController < CachingController
|
|
61
123
|
caches_page :gzip_level, gzip: :best_speed
|
62
124
|
|
63
125
|
def ok
|
64
|
-
|
126
|
+
render html: "ok"
|
65
127
|
end
|
66
128
|
|
67
129
|
def no_content
|
@@ -69,7 +131,7 @@ class PageCachingTestController < CachingController
|
|
69
131
|
end
|
70
132
|
|
71
133
|
def found
|
72
|
-
redirect_to action:
|
134
|
+
redirect_to action: "ok"
|
73
135
|
end
|
74
136
|
|
75
137
|
def not_found
|
@@ -77,170 +139,204 @@ class PageCachingTestController < CachingController
|
|
77
139
|
end
|
78
140
|
|
79
141
|
def custom_path
|
80
|
-
render
|
81
|
-
cache_page(
|
142
|
+
render html: "custom_path"
|
143
|
+
cache_page(nil, "/index.html")
|
82
144
|
end
|
83
145
|
|
84
146
|
def default_gzip
|
85
|
-
render
|
147
|
+
render html: "default_gzip"
|
86
148
|
end
|
87
149
|
|
88
150
|
def no_gzip
|
89
|
-
render
|
151
|
+
render html: "no_gzip"
|
90
152
|
end
|
91
153
|
|
92
154
|
def gzip_level
|
93
|
-
render
|
155
|
+
render html: "gzip_level"
|
94
156
|
end
|
95
157
|
|
96
158
|
def expire_custom_path
|
97
|
-
expire_page(
|
159
|
+
expire_page("/index.html")
|
98
160
|
head :ok
|
99
161
|
end
|
100
162
|
|
101
163
|
def trailing_slash
|
102
|
-
render
|
164
|
+
render html: "trailing_slash"
|
103
165
|
end
|
104
166
|
|
105
167
|
def about_me
|
106
168
|
respond_to do |format|
|
107
|
-
format.html { render
|
108
|
-
format.xml { render
|
169
|
+
format.html { render html: "I am html" }
|
170
|
+
format.xml { render xml: "I am xml" }
|
109
171
|
end
|
110
172
|
end
|
111
173
|
end
|
112
174
|
|
113
175
|
class PageCachingTest < ActionController::TestCase
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
@request = ActionController::TestRequest.new
|
118
|
-
@request.host = 'hostname.com'
|
119
|
-
@request.env.delete('PATH_INFO')
|
176
|
+
include PageCachingTestHelpers
|
177
|
+
tests PageCachingTestController
|
120
178
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
179
|
+
def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route
|
180
|
+
draw do
|
181
|
+
get "posts.:format", to: "posts#index", as: :formatted_posts
|
182
|
+
get "/", to: "posts#index", as: :main
|
183
|
+
end
|
126
184
|
|
127
|
-
|
185
|
+
defaults = { controller: "posts", action: "index", only_path: true }
|
128
186
|
|
129
|
-
|
130
|
-
|
187
|
+
assert_equal "/posts.rss", @routes.url_for(defaults.merge(format: "rss"))
|
188
|
+
assert_equal "/", @routes.url_for(defaults.merge(format: nil))
|
131
189
|
end
|
132
190
|
|
133
|
-
def
|
134
|
-
|
135
|
-
|
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)
|
191
|
+
def test_should_cache_head_with_ok_status
|
192
|
+
draw do
|
193
|
+
get "/page_caching_test/ok", to: "page_caching_test#ok"
|
148
194
|
end
|
149
|
-
end
|
150
195
|
|
151
|
-
def test_should_cache_head_with_ok_status
|
152
196
|
head :ok
|
153
197
|
assert_response :ok
|
154
|
-
assert_page_cached :ok
|
198
|
+
assert_page_cached :ok
|
155
199
|
end
|
156
200
|
|
157
201
|
def test_should_cache_get_with_ok_status
|
202
|
+
draw do
|
203
|
+
get "/page_caching_test/ok", to: "page_caching_test#ok"
|
204
|
+
end
|
205
|
+
|
158
206
|
get :ok
|
159
207
|
assert_response :ok
|
160
|
-
assert_page_cached :ok
|
208
|
+
assert_page_cached :ok
|
161
209
|
end
|
162
210
|
|
163
211
|
def test_should_cache_with_custom_path
|
212
|
+
draw do
|
213
|
+
get "/page_caching_test/custom_path", to: "page_caching_test#custom_path"
|
214
|
+
end
|
215
|
+
|
164
216
|
get :custom_path
|
165
|
-
|
217
|
+
assert_page_cached :index, controller: ".", content: "custom_path"
|
166
218
|
end
|
167
219
|
|
168
220
|
def test_should_expire_cache_with_custom_path
|
221
|
+
draw do
|
222
|
+
get "/page_caching_test/custom_path", to: "page_caching_test#custom_path"
|
223
|
+
get "/page_caching_test/expire_custom_path", to: "page_caching_test#expire_custom_path"
|
224
|
+
end
|
225
|
+
|
169
226
|
get :custom_path
|
170
|
-
|
227
|
+
assert_page_cached :index, controller: ".", content: "custom_path"
|
171
228
|
|
172
229
|
get :expire_custom_path
|
173
|
-
|
230
|
+
assert_page_not_cached :index, controller: ".", content: "custom_path"
|
174
231
|
end
|
175
232
|
|
176
233
|
def test_should_gzip_cache
|
234
|
+
draw do
|
235
|
+
get "/page_caching_test/custom_path", to: "page_caching_test#custom_path"
|
236
|
+
get "/page_caching_test/expire_custom_path", to: "page_caching_test#expire_custom_path"
|
237
|
+
end
|
238
|
+
|
177
239
|
get :custom_path
|
178
|
-
|
240
|
+
assert_page_cached :index, controller: ".", format: "html.gz", content: "custom_path"
|
179
241
|
|
180
242
|
get :expire_custom_path
|
181
|
-
|
243
|
+
assert_page_not_cached :index, controller: ".", format: "html.gz"
|
182
244
|
end
|
183
245
|
|
184
246
|
def test_should_allow_to_disable_gzip
|
247
|
+
draw do
|
248
|
+
get "/page_caching_test/no_gzip", to: "page_caching_test#no_gzip"
|
249
|
+
end
|
250
|
+
|
185
251
|
get :no_gzip
|
186
|
-
|
187
|
-
|
252
|
+
assert_page_cached :no_gzip, format: "html"
|
253
|
+
assert_page_not_cached :no_gzip, format: "html.gz"
|
188
254
|
end
|
189
255
|
|
190
256
|
def test_should_use_config_gzip_by_default
|
257
|
+
draw do
|
258
|
+
get "/page_caching_test/default_gzip", to: "page_caching_test#default_gzip"
|
259
|
+
end
|
260
|
+
|
191
261
|
@controller.expects(:cache_page).with(nil, nil, Zlib::BEST_COMPRESSION)
|
192
262
|
get :default_gzip
|
193
263
|
end
|
194
264
|
|
195
265
|
def test_should_set_gzip_level
|
266
|
+
draw do
|
267
|
+
get "/page_caching_test/gzip_level", to: "page_caching_test#gzip_level"
|
268
|
+
end
|
269
|
+
|
196
270
|
@controller.expects(:cache_page).with(nil, nil, Zlib::BEST_SPEED)
|
197
271
|
get :gzip_level
|
198
272
|
end
|
199
273
|
|
200
274
|
def test_should_cache_without_trailing_slash_on_url
|
201
|
-
@controller.class.cache_page
|
202
|
-
|
275
|
+
@controller.class.cache_page "cached content", "/page_caching_test/trailing_slash"
|
276
|
+
assert_page_cached :trailing_slash, content: "cached content"
|
203
277
|
end
|
204
278
|
|
205
279
|
def test_should_obey_http_accept_attribute
|
206
|
-
|
280
|
+
draw do
|
281
|
+
get "/page_caching_test/about_me", to: "page_caching_test#about_me"
|
282
|
+
end
|
283
|
+
|
284
|
+
@request.env["HTTP_ACCEPT"] = "text/xml"
|
207
285
|
get :about_me
|
208
|
-
|
209
|
-
|
286
|
+
assert_equal "I am xml", @response.body
|
287
|
+
assert_page_cached :about_me, format: "xml", content: "I am xml"
|
210
288
|
end
|
211
289
|
|
212
290
|
def test_cached_page_should_not_have_trailing_slash_even_if_url_has_trailing_slash
|
213
|
-
@controller.class.cache_page
|
214
|
-
|
291
|
+
@controller.class.cache_page "cached content", "/page_caching_test/trailing_slash/"
|
292
|
+
assert_page_cached :trailing_slash, content: "cached content"
|
215
293
|
end
|
216
294
|
|
217
295
|
def test_should_cache_ok_at_custom_path
|
218
|
-
|
296
|
+
draw do
|
297
|
+
get "/page_caching_test/ok", to: "page_caching_test#ok"
|
298
|
+
end
|
299
|
+
|
300
|
+
@request.env["PATH_INFO"] = "/index.html"
|
219
301
|
get :ok
|
220
302
|
assert_response :ok
|
221
|
-
|
303
|
+
assert_page_cached :index, controller: ".", content: "ok"
|
222
304
|
end
|
223
305
|
|
224
306
|
[:ok, :no_content, :found, :not_found].each do |status|
|
225
307
|
[:get, :post, :patch, :put, :delete].each do |method|
|
226
308
|
unless method == :get && status == :ok
|
227
309
|
define_method "test_shouldnt_cache_#{method}_with_#{status}_status" do
|
310
|
+
draw do
|
311
|
+
get "/page_caching_test/ok", to: "page_caching_test#ok"
|
312
|
+
match "/page_caching_test/#{status}", to: "page_caching_test##{status}", via: method
|
313
|
+
end
|
314
|
+
|
228
315
|
send(method, status)
|
229
316
|
assert_response status
|
230
|
-
assert_page_not_cached status
|
317
|
+
assert_page_not_cached status
|
231
318
|
end
|
232
319
|
end
|
233
320
|
end
|
234
321
|
end
|
235
322
|
|
236
323
|
def test_page_caching_conditional_options
|
237
|
-
|
324
|
+
draw do
|
325
|
+
get "/page_caching_test/ok", to: "page_caching_test#ok"
|
326
|
+
end
|
327
|
+
|
328
|
+
get :ok, format: "json"
|
238
329
|
assert_page_not_cached :ok
|
239
330
|
end
|
240
331
|
|
241
332
|
def test_page_caching_directory_set_as_pathname
|
242
333
|
begin
|
243
334
|
ActionController::Base.page_cache_directory = Pathname.new(FILE_STORE_PATH)
|
335
|
+
|
336
|
+
draw do
|
337
|
+
get "/page_caching_test/ok", to: "page_caching_test#ok"
|
338
|
+
end
|
339
|
+
|
244
340
|
get :ok
|
245
341
|
assert_response :ok
|
246
342
|
assert_page_cached :ok
|
@@ -249,17 +345,180 @@ class PageCachingTest < ActionController::TestCase
|
|
249
345
|
end
|
250
346
|
end
|
251
347
|
|
252
|
-
|
348
|
+
def test_page_caching_directory_set_on_controller_instance
|
349
|
+
draw do
|
350
|
+
get "/page_caching_test/ok", to: "page_caching_test#ok"
|
351
|
+
end
|
352
|
+
|
353
|
+
file_store_path = File.join(TEST_TMP_DIR, "instance_cache")
|
354
|
+
@controller.page_cache_directory = file_store_path
|
355
|
+
|
356
|
+
get :ok
|
357
|
+
assert_response :ok
|
358
|
+
assert_page_cached :ok, path: file_store_path
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
class ProcPageCachingTestController < CachingController
|
363
|
+
self.page_cache_directory = -> { File.join(TEST_TMP_DIR, request.domain) }
|
364
|
+
|
365
|
+
caches_page :ok
|
366
|
+
|
367
|
+
def ok
|
368
|
+
render html: "ok"
|
369
|
+
end
|
370
|
+
|
371
|
+
def expire_ok
|
372
|
+
expire_page action: :ok
|
373
|
+
head :ok
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
class ProcPageCachingTest < ActionController::TestCase
|
378
|
+
include PageCachingTestHelpers
|
379
|
+
tests ProcPageCachingTestController
|
380
|
+
|
381
|
+
def test_page_is_cached_by_domain
|
382
|
+
draw do
|
383
|
+
get "/proc_page_caching_test/ok", to: "proc_page_caching_test#ok"
|
384
|
+
get "/proc_page_caching_test/ok/expire", to: "proc_page_caching_test#expire_ok"
|
385
|
+
end
|
386
|
+
|
387
|
+
@request.env["HTTP_HOST"] = "www.foo.com"
|
388
|
+
get :ok
|
389
|
+
assert_response :ok
|
390
|
+
assert_page_cached :ok, path: TEST_TMP_DIR + "/foo.com"
|
391
|
+
|
392
|
+
get :expire_ok
|
393
|
+
assert_response :ok
|
394
|
+
assert_page_not_cached :ok, path: TEST_TMP_DIR + "/foo.com"
|
395
|
+
|
396
|
+
@request.env["HTTP_HOST"] = "www.bar.com"
|
397
|
+
get :ok
|
398
|
+
assert_response :ok
|
399
|
+
assert_page_cached :ok, path: TEST_TMP_DIR + "/bar.com"
|
400
|
+
|
401
|
+
get :expire_ok
|
402
|
+
assert_response :ok
|
403
|
+
assert_page_not_cached :ok, path: TEST_TMP_DIR + "/bar.com"
|
404
|
+
end
|
405
|
+
|
406
|
+
def test_class_level_cache_page_raise_error
|
407
|
+
assert_raises(RuntimeError, /class-level cache_page method/) do
|
408
|
+
@controller.class.cache_page "cached content", "/proc_page_caching_test/ok"
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
class SymbolPageCachingTestController < CachingController
|
414
|
+
self.page_cache_directory = :domain_cache_directory
|
415
|
+
|
416
|
+
caches_page :ok
|
417
|
+
|
418
|
+
def ok
|
419
|
+
render html: "ok"
|
420
|
+
end
|
421
|
+
|
422
|
+
def expire_ok
|
423
|
+
expire_page action: :ok
|
424
|
+
head :ok
|
425
|
+
end
|
253
426
|
|
254
|
-
|
255
|
-
|
427
|
+
protected
|
428
|
+
def domain_cache_directory
|
429
|
+
File.join(TEST_TMP_DIR, request.domain)
|
256
430
|
end
|
431
|
+
end
|
432
|
+
|
433
|
+
class SymbolPageCachingTest < ActionController::TestCase
|
434
|
+
include PageCachingTestHelpers
|
435
|
+
tests SymbolPageCachingTestController
|
257
436
|
|
258
|
-
|
259
|
-
|
437
|
+
def test_page_is_cached_by_domain
|
438
|
+
draw do
|
439
|
+
get "/symbol_page_caching_test/ok", to: "symbol_page_caching_test#ok"
|
440
|
+
get "/symbol_page_caching_test/ok/expire", to: "symbol_page_caching_test#expire_ok"
|
260
441
|
end
|
261
442
|
|
262
|
-
|
263
|
-
|
443
|
+
@request.env["HTTP_HOST"] = "www.foo.com"
|
444
|
+
get :ok
|
445
|
+
assert_response :ok
|
446
|
+
assert_page_cached :ok, path: TEST_TMP_DIR + "/foo.com"
|
447
|
+
|
448
|
+
get :expire_ok
|
449
|
+
assert_response :ok
|
450
|
+
assert_page_not_cached :ok, path: TEST_TMP_DIR + "/foo.com"
|
451
|
+
|
452
|
+
@request.env["HTTP_HOST"] = "www.bar.com"
|
453
|
+
get :ok
|
454
|
+
assert_response :ok
|
455
|
+
assert_page_cached :ok, path: TEST_TMP_DIR + "/bar.com"
|
456
|
+
|
457
|
+
get :expire_ok
|
458
|
+
assert_response :ok
|
459
|
+
assert_page_not_cached :ok, path: TEST_TMP_DIR + "/bar.com"
|
460
|
+
end
|
461
|
+
|
462
|
+
def test_class_level_cache_page_raise_error
|
463
|
+
assert_raises(RuntimeError, /class-level cache_page method/) do
|
464
|
+
@controller.class.cache_page "cached content", "/symbol_page_caching_test/ok"
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
class CallablePageCachingTestController < CachingController
|
470
|
+
class DomainCacheDirectory
|
471
|
+
def self.call(request)
|
472
|
+
File.join(TEST_TMP_DIR, request.domain)
|
264
473
|
end
|
474
|
+
end
|
475
|
+
|
476
|
+
self.page_cache_directory = DomainCacheDirectory
|
477
|
+
|
478
|
+
caches_page :ok
|
479
|
+
|
480
|
+
def ok
|
481
|
+
render html: "ok"
|
482
|
+
end
|
483
|
+
|
484
|
+
def expire_ok
|
485
|
+
expire_page action: :ok
|
486
|
+
head :ok
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
class CallablePageCachingTest < ActionController::TestCase
|
491
|
+
include PageCachingTestHelpers
|
492
|
+
tests CallablePageCachingTestController
|
493
|
+
|
494
|
+
def test_page_is_cached_by_domain
|
495
|
+
draw do
|
496
|
+
get "/callable_page_caching_test/ok", to: "callable_page_caching_test#ok"
|
497
|
+
get "/callable_page_caching_test/ok/expire", to: "callable_page_caching_test#expire_ok"
|
498
|
+
end
|
499
|
+
|
500
|
+
@request.env["HTTP_HOST"] = "www.foo.com"
|
501
|
+
get :ok
|
502
|
+
assert_response :ok
|
503
|
+
assert_page_cached :ok, path: TEST_TMP_DIR + "/foo.com"
|
504
|
+
|
505
|
+
get :expire_ok
|
506
|
+
assert_response :ok
|
507
|
+
assert_page_not_cached :ok, path: TEST_TMP_DIR + "/foo.com"
|
508
|
+
|
509
|
+
@request.env["HTTP_HOST"] = "www.bar.com"
|
510
|
+
get :ok
|
511
|
+
assert_response :ok
|
512
|
+
assert_page_cached :ok, path: TEST_TMP_DIR + "/bar.com"
|
513
|
+
|
514
|
+
get :expire_ok
|
515
|
+
assert_response :ok
|
516
|
+
assert_page_not_cached :ok, path: TEST_TMP_DIR + "/bar.com"
|
517
|
+
end
|
518
|
+
|
519
|
+
def test_class_level_cache_page_raise_error
|
520
|
+
assert_raises(RuntimeError, /class-level cache_page method/) do
|
521
|
+
@controller.class.cache_page "cached content", "/callable_page_caching_test/ok"
|
522
|
+
end
|
523
|
+
end
|
265
524
|
end
|