Rails time_ago_in_words producing bad output - ruby-on-rails

I thought this might be due to moving to activesupport 2.3.5 but now I believe something else must have happened.
Model has a valid rfc822 style date:
>> s.lastVisitDate
=> "Thu, 06 Jan 2011 22:24:10 -0800"
But in my view:
<%=h time_ago_in_words(#site.lastVisitDate) -%>
renders: *about {{count}} hours ago*
instead of: *about 2 hours ago* which was working just fine earlier.
Wondering if anyone else has seen this behavior. I've reviewed my version history for the model and view and nothing has changed recently so I believe I must have messed up something on the config side of things.

I found that I was missing the appropriate values in a locale file.
So in my case I added the following to /config/locales/en.yml
I am not sure why this was previously working or what specific gem or config change triggered this issue but having the proper definition here make actionpack happy.
# Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
datetime:
distance_in_words:
half_a_minute: "half a minute"
less_than_x_seconds:
one: "less than 1 second"
other: "less than %{count} seconds"
x_seconds:
one: "1 second"
other: "%{count} seconds"
less_than_x_minutes:
one: "less than a minute"
other: "less than %{count} minutes"
x_minutes:
one: "1 minute"
other: "%{count} minutes"
about_x_hours:
one: "about 1 hour"
other: "about %{count} hours"
x_days:
one: "1 day"
other: "%{count} days"
about_x_months:
one: "about 1 month"
other: "about %{count} months"
x_months:
one: "1 month"
other: "%{count} months"
about_x_years:
one: "about 1 year"
other: "about %{count} years"
over_x_years:
one: "over 1 year"
other: "over %{count} years"
almost_x_years:
one: "almost 1 year"
other: "almost %{count} years"
prompts:
year: "Year"
month: "Month"
day: "Day"
hour: "Hour"
minute: "Minute"
second: "Seconds"

Related

ruby on rails time_ago_in_words doesn't display seconds ago

Here is my en.yml locale
en:
datetime:
distance_in_words:
less_than_x_seconds:
one: "1 sec"
other: "%{count} secs"
x_seconds:
one: "1 sec"
other: "%{count} secs"
less_than_x_minutes:
one: "1 min"
other: "%{count} mins"
x_minutes:
one: "1 min"
other: "%{count} mins"
about_x_hours:
one: "1 hour"
other: "%{count} hours"
x_days:
one: "1 day"
other: "%{count} days"
about_x_months:
one: "1 month"
other: "%{count} months"
x_months:
one: "1 month"
other: "%{count} months"
about_x_years:
one: "1 year"
other: "%{count} years"
over_x_years:
one: "1 year"
other: "%{count} years"
almost_x_years:
one: "1 year"
other: "%{count} years"
Whenever i post something i use
<%= link_to time_ago_in_words(post.created_at), post_path(post) %>
to display the time ago since the post was created but instead of showing 1 sec, 2 secs etc... it displays 1 min, and continues with minutes
You need to pass true to time_ago_in_words's include_seconds parameter:
time_ago_in_words(post.created_at, true)
See the documentation for distance_of_time_in_words, which is used by time_ago_in_words for more detail.

Ruby/Rails time helper method

I am looking for a helper class/method/gem that's out there that will help me format a time helper. The output I'm looking after passing in an instance of Time.now is something like the following:
"1 minute ago"
"2 minutes ago"
"1 hour ago"
"2 hours ago"
"1 day ago"
"2 days ago"
"over a year ago"
I started writing something like this but it's going to be long and painful and I feel like something like this has to exist. The only catch is I need it to use my own wording, so something with a formatter is required..
def time_ago_to_str(timestamp)
minutes = (((Time.now.to_i - timestamp).abs)/60).round
return nil if minutes < 0
Rails.logger.debug("minutes #{minutes}")
return "#{minutes} minute ago" if minutes == 1
return "#{minutes} minutes ago" if minutes < 60
# crap load more return statements to follow?
end
Such a helper already exists and is built-in to Rails:
http://apidock.com/rails/ActionView/Helpers/DateHelper/time_ago_in_words
time_ago_in_words(5.days.ago)
=> "5 days"
EDIT:
If you'd like to customize the wording you can create a custom I18n locale, for example, I created one called time_ago in config/locales/time_ago.yml:
time_ago:
datetime:
distance_in_words:
half_a_minute: "half a minute"
less_than_x_seconds:
one: "less than 1 second"
other: "less than %{count} seconds"
x_seconds:
one: "1 second"
other: "%{count} seconds"
less_than_x_minutes:
one: "less than a minute"
other: "less than %{count} minutes"
x_minutes:
one: "1 min"
other: "%{count} mins"
about_x_hours:
one: "about 1 hour"
other: "about %{count} hours"
x_days:
one: "1 day"
other: "%{count} days"
about_x_months:
one: "about 1 month"
other: "about %{count} months"
x_months:
one: "1 month"
other: "%{count} months"
about_x_years:
one: "about 1 year"
other: "about %{count} years"
over_x_years:
one: "over 1 year"
other: "over %{count} years"
almost_x_years:
one: "almost 1 year"
other: "almost %{count} years"
Now, you can use the locale with distance_of_time_in_words:
# distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
distance_of_time_in_words(5.minutes.ago, Time.now, true, {:locale => "time_ago"})
=> "5 mins"
You could of course add this to config/locales/en.yml and completely override them application wide, which would you allow you to call time_ago_in_words as mentioned above!

distance_of_time_in_words and then remove the word "about"

I have this code:
= distance_of_time_in_words(Time.now, real_time + 0.seconds, true)
Which generates also like:
about 15 hours
less than
Is there a way to remove the word "About" from the results? Already searched a lot but cannot find any info, the function in itself is great it throws back hours, minutes, seconds, etc. so great but the worst "about" has to go! Anyone knows how?
Since distance_of_time_in_words uses localization keys, you can simply override them to achieve what you want in an I18n-safe way:
config/locales/en.yml:
en:
# Used in distance_of_time_in_words(), distance_of_time_in_words_to_now(), time_ago_in_words()
datetime:
distance_in_words:
half_a_minute: "half a minute"
less_than_x_seconds:
one: "1 second" # default was: "less than 1 second"
other: "%{count} seconds" # default was: "less than %{count} seconds"
x_seconds:
one: "1 second"
other: "%{count} seconds"
less_than_x_minutes:
one: "a minute" # default was: "less than a minute"
other: "%{count} minutes" # default was: "less than %{count} minutes"
x_minutes:
one: "1 minute"
other: "%{count} minutes"
about_x_hours:
one: "1 hour" # default was: "about 1 hour"
other: "%{count} hours" # default was: "about %{count} hours"
x_days:
one: "1 day"
other: "%{count} days"
about_x_months:
one: "1 month" # default was: "about 1 month"
other: "%{count} months" # default was: "about %{count} months"
x_months:
one: "1 month"
other: "%{count} months"
about_x_years:
one: "1 year" # default was: "about 1 year"
other: "%{count} years" # default was: "about %{count} years"
over_x_years:
one: "1 year" # default was: "over 1 year"
other: "%{count} years" # default was: "over %{count} years"
almost_x_years:
one: "1 year" # default was: "almost 1 year"
other: "%{count} years" # default was: "almost %{count} years"
distance_of_time_in_words(Time.now, real_time + 0.seconds, true).gsub('about ','')
look here for more information
try a helper (put this code in app/helpers/application_helper.rb)
def remove_unwanted_words string
bad_words = ["less than", "about"]
bad_words.each do |bad|
string.gsub!(bad + " ", '')
end
return string
end
in bad words you can define strings which you want to have removed from that string.
user it like this:
<%= remove_unwanted_words distance_of_time_in_words(Time.now, real_time + 0.seconds, true) %>

I18n::InvalidPluralizationData error

Based on help from this site, I was able to set up a display for the person's age. But when I do something like <%= distance_of_time_in_words(DateTime.now, p.dob) %>, I get an invalidPliralizationData error, "translation data {:one=>"1 an", :many=>"{{count}} ans"} can not be used with :count => 30"
My yml file has all the translations for datetime:distance_in_words_... where ... defines all the various possible occurrences.
Again help will be highly appreciated. All previous Google searches haven't been fruitful
I think the hash keys are :one and :other (not :many). I suspect they chose this wording because :other also includes the zero case (?).
Anyway, hope that helps!
It seems you didn't define :many in your localization file.
English has only :one and :many
If you are using :en then you should replace :many by :other.
Else if you are using another language you need to check the mapping key for 30 in config/locales/plurals.rb and define it in your localization file.
For example, 30 should be :many in :ar Arabic
Helped me with such localization file
en:
datetime:
distance_in_words:
less_than_x_seconds:
one: "1 second" # default was: "less than 1 second"
many: "%{count} seconds" # default was: "less than %{count} seconds"
x_seconds:
one: "1 second"
many: "%{count} seconds"
less_than_x_minutes:
one: "a minute" # default was: "less than a minute"
many: "less than %{count} minutes" # default was: "less than % {count} minutes"
x_minutes:
one: "1 minute"
many: "about %{count} minutes"
about_x_hours:
one: "1 hour" # default was: "about 1 hour"
many: "about %{count} hours" # default was: "about %{count} hours"
x_days:
one: "1 day"
many: "%{count} days"
about_x_months:
one: "1 month" # default was: "about 1 month"
many: "%{count} months" # default was: "about %{count} months"
x_months:
one: "1 month"
many: "%{count} months"
about_x_years:
one: "1 year" # default was: "about 1 year"
many: "%{count} years" # default was: "about %{count} years"
over_x_years:
one: "1 year" # default was: "over 1 year"
many: "%{count} years" # default was: "over %{count} years"
almost_x_years:
one: "1 year" # default was: "almost 1 year"
many: "%{count} years" # default was: "almost %{count} years"
As you can see, :other key changed to :many

Getting {{count}} with time_ago_in_words

I currently have this code in my application:
def comment_poster(comment)
if comment.user
"posted by #{comment.user.username} #{time_ago_in_words(comment.created_at)} ago"
else
"posted by anonymous"
end
end
However, this works only when I have posted in seconds ago, and years ago:
posted by teejay about 1 year ago
posted by teejay about 1 month ago
When I edit the created_at value to a few days ago it gives me this:
posted by thorpe {{count}} days ago
What should I do for this to make it work and lose that {{count}}
Edit: I am using Rails 2.3.5 if that means anything
Edit: #2
I fixed the problem by pasting this code at config/locales/en.yml
datetime:
distance_in_words:
half_a_minute: "half a minute"
less_than_x_seconds:
one: "less than 1 second"
other: "less than %{count} seconds"
x_seconds:
one: "1 second"
other: "%{count} seconds"
less_than_x_minutes:
one: "less than a minute"
other: "less than %{count} minutes"
x_minutes:
one: "1 minute"
other: "%{count} minutes"
about_x_hours:
one: "about 1 hour"
other: "about %{count} hours"
x_days:
one: "1 day"
other: "%{count} days"
about_x_months:
one: "about 1 month"
other: "about %{count} months"
x_months:
one: "1 month"
other: "%{count} months"
about_x_years:
one: "about 1 year"
other: "about %{count} years"
over_x_years:
one: "over 1 year"
other: "over %{count} years"
almost_x_years:
one: "almost 1 year"
other: "almost %{count} years"
prompts:
year: "Year"
month: "Month"
day: "Day"
hour: "Hour"
minute: "Minute"
second: "Seconds"
Can anyone explain what the issue was?
The problem is with the i18n gem version. If you downgrade to 0.4.1 this problem will disappear.
The thing is that from version 0.4.1 on, the way of accessing variables isn't {{variable}} anymore.

Resources