Nithin Bekal

Posts About Notes Slides

Avoid time_ago_in_words in Rails

24 Jul 2015

ActiveSupport’s time_ago_in_words makes it really easy to display time as “x minutes/hours/months ago” format. However, it has one big disadvantage: it makes it harder to use fragment caching.

Let’s say we’re displaying posts within a partial:

<% # app/views/posts/_post.html.erb %>

<% cache post do %>
  <%= post.body %><br/>
  (posted <%= time_ago_in_words(post.created_at) %> ago)
<% end %>

Here the second line might show “posted 2 minutes ago” right now, but in a minute, it needs to change to “posted 3 minutes ago”, but it will keep showing the older time until the cache expires.

My preferred solution for this is to use the timeago jquery plugin. Timeago plugin requires time in ISO 8601 format, so we’ll add a helper method that renders a span containing time in the correct format.

# app/helpers/time_helper.rb

module TimeHelper
  def timeago(time)
    content_tag(:span, time.iso8601, title: time.iso8601, class: 'timeago')
  end
end

Let’s add a line of Javascript to convert all spans having the class timeago to the time ago in words format:

$('.timeago').timeago()

Now we can use this in the view, in place of time_ago_in_words:

<% # app/views/posts/_post.html.erb %>

<% cache post do %>
  <%= post.body %><br/>
  (posted <%= timeago(post.created_at) %> ago)
<% end %>

Not only does this allow you to use fragment caching correctly, but it also updates the time if you keep the page open for a while.

Hi, I’m Nithin Bekal, a software craftsman with over 7 years of experience in shipping web applications. I mostly use Ruby, but lately have also been exploring Elixir. Co-founder of CrowdStudio.in, and helping organize Rubyconf India. Tweet to me at @nithinbekal.