mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Added controller-level etag additions that will be part of the action etag computation *Jeremy Kemper/DHH*
This commit is contained in:
parent
502d5e24e2
commit
ed5c938fa3
3 changed files with 78 additions and 4 deletions
|
@ -1,5 +1,17 @@
|
|||
## Rails 4.0.0 (unreleased) ##
|
||||
|
||||
* Added controller-level etag additions that will be part of the action etag computation *Jeremy Kemper/DHH*
|
||||
|
||||
class InvoicesController < ApplicationController
|
||||
etag { current_user.try :id }
|
||||
|
||||
def show
|
||||
# Etag will differ even for the same invoice when it's viewed by a different current_user
|
||||
@invoice = Invoice.find(params[:id])
|
||||
fresh_when(@invoice)
|
||||
end
|
||||
end
|
||||
|
||||
* Add automatic template digests to all CacheHelper#cache calls (originally spiked in the cache_digests plugin) *DHH*
|
||||
|
||||
* When building a URL fails, add missing keys provided by Journey. Failed URL
|
||||
|
|
|
@ -5,6 +5,30 @@ module ActionController
|
|||
include RackDelegation
|
||||
include Head
|
||||
|
||||
included { cattr_accessor(:etaggers) { Array.new } }
|
||||
|
||||
module ClassMethods
|
||||
# Allows you to consider additional controller-wide information when generating an etag.
|
||||
# For example, if you serve pages tailored depending on who's logged in at the moment, you
|
||||
# may want to add the current user id to be part of the etag to prevent authorized displaying
|
||||
# of cached pages.
|
||||
#
|
||||
# === Example
|
||||
#
|
||||
# class InvoicesController < ApplicationController
|
||||
# etag { current_user.try :id }
|
||||
#
|
||||
# def show
|
||||
# # Etag will differ even for the same invoice when it's viewed by a different current_user
|
||||
# @invoice = Invoice.find(params[:id])
|
||||
# fresh_when(@invoice)
|
||||
# end
|
||||
# end
|
||||
def etag(&etagger)
|
||||
self.etaggers += [etagger]
|
||||
end
|
||||
end
|
||||
|
||||
# Sets the etag, last_modified, or both on the response and renders a
|
||||
# <tt>304 Not Modified</tt> response if the request is already fresh.
|
||||
#
|
||||
|
@ -42,12 +66,12 @@ module ActionController
|
|||
options.assert_valid_keys(:etag, :last_modified, :public)
|
||||
else
|
||||
record = record_or_options
|
||||
options = { :etag => record, :last_modified => record.try(:updated_at) }.merge(additional_options)
|
||||
options = { etag: record, last_modified: record.try(:updated_at) }.merge(additional_options)
|
||||
end
|
||||
|
||||
response.etag = options[:etag] if options[:etag]
|
||||
response.last_modified = options[:last_modified] if options[:last_modified]
|
||||
response.cache_control[:public] = true if options[:public]
|
||||
response.etag = combine_etags(options[:etag]) if options[:etag]
|
||||
response.last_modified = options[:last_modified] if options[:last_modified]
|
||||
response.cache_control[:public] = true if options[:public]
|
||||
|
||||
head :not_modified if request.fresh?(response)
|
||||
end
|
||||
|
@ -133,5 +157,11 @@ module ActionController
|
|||
def expires_now #:doc:
|
||||
response.cache_control.replace(:no_cache => true)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def combine_etags(etag)
|
||||
[ etag, *etaggers.map { |etagger| instance_exec &etagger }.compact ]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,6 +22,18 @@ module Quiz
|
|||
end
|
||||
end
|
||||
|
||||
class TestControllerWithExtraEtags < ActionController::Base
|
||||
etag { nil }
|
||||
etag { 'ab' }
|
||||
etag { :cde }
|
||||
etag { [:f] }
|
||||
etag { nil }
|
||||
|
||||
def fresh
|
||||
render text: "stale" if stale?(etag: '123')
|
||||
end
|
||||
end
|
||||
|
||||
class TestController < ActionController::Base
|
||||
protect_from_forgery
|
||||
|
||||
|
@ -1626,6 +1638,26 @@ class LastModifiedRenderTest < ActionController::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class EtagRenderTest < ActionController::TestCase
|
||||
tests TestControllerWithExtraEtags
|
||||
|
||||
def setup
|
||||
super
|
||||
@request.host = "www.nextangle.com"
|
||||
end
|
||||
|
||||
def test_multiple_etags
|
||||
@request.if_none_match = %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key([ "123", 'ab', :cde, [:f] ]))}")
|
||||
get :fresh
|
||||
assert_response :not_modified
|
||||
|
||||
@request.if_none_match = %("nomatch")
|
||||
get :fresh
|
||||
assert_response :success
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class MetalRenderTest < ActionController::TestCase
|
||||
tests MetalTestController
|
||||
|
||||
|
|
Loading…
Reference in a new issue