1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
# In one of your helper module, dump: def cachable_time_ago_in_words(from) js_call = javascript_tag "document.write(DateHelper.timeAgoInWords(#{(from.to_i * 1000).to_json}) + ' ago');" "<noscript>on #{from.to_formatted_s(:long)}</noscript>#{js_call}" end # In your application.js var DateHelper = { timeAgoInWords: function(from) { return this.distanceOfTimeInWords(new Date().getTime(), from); }, distanceOfTimeInWords: function(to, from) { seconds_ago = ((to - from) / 1000); minutes_ago = Math.floor(seconds_ago / 60); if(minutes_ago == 0) { return "less than a minute"; } if(minutes_ago == 1) { return "a minute"; } if(minutes_ago < 45) { return minutes_ago + " minutes"; } if(minutes_ago < 90) { return " about 1 hour"; } hours_ago = Math.round(minutes_ago / 60); if(minutes_ago < 1440) { return "about " + hours_ago + " hours"; } if(minutes_ago < 2880) { return "1 day"; } days_ago = Math.round(minutes_ago / 1440); if(minutes_ago < 43200) { return days_ago + " days"; } if(minutes_ago < 86400) { return "about 1 month"; } months_ago = Math.round(minutes_ago / 43200); if(minutes_ago < 525960) { return months_ago + " months"; } if(minutes_ago < 1051920) { return "about 1 year"; } years_ago = Math.round(minutes_ago / 525960); return "over " + years_ago + " years"; } } # Then in your views use: <%= cachable_time_ago_in_words Time.now %>
Refactorings
No refactoring yet !
macournoyer
September 19, 2007, September 19, 2007 13:16, permalink
Seems it doesn't work with AJAX request, here my solution, pretty simple
Thx James for reporting this!
1 2 3 4 5 6 7 8
def cachable_time_ago_in_words(from) if request.xhr? time_ago_in_words from else js_call = javascript_tag "document.write(DateHelper.timeAgoInWords(#{(from.to_i * 1000).to_json}) + ' ago');" "<noscript>on #{from.to_formatted_s(:long)}</noscript>#{js_call}" end end
jamesgolick
September 19, 2007, September 19, 2007 13:18, permalink
But document.write is still gross, so here's my take
1 2 3 4 5
def cachable_time_ago_in_words(from, id_prefix = '') id = "#{id_prefix}_#{from.to_i}" content_tag :span, "", :id => id javascript_tag "$('#{id}').update(DateHelper.timeAgoInWords(#{(from.to_i * 1000).to_json}))" end
macournoyer
September 19, 2007, September 19, 2007 13:29, permalink
You're right, but this does not degrade gracefully and the first content_atg won't be rendered, here's my fix
1 2 3 4 5
def cachable_time_ago_in_words(from, id_prefix = 'time_ago') id = "#{id_prefix}_#{from.to_i}" content_tag(:span, from.to_formatted_s(:long), :id => id) << javascript_tag("$('#{id}').update(DateHelper.timeAgoInWords(#{(from.to_i * 1000).to_json}))") end
makenai
April 10, 2008, April 10, 2008 21:54, permalink
In the rails version the numbers are not cast to Floats before dividing, so the results are not consistent when you put this code and time_ago_in_words side by side. Using Math.floor will give the proper results.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
distanceOfTimeInWords: function(to, from) { seconds_ago = ((to - from) / 1000); minutes_ago = Math.floor(seconds_ago / 60); if(minutes_ago == 0) { return "less than a minute"; } if(minutes_ago == 1) { return "1 minute ago"; } if(minutes_ago < 45) { return minutes_ago + " minutes"; } if(minutes_ago < 90) { return " about 1 hour"; } hours_ago = Math.floor(minutes_ago / 60); if(minutes_ago < 1440) { return "about " + hours_ago + " hours"; } if(minutes_ago < 2880) { return "1 day"; } days_ago = Math.floor(minutes_ago / 1440); if(minutes_ago < 43200) { return days_ago + " days"; } if(minutes_ago < 86400) { return "about 1 month"; } months_ago = Math.floor(minutes_ago / 43200); if(minutes_ago < 525960) { return months_ago + " months"; } if(minutes_ago < 1051920) { return "about 1 year"; } years_ago = Math.floor(minutes_ago / 525960); return "over " + years_ago + " years"; }
When a page is cached, if you use the Rails ActionView helper "time_ago_in_words" the time will stay the same until the cache is refreshed, ie.: about 1 sec ago .... 1 hour later .... 1 sec ago.
Here's the solution in found at http://nullstyle.com/2007/6/3/caching-time_ago_in_words
Got any better solution ? Let me know !