Method: ActionController::ConditionalGet#fresh_when
- Defined in:
- actionpack/lib/action_controller/metal/conditional_get.rb
#fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil) ⇒ Object
Sets the etag, last_modified, or both on the response, and renders a 304 Not Modified response if the request is already fresh.
Options
:etag
: Sets a "weak" ETag validator on the response. See the :weak_etag option.
:weak_etag
: Sets a "weak" ETag validator on the response. Requests that specify an
If-None-Match header may receive a 304 Not Modified response if the
ETag matches exactly.
: A weak ETag indicates semantic equivalence, not byte-for-byte equality, so
they're good for caching HTML pages in browser caches. They can't be used
for responses that must be byte-identical, like serving Range requests
within a PDF file.
:strong_etag
: Sets a "strong" ETag validator on the response. Requests that specify an
If-None-Match header may receive a 304 Not Modified response if the
ETag matches exactly.
: A strong ETag implies exact equality -- the response must match byte for
byte. This is necessary for serving Range requests within a large video
or PDF file, for example, or for compatibility with some CDNs that don't
support weak ETags.
:last_modified
: Sets a "weak" last-update validator on the response. Subsequent requests
that specify an If-Modified-Since header may receive a 304 Not Modified response if last_modified <= If-Modified-Since.
:public
: By default the Cache-Control header is private. Set this option to
true if you want your application to be cacheable by other devices, such
as proxy caches.
:cache_control
: When given, will overwrite an existing Cache-Control header. For a list
of Cache-Control directives, see the article on
MDN.
:template
: By default, the template digest for the current controller/action is
included in ETags. If the action renders a different template, you can
include its digest instead. If the action doesn't render a template at
all, you can pass template: false to skip any attempt to check for a
template digest.
Examples
def show
@article = Article.find(params[:id])
fresh_when(etag: @article, last_modified: @article.updated_at, public: true)
end
This will send a 304 Not Modified response if the request specifies a
matching ETag and If-Modified-Since header. Otherwise, it will render the
show template.
You can also just pass a record:
def show
@article = Article.find(params[:id])
fresh_when(@article)
end
etag will be set to the record, and last_modified will be set to the
record's updated_at.
You can also pass an object that responds to maximum, such as a collection
of records:
def index
@articles = Article.all
fresh_when(@articles)
end
In this case, etag will be set to the collection, and last_modified will
be set to maximum(:updated_at) (the timestamp of the most recently updated
record).
When passing a record or a collection, you can still specify other options,
such as :public and :cache_control:
def show
@article = Article.find(params[:id])
fresh_when(@article, public: true, cache_control: { no_cache: true })
end
The above will set Cache-Control: public, no-cache in the response.
When rendering a different template than the controller/action's default template, you can indicate which digest to include in the ETag:
before_action { fresh_when @article, template: "widgets/show" }
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'actionpack/lib/action_controller/metal/conditional_get.rb', line 137 def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil) response.cache_control.delete(:no_store) weak_etag ||= etag || object unless strong_etag last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at) if strong_etag response.strong_etag = strong_etag, last_modified: last_modified, public: public, template: template elsif weak_etag || template response.weak_etag = weak_etag, last_modified: last_modified, public: public, template: template end response.last_modified = last_modified if last_modified response.cache_control[:public] = true if public response.cache_control.merge!(cache_control) head :not_modified if request.fresh?(response) end |