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 CHANGED
@@ -1,21 +1,11 @@
1
- Copyright (c) 2008 José Valim (jose.valim at gmail dot com)
2
- Site: http://www.pagestacker.com/
3
- Blog: http://josevalim.blogspot.com/
1
+ Easy HTTP Cache
4
2
  License: MIT
5
- Version: 2.0
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 Symbols that are evaluated within the current controller.
31
- Read more about each option below:
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 Symbols, they will be evaluated
36
- within the current controller and :to_time will be called.
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
- You can also pass resources and :updated_at or :updated_on will be called on
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. If you pass a Proc or Method or Symbols, they
47
- will be evaluated within the current controller.
48
-
49
- You can also pass an array and each element will be also evaluated with needed.
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 a previous version, please updagrade your app. =)
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
- You can set ENV['RAILS_CACHE_ID'] or ENV['RAILS_APP_VERSION'] to change
99
- the ETag that will be generated, expiring all previous caches. Those variables
100
- are also used by other cache stores (memcached, file, ...).
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
- Just as above:
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.__send__(:flash).empty? }
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 You want to cache a list and automatically expire the cache when
132
- it changes, just do:
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 and it will be called in your resources:
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
- def list
162
- @list ||= List.find(params[:id])
163
- end
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 ListsController < ApplicationController
164
+ class ItemsController < ApplicationController
169
165
  http_cache :index, :show,
170
- :last_modified => [ :list, Time.utc(2007,12,27) ]
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 'Generate documentation for Footnotes plugin.'
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
@@ -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.__send__(:head, :not_modified)
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.__send__ :include, ActionController::Caching::HttpCache
124
+ ActionController::Base.send :include, ActionController::Caching::HttpCache
@@ -1,9 +1,16 @@
1
1
  # Those lines are plugin test settings
2
- ENV["RAILS_ENV"] = "test"
2
+ require 'test/unit'
3
+ require 'rubygems'
3
4
  require 'ostruct'
4
- require File.dirname(__FILE__) + '/../../../../config/environment'
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 < Test::Unit::TestCase
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.headers['Status']
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.headers['Status']
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.0"
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: 2008-11-29 00:00:00 -08:00
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'