Caching with ActiveResource
ActiveResource makes it easy to communicate with REST APIs. It relies a lot on REST conventions so you can set your clients with little to no configuration, plus it has an interface very similar to that of ActiveRecord.
When developing REST clients with ActiveResource you need to remember that you are not in fact working with a database connection. For example, there's a lot going on to make a find method work:
* Sending the GET request
* The API server handling of the request, which may include getting data from a database, serializing the response, and whatever extra work the server needs to do.
* Sending the response over the network
* The client de-serializing the data and returning a new instance of the model.
A lot of work indeed. Thankfully, HTTP comes with some strategies meant to reduce the amount of unnecessary requests: cache control headers, last modified headers and Etags.
Today I'll show you how to to implement caching on active support and how to use Etags to invalidate the cache.
The Server
https://gist.github.com/lacides/4ce658bac7df4a03ee7b
The server just gets an User from the db, simulates some work by waiting 4 seconds and then returns a json representation of the user.
The Client
https://gist.github.com/lacides/2085358f95acd52149a9
It doesn't get simpler
Caching
https://gist.github.com/lacides/04cf5852a11ea44a7958
This a simple implementation of a read-through cache on the connection class.
Basically when the connection needs to get a resource, it first checks the cache, it uses the cached resource if available, if not it requests it from the API, saves it to the cache and then uses it.
Invalidating the Cache with Etags
There's one huge problem with this approach, we have no means of invalidating the cache. If the api makes changes to the resource then we're stuck with the cached version. Invalidating our cache with Etags can solve this problem.
How it works
When the server returns a resource it will send it along its Etag (typically a hash generated from its last update date), which is sent in a HTTP "Etag" header.
The client then caches the resource and its Etag. When the client tries to retrieve the same resource again, it will send its cached copy of the Etag on a "If-None-Match" header.
Then the server gets to decide if the Etag its valid. If so, it will send a short response with a 304 Not Modified status, if not it will send a full response with the resource contents.
If the client gets the 304 response then it will use its cached resource, if not it will update its cache with the new resource and use it.
The new server
Sinatra comes with an entity_tag method (aliased as etag) that handles the server side implementation of etag caching. Our updated server now looks like this:
https://gist.github.com/lacides/e0b47fbf04cd47bc4aaf
The new client
Our caching solution, updated to invalidate the cache based on Etags, now looks like this:
https://gist.github.com/lacides/bbaa6f6de63d0795fed6
Does it work with Rails?
Of course it does! Take a look at http://apidock.com/rails/ActionController/ConditionalGet/stale%3F and http://guides.rubyonrails.org/caching_with_rails.html#conditional-get-support to find out how.















