Advanced Rails - Building Industrial-Strength Web Apps in Record Time

(Tuis.) #1
RESTful Rails | 221

Custom caching


Making cache control more granular requires coupling the caching a bit more with
the application. Assaf Arkin’s restfully_yours plugin*provides some helper methods
for RESTful Rails development, primarily in the domain of cache control. It provides
methods to support both conditionalGET(which controls caches usingIf-Modified-
SinceandIf-None-Match) and conditionalPUT(which prevents stale updates using
If-Unmodified-Since andIf-Match).


The first method provided isif_modified, which supports conditionalGET. It takes
one or more entities as arguments, which are expected to respond to either the
updated_atoretagmethods (or both).†Theupdated_atmethod generatesLast-
Modifiedheaders, while theetagmethod generates anETagheader. Any of these
methods can be overridden or defined on custom entities, depending on the applica-
tion’s idea of “last update time” or “identity.”


This behavior works transparently with ActiveRecord entities. If the ActiveRecord
object has timestamps, itsupdated_atattribute will be used to provide a Last-Modified
time. The restfully_yours plugin also provides a defaultetagmethod that uses an
MD5 hash of either the ActiveRecord ID and lock version if using optimistic locking
(this is a cheap way to get a monotonically increasing version number) or all of its
attributes otherwise. This saves all but the initial trip to the database to get the
attributes and instantiate the ActiveRecord object.


Here is a typical use of this plugin’s conditionalGET functionality:


def show
@product = Product.find params[:id]
if_modified @product do
render
end
end

Theifmodifiedfunction yields to its block if the provided entity (@productin this
case) has been modified from the client’s version, as determined by the appropriate
request headers. If the entity has not been modified, a 304 Not Modified response
will be rendered. This is preferable to the default Rails ETag method because theif

modifieddecision is made before rendering the body, which may be expensive. The
disadvantage is that the list of entities to track must always be passed toif_modified,
and they must generate sensible values forupdated_at andetag.


The complement to conditionalGETis conditionalPUT. Both of them use similar
request and response headers, but they use them toward different ends. While condi-
tionalGETis used to save bandwidth by not resending duplicate response bodies,



  • Available fromhttp://labnotes.org/svn/public/ruby/rails_plugins/restfully_yours.
    †updated_oncan be used as a synonym forupdated_at. In Rails, the_onvariants indicate dates, while the_at
    variants indicate times.

Free download pdf