module ActionController::ConditionalGet

def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil)


before_action { fresh_when @article, template: "widgets/show" }

template, you can indicate which digest to include in the ETag:
When rendering a different template than the controller/action's default

The above will set Cache-Control: public, no-cache in the response.

end
fresh_when(@article, public: true, cache_control: { no_cache: true })
@article = Article.find(params[:id])
def show

options, such as +:public+ and +:cache_control+:
When passing a record or a collection, you can still specify other

recently updated record).
will be set to maximum(:updated_at) (the timestamp of the most
In this case, +etag+ will be set to the collection, and +last_modified+

end
fresh_when(@articles)
@articles = Article.all
def index

collection of records:
You can also pass an object that responds to +maximum+, such as a

record's +updated_at+.
+etag+ will be set to the record, and +last_modified+ will be set to the

end
fresh_when(@article)
@article = Article.find(params[:id])
def show

You can also just pass a record:

will render the +show+ template.
specifies a matching ETag and +If-Modified-Since+ header. Otherwise, it
This will send a 304 Not Modified response if the request

end
fresh_when(etag: @article, last_modified: @article.updated_at, public: true)
@article = Article.find(params[:id])
def show

==== Examples

for a template digest.
all, you can pass template: false to skip any attempt to check
include its digest instead. If the action doesn't render a template at
included in ETags. If the action renders a different template, you can
By default, the template digest for the current controller/action is
[+:template+]
MDN}[https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control].
list of +Cache-Control+ directives, see the {article on
When given, will overwrite an existing +Cache-Control+ header. For a
[+:cache_control+]
such as proxy caches.
+true+ if you want your application to be cacheable by other devices,
By default the +Cache-Control+ header is private. Set this option to
[+:public+]
response if +last_modified+ <= +If-Modified-Since+.
that specify an +If-Modified-Since+ header may receive a 304 Not Modified
Sets a "weak" last-update validator on the response. Subsequent requests
[+:last_modified+]
don't support weak ETags.
video or PDF file, for example, or for compatibility with some CDNs that
byte. This is necessary for serving +Range+ requests within a large
A strong ETag implies exact equality -- the response must match byte for

if the ETag matches exactly.
+If-None-Match+ header may receive a 304 Not Modified response
Sets a "strong" ETag validator on the response. Requests that specify an
[+:strong_etag+]
requests within a PDF file.
used for responses that must be byte-identical, like serving +Range+
so they're good for caching HTML pages in browser caches. They can't be
A weak ETag indicates semantic equivalence, not byte-for-byte equality,

if the ETag matches exactly.
+If-None-Match+ header may receive a 304 Not Modified response
Sets a "weak" ETag validator on the response. Requests that specify an
[+:weak_etag+]
Sets a "weak" ETag validator on the response. See the +:weak_etag+ option.
[+:etag+]

==== Options

304 Not Modified response if the request is already fresh.
Sets the +etag+, +last_modified+, or both on the response, and renders a
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 = combine_etags strong_etag,
      last_modified: last_modified, public: public, template: template
  elsif weak_etag || template
    response.weak_etag = combine_etags 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