josevalim-easy_http_cache 2.0 → 2.1
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.
- data/README +73 -47
- data/Rakefile +9 -2
- data/lib/easy_http_cache.rb +2 -18
- data/test/easy_http_cache_test.rb +13 -40
- metadata +2 -3
- data/init.rb +0 -1
data/README
CHANGED
@@ -1,21 +1,11 @@
|
|
1
|
-
|
2
|
-
Site: http://www.pagestacker.com/
|
3
|
-
Blog: http://josevalim.blogspot.com/
|
1
|
+
Easy HTTP Cache
|
4
2
|
License: MIT
|
5
|
-
Version: 2.
|
3
|
+
Version: 2.1
|
6
4
|
|
7
5
|
You can also read this README in pretty html at the GitHub project Wiki page
|
8
6
|
|
9
7
|
http://github.com/josevalim/easy_http_cache/wikis/home
|
10
8
|
|
11
|
-
Warning
|
12
|
-
-------
|
13
|
-
|
14
|
-
Since version 2.0, this plugin/gem has drastically changed to fit Rails 2.2
|
15
|
-
http cache goodness. :expires_in, :expires_at and :control options were
|
16
|
-
removed, so if you want to use previous versions, see "Previous versions"
|
17
|
-
below.
|
18
|
-
|
19
9
|
Description
|
20
10
|
-----------
|
21
11
|
|
@@ -23,36 +13,42 @@ Allows Rails applications to do conditional cache easily and in a DRY way
|
|
23
13
|
(without messing up your actions):
|
24
14
|
|
25
15
|
class ListsController < ApplicationController
|
26
|
-
http_cache :index, :show
|
16
|
+
http_cache :index, :show, :last_modified => :list
|
17
|
+
|
18
|
+
protected
|
19
|
+
def list
|
20
|
+
@list ||= List.find(params[:id])
|
21
|
+
end
|
27
22
|
end
|
28
23
|
|
29
24
|
It uses :last_modified and :etag keys, that besides Time, String or resources
|
30
|
-
accepts Proc, Method and
|
31
|
-
|
25
|
+
accepts Proc, Method and Symbol that are evaluated within the current controller.
|
26
|
+
|
27
|
+
Read more about each option (more examples at the end of this page):
|
32
28
|
|
33
29
|
:last_modified
|
34
30
|
Used to manipulate Last-Modified header. You can pass any object that responds
|
35
|
-
to :to_time. If you pass a Proc or Method or
|
36
|
-
within the current controller
|
31
|
+
to :updated_at, :updated_on or :to_time. If you pass a Proc or Method or Symbol,
|
32
|
+
they will be evaluated within the current controller first.
|
37
33
|
|
38
|
-
|
39
|
-
it. If you want to call a different method on your resource, you can pass it as
|
40
|
-
a symbol using the :method option.
|
41
|
-
|
42
|
-
All times will be converted to UTC. Finally, if you pass an array, it will get
|
43
|
-
the most recent time to be used.
|
34
|
+
Finally, if you pass an array, it will get the most recent time to be used.
|
44
35
|
|
45
36
|
:etag
|
46
|
-
Used to manipulate Etag header.
|
47
|
-
|
48
|
-
|
49
|
-
|
37
|
+
Used to manipulate Etag header. The Etag is generated as memcached keys are
|
38
|
+
generated, i.e. calling to_param in the object and then MD5 is applied.
|
39
|
+
|
40
|
+
If you pass a Proc or Method or Symbols, they will be also evaluated within the
|
41
|
+
current controller first.
|
50
42
|
|
51
43
|
:if
|
52
44
|
Only perform http cache if it returns true.
|
53
45
|
|
54
46
|
:unless
|
55
47
|
Only perform http cache if it returns false.
|
48
|
+
|
49
|
+
:method
|
50
|
+
If in :last_modified you want to pass a object that doesn't respond to updated_at,
|
51
|
+
updated_on or to_time, you can specify the method that will be called in this object.
|
56
52
|
|
57
53
|
|
58
54
|
Install
|
@@ -62,9 +58,6 @@ Install Easy HTTP Cache is very easy. It is stored in GitHub, so if you
|
|
62
58
|
have never installed a gem via GitHub run the following:
|
63
59
|
|
64
60
|
gem sources -a http://gems.github.com
|
65
|
-
|
66
|
-
Then install the gem:
|
67
|
-
|
68
61
|
sudo gem install josevalim-easy_http_cache
|
69
62
|
|
70
63
|
In RAILS_ROOT/config/environment.rb:
|
@@ -77,6 +70,7 @@ If you want it as plugin, just do:
|
|
77
70
|
git clone git://github.com/josevalim/easy_http_cache.git
|
78
71
|
rm -rf vendor/plugins/easy_http_cache/.git
|
79
72
|
|
73
|
+
Current version supports Rails 2.2.x and Rails 2.3.x.
|
80
74
|
|
81
75
|
Previous versions
|
82
76
|
-----------------
|
@@ -89,21 +83,21 @@ If you are running on Rails 2.1.x, you should use v1.2.3:
|
|
89
83
|
git checkout v1.2.3
|
90
84
|
rm -rf ./.git
|
91
85
|
|
92
|
-
If you are using
|
86
|
+
If you are using earlier than 2.1, please upgrade your app. =)
|
93
87
|
|
94
88
|
|
95
89
|
Variables
|
96
90
|
---------
|
97
91
|
|
98
|
-
|
99
|
-
the
|
100
|
-
|
92
|
+
As in memcached, you can set ENV['RAILS_CACHE_ID'] or ENV['RAILS_APP_VERSION'] variables
|
93
|
+
to change the Etag that will be generated. This means you can control the cache by setting
|
94
|
+
a timestamp or a version number in ENV['RAILS_APP_VERSION'] everytime you deploy.
|
101
95
|
|
102
96
|
|
103
97
|
Examples
|
104
98
|
--------
|
105
99
|
|
106
|
-
|
100
|
+
The example below will cache your actions and it will never expire:
|
107
101
|
|
108
102
|
class ListsController < ApplicationController
|
109
103
|
http_cache :index, :show
|
@@ -113,10 +107,10 @@ If you do not want to cache when you are showing a flash message (and you
|
|
113
107
|
usually want that), you can simply do:
|
114
108
|
|
115
109
|
class ListsController < ApplicationController
|
116
|
-
http_cache :index, :show, :if => Proc.new { |c| c.
|
110
|
+
http_cache :index, :show, :if => Proc.new { |c| c.send(:flash).empty? }
|
117
111
|
end
|
118
112
|
|
119
|
-
And if you do not want JSON requests:
|
113
|
+
And if you do not want to cache JSON requests:
|
120
114
|
|
121
115
|
class ListsController < ApplicationController
|
122
116
|
http_cache :index, :show, :unless => Proc.new { |c| c.request.format.json? }
|
@@ -128,8 +122,8 @@ Or if you want to expire all http cache before 2008, just do:
|
|
128
122
|
http_cache :index, :show, :last_modified => Time.utc(2008)
|
129
123
|
end
|
130
124
|
|
131
|
-
If
|
132
|
-
it
|
125
|
+
If you want to cache a list and automatically expire the cache when it changes,
|
126
|
+
just do (it will check updated_at and updated_on on the @list object):
|
133
127
|
|
134
128
|
class ListsController < ApplicationController
|
135
129
|
http_cache :index, :show, :last_modified => :list
|
@@ -140,7 +134,8 @@ it changes, just do:
|
|
140
134
|
end
|
141
135
|
end
|
142
136
|
|
143
|
-
You can also set :etag header
|
137
|
+
You can also set :etag header (it will generate an etag calling to_param
|
138
|
+
in the object and applying MD5):
|
144
139
|
|
145
140
|
class ListsController < ApplicationController
|
146
141
|
http_cache :index, :show, :etag => :list
|
@@ -152,23 +147,54 @@ You can also set :etag header:
|
|
152
147
|
end
|
153
148
|
|
154
149
|
If you are using a resource that doesn't respond to updated_at or updated_on,
|
155
|
-
you can pass a method as parameter
|
150
|
+
you can pass a method as parameter that will be called in your resources:
|
156
151
|
|
157
152
|
class ListsController < ApplicationController
|
158
153
|
http_cache :index, :show, :last_modified => :list, :method => :cached_at
|
159
154
|
|
160
155
|
protected
|
161
|
-
|
162
|
-
|
163
|
-
|
156
|
+
def list
|
157
|
+
@list ||= List.find(params[:id])
|
158
|
+
end
|
164
159
|
end
|
165
160
|
|
161
|
+
The sample below will call @list.cached_at to generate Last-Modified header.
|
166
162
|
Finally, you can also pass an array at :last_modified as below:
|
167
163
|
|
168
|
-
class
|
164
|
+
class ItemsController < ApplicationController
|
169
165
|
http_cache :index, :show,
|
170
|
-
:last_modified => [ :list,
|
166
|
+
:last_modified => [ :list, :item ]
|
167
|
+
|
168
|
+
protected
|
169
|
+
def list
|
170
|
+
@list ||= List.find(params[:list_id])
|
171
|
+
end
|
172
|
+
|
173
|
+
def item
|
174
|
+
@item ||= list.items.find(params[:id])
|
175
|
+
end
|
171
176
|
end
|
172
177
|
|
173
178
|
This will check which one is the most recent to compare with the
|
174
|
-
"Last-Modified" field sent by the client.
|
179
|
+
"Last-Modified" field sent by the client.
|
180
|
+
|
181
|
+
|
182
|
+
What if?
|
183
|
+
--------
|
184
|
+
|
185
|
+
At this point (or at some point), you will ask what happens if you use :etag
|
186
|
+
and :last_modified at the same time.
|
187
|
+
|
188
|
+
Well, Padawan, the specification says that if both are sent by the client, both have
|
189
|
+
to be valid for the cache not be considered stale. This subject was already brought
|
190
|
+
to Rails Core group and this is also how Rails' current implementation behaves.
|
191
|
+
|
192
|
+
Bugs and Feedback
|
193
|
+
-----------------
|
194
|
+
|
195
|
+
If you discover any bugs, please send an e-mail to jose.valim@gmail.com
|
196
|
+
If you just want to give some positive feedback or drop a line, that's fine too! =)
|
197
|
+
|
198
|
+
Copyright (c) 2009 José Valim
|
199
|
+
http://www.pagestacker.com/
|
200
|
+
http://josevalim.blogspot.com/
|
data/Rakefile
CHANGED
@@ -2,11 +2,18 @@ require 'rake'
|
|
2
2
|
require 'rake/testtask'
|
3
3
|
require 'rake/rdoctask'
|
4
4
|
|
5
|
-
desc '
|
5
|
+
desc 'Run tests for Easy HTTP Cache.'
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.pattern = 'test/**/*_test.rb'
|
8
|
+
t.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Generate documentation for Easy HTTP Cache.'
|
6
12
|
Rake::RDocTask.new(:rdoc) do |rdoc|
|
7
13
|
rdoc.rdoc_dir = 'rdoc'
|
8
14
|
rdoc.title = 'Easy HTTP Cache'
|
9
15
|
rdoc.options << '--line-numbers' << '--inline-source'
|
10
16
|
rdoc.rdoc_files.include('README')
|
17
|
+
rdoc.rdoc_files.include('MIT-LICENSE')
|
11
18
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
12
|
-
end
|
19
|
+
end
|
data/lib/easy_http_cache.rb
CHANGED
@@ -33,10 +33,6 @@ module ActionController #:nodoc:
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def filter(controller)
|
36
|
-
# We don't go ahead if we are rendering a component
|
37
|
-
#
|
38
|
-
return if component_request?(controller)
|
39
|
-
|
40
36
|
last_modified = get_last_modified(controller)
|
41
37
|
controller.response.last_modified = last_modified if last_modified
|
42
38
|
|
@@ -44,7 +40,7 @@ module ActionController #:nodoc:
|
|
44
40
|
controller.response.etag = processed_etags if processed_etags
|
45
41
|
|
46
42
|
if controller.request.fresh?(controller.response)
|
47
|
-
controller.
|
43
|
+
controller.send(:head, :not_modified)
|
48
44
|
return false
|
49
45
|
end
|
50
46
|
end
|
@@ -53,11 +49,6 @@ module ActionController #:nodoc:
|
|
53
49
|
# If :etag is an array, it processes all Methods, Procs and Symbols
|
54
50
|
# and return them as array. If it's an object, we only evaluate it.
|
55
51
|
#
|
56
|
-
# Finally, if :etag is not sent but RAILS_CACHE_ID or RAILS_APP_VERSION
|
57
|
-
# are set, we return an empty string allowing etag to be performed
|
58
|
-
# because those variables, when modified, are a valid way to expire
|
59
|
-
# all previous caches.
|
60
|
-
#
|
61
52
|
def get_processed_etags(controller)
|
62
53
|
if @options[:etag].is_a?(Array)
|
63
54
|
@options[:etag].collect do |item|
|
@@ -65,8 +56,6 @@ module ActionController #:nodoc:
|
|
65
56
|
end
|
66
57
|
elsif @options[:etag]
|
67
58
|
evaluate_method(@options[:etag], controller)
|
68
|
-
elsif ENV['RAILS_CACHE_ID'] || ENV['RAILS_APP_VERSION']
|
69
|
-
''
|
70
59
|
else
|
71
60
|
nil
|
72
61
|
end
|
@@ -126,15 +115,10 @@ module ActionController #:nodoc:
|
|
126
115
|
end
|
127
116
|
end
|
128
117
|
|
129
|
-
# We should not do http cache when we are using components
|
130
|
-
#
|
131
|
-
def component_request?(controller)
|
132
|
-
controller.instance_variable_get('@parent_controller')
|
133
|
-
end
|
134
118
|
end
|
135
119
|
|
136
120
|
end
|
137
121
|
end
|
138
122
|
end
|
139
123
|
|
140
|
-
ActionController::Base.
|
124
|
+
ActionController::Base.send :include, ActionController::Caching::HttpCache
|
@@ -1,9 +1,16 @@
|
|
1
1
|
# Those lines are plugin test settings
|
2
|
-
|
2
|
+
require 'test/unit'
|
3
|
+
require 'rubygems'
|
3
4
|
require 'ostruct'
|
4
|
-
|
5
|
+
|
6
|
+
ENV["RAILS_ENV"] = "test"
|
7
|
+
|
8
|
+
require 'active_support'
|
9
|
+
require 'action_controller'
|
10
|
+
require 'action_controller/test_case'
|
11
|
+
require 'action_controller/test_process'
|
12
|
+
|
5
13
|
require File.dirname(__FILE__) + '/../lib/easy_http_cache.rb'
|
6
|
-
require 'test_help'
|
7
14
|
|
8
15
|
ActionController::Base.perform_caching = true
|
9
16
|
ActionController::Routing::Routes.draw do |map|
|
@@ -62,7 +69,7 @@ class HttpCacheTestController < ActionController::Base
|
|
62
69
|
end
|
63
70
|
end
|
64
71
|
|
65
|
-
class HttpCacheTest <
|
72
|
+
class HttpCacheTest < ActionController::TestCase
|
66
73
|
def setup
|
67
74
|
reset!
|
68
75
|
end
|
@@ -115,17 +122,7 @@ class HttpCacheTest < Test::Unit::TestCase
|
|
115
122
|
@request.env['HTTP_ACCEPT'] = 'application/json'
|
116
123
|
@request.env['HTTP_IF_MODIFIED_SINCE'] = 1.hour.ago.httpdate
|
117
124
|
get :show
|
118
|
-
assert_equal '200 OK', @response.
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_http_cache_without_input_with_env_variable
|
122
|
-
ENV['RAILS_APP_VERSION'] = '1.2.3'
|
123
|
-
|
124
|
-
get :index
|
125
|
-
assert_headers('200 OK', 'private, max-age=0, must-revalidate', 'Last-Modified', Time.utc(0).httpdate)
|
126
|
-
reset!
|
127
|
-
|
128
|
-
etag_http_cache(:index, '')
|
125
|
+
assert_equal '200 OK', @response.status
|
129
126
|
end
|
130
127
|
|
131
128
|
def test_etag_http_cache
|
@@ -141,22 +138,6 @@ class HttpCacheTest < Test::Unit::TestCase
|
|
141
138
|
etag_http_cache(:etag, 'ETAG_CACHE')
|
142
139
|
end
|
143
140
|
|
144
|
-
def test_should_not_cache_when_rendering_components
|
145
|
-
set_parent_controller!
|
146
|
-
get :show
|
147
|
-
assert_headers('200 OK', 'no-cache')
|
148
|
-
|
149
|
-
set_parent_controller!
|
150
|
-
@request.env['HTTP_IF_MODIFIED_SINCE'] = 1.hour.ago.httpdate
|
151
|
-
get :show
|
152
|
-
assert_headers('200 OK', 'no-cache')
|
153
|
-
|
154
|
-
set_parent_controller!
|
155
|
-
@request.env['HTTP_IF_MODIFIED_SINCE'] = 3.hours.ago.httpdate
|
156
|
-
get :show
|
157
|
-
assert_headers('200 OK', 'no-cache')
|
158
|
-
end
|
159
|
-
|
160
141
|
private
|
161
142
|
def reset!
|
162
143
|
@request = ActionController::TestRequest.new
|
@@ -164,20 +145,12 @@ class HttpCacheTest < Test::Unit::TestCase
|
|
164
145
|
@controller = HttpCacheTestController.new
|
165
146
|
end
|
166
147
|
|
167
|
-
def set_parent_controller!
|
168
|
-
get :index
|
169
|
-
old_controller = @controller.dup
|
170
|
-
reset!
|
171
|
-
|
172
|
-
@controller.instance_variable_set('@parent_controller', old_controller)
|
173
|
-
end
|
174
|
-
|
175
148
|
def etag_for(etag)
|
176
149
|
%("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(etag))}")
|
177
150
|
end
|
178
151
|
|
179
152
|
def assert_headers(status, control, cache_header=nil, value=nil)
|
180
|
-
assert_equal status, @response.
|
153
|
+
assert_equal status, @response.status
|
181
154
|
assert_equal control, @response.headers['Cache-Control']
|
182
155
|
|
183
156
|
if cache_header
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: josevalim-easy_http_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "2.
|
4
|
+
version: "2.1"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Jos\xC3\xA9 Valim"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-02-04 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -25,7 +25,6 @@ files:
|
|
25
25
|
- MIT-LICENSE
|
26
26
|
- README
|
27
27
|
- Rakefile
|
28
|
-
- init.rb
|
29
28
|
- lib/easy_http_cache.rb
|
30
29
|
- test/easy_http_cache_test.rb
|
31
30
|
has_rdoc: true
|
data/init.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'easy_http_cache'
|