actionpack-page_caching 1.0.2 → 1.1.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.
- 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
|