---
title: "Rails 5 Passing records to fresh_when and stale?"
description:
  "Rails 5 adds support to pass collection of records to fresh_when and stale?
  for improved caching"
canonical_url: "https://www.bigbinary.com/blog/rails-5-supports-passing-collection-of-records-to-fresh_when-and-stale"
markdown_url: "https://www.bigbinary.com/blog/rails-5-supports-passing-collection-of-records-to-fresh_when-and-stale.md"
---

# Rails 5 Passing records to fresh_when and stale?

Rails 5 adds support to pass collection of records to fresh_when and stale? for
improved caching

- Author: Ershad Kunnakkadan
- Published: August 16, 2016
- Categories: Rails 5, Rails

Rails has powerful tools to control
[caching of resources via HTTP](http://api.rubyonrails.org/classes/ActionController/ConditionalGet.html)
such as `fresh_when` and `stale?`.

Previously we could only pass a single record to these methods but now Rails 5
adds support for accepting a collection of records as well. For example,

```ruby

def index
  @posts = Post.all
  fresh_when(etag: @posts, last_modified: @posts.maximum(:updated_at))
end

```

or simply written as,

```ruby

def index
  @posts = Post.all
  fresh_when(@posts)
end

```

This works with `stale?` method too, we can pass a collection of records to it.
For example,

```ruby

def index
  @posts = Post.all

  if stale?(@posts)
    render json: @posts
  end
end

```

To see this in action, let's begin by making a request at `/posts`.

```bash

$ curl -I http://localhost:3000/posts

HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
ETag: W/"a2b68b7a7f8c67f1b88848651a86f5f5"
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 7c8457e7-9d26-4646-afdf-5eb44711fa7b
X-Runtime: 0.074238

```

In the second request, we would send the ETag in `If-None-Match` header to check
if the data has changed.

```bash

$ curl -I -H 'If-None-Match: W/"a2b68b7a7f8c67f1b88848651a86f5f5"' http://localhost:3000/posts

HTTP/1.1 304 Not Modified
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
ETag: W/"a2b68b7a7f8c67f1b88848651a86f5f5"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 6367b2a5-ecc9-4671-8a79-34222dc50e7f
X-Runtime: 0.003756

```

Since there's no change, the server returned `HTTP/1.1 304 Not Modified`. If
these requests were made from a browser, it would automatically use the version
in its cache on the second request.

The second request was obviously faster as the server was able to save the time
of fetching data and rendering it. This can be seen in Rails log,

```plaintext

Started GET "/posts" for ::1 at 2016-08-06 00:39:44 +0530
Processing by PostsController#index as HTML
   (0.2ms)  SELECT MAX("posts"."updated_at") FROM "posts"
   (0.1ms)  SELECT COUNT(*) AS "size", MAX("posts"."updated_at") AS timestamp FROM "posts"
  Rendering posts/index.html.erb within layouts/application
  Post Load (0.2ms)  SELECT "posts".* FROM "posts"
  Rendered posts/index.html.erb within layouts/application (2.0ms)
Completed 200 OK in 31ms (Views: 27.1ms | ActiveRecord: 0.5ms)


Started GET "/posts" for ::1 at 2016-08-06 00:39:46 +0530
Processing by PostsController#index as HTML
   (0.2ms)  SELECT MAX("posts"."updated_at") FROM "posts"
   (0.1ms)  SELECT COUNT(*) AS "size", MAX("posts"."updated_at") AS timestamp FROM "posts"
Completed 304 Not Modified in 2ms (ActiveRecord: 0.3ms)

```

Cache expires when collection of records is updated. For example, an addition of
a new record to the collection or a change in any of the records (which changes
`updated_at`) would change the `ETag`.

Now that Rails 5 supports collection of records in `fresh_when` and `stale?`, we
have an improved system to cache resources and make our applications faster.
This is more helpful when we have controller actions with time consuming data
processing logic.

## Links

- [Human page](https://www.bigbinary.com/blog/rails-5-supports-passing-collection-of-records-to-fresh_when-and-stale)
