Increment page view counter even if page is cached

Adding cache to web pages is usually a good practice; however, making all the content static prevents you from adding some functionalities. A common case is when you need to increment a counter every time a cached resource is viewed.

If you have a model which is being observed by a Rails Sweeper, a simple update_attributes to increment the counter by 1 will expire all the cached object. And it will do it every time it is viewed. This behavior not only makes caching obsolete, but drastically decreases the overall performance of the site on each page hit.

There are some solutions to this problem, the most efficient probably would be using an alternate system to store stats like a key/value database (Redis, MongoDB, etc), but an easier approach would be to update the database directly to bypass the observer and skip the cache expiration. This can be done with the ActiveRecord method update_counters.

@element.class.update_counters @element.id, :view_count => 1

There are two problems with this solution. The first is obvious, with each page view the database will be hit, reducing a bit the performance. The second is that the cache has to be expired periodically to reflect the counter increments. But for most average sites it’s a good solution.

Ubiquo Widgets expiring cache policy

With ubiquo it’s quite easy to expire cached data of a widget after a given time. By defining the expires_in clause in the configuration policy file (“config/initializers/design_cache.rb”) we can set the time to live (in seconds) of the cached object. Each widget should have it’s own expiring configuration if needed.

:media_center_top => [
  {:expires_in => 15.minutes},
  :Video,
  :Document,
  :Photo
]

Another way of expiring cached data is using a system cron job.