Even Better Rails Date Formatting

I just recently came across Andy Croll's article about using strftime to format date and time values in a Rails View.

He makes a strong argument that you shouldn't use strftime in a Rails View:

<%= @user.last_sign_in_at.strftime('%m-%e-%y %H:%M') %>

Because Rails has built in date and time formats, and you can also define your own. To use one of the built in formats you can just call to_s on a Date or Time class and pass in the format you wish to use:

<%= @user.last_sign_in_at.to_s(:long) %>

See Andy Croll's article for the nitty gritty details.

What About nil?

If you've spent much time writing Ruby or Rails code you probably already see an issue with the to_s call above. What if the last_sign_in_at value is nil?

You might think... "Hmm, no problem. Calling to_s on nil just returns an empty string, so no harm, no foul."

nil.to_s
  => ""

Well, there are two problems with that line of thinking. First, Rails actually creates a to_formatted_s method that takes a single argument which references the format to use. The to_formatted_s method is aliased too to_s for Date and Time objects. If you try to pass an argument to nils version of to_s you get an error.

nil.to_s(:long)
ArgumentError (wrong number of arguments (given 1, expected 0))

Second, you might actually want to have some visual representation that the date or time is missing or unset. I like to show a couple of dash characters when a date or time is missing.

Best of Both Worlds

Here is how I handle date and time formatting in my Rails apps.

In the application_helper module I add a format_date method, so it is available to every view.

def format_date(date, format = :long)
  date.blank? ? '--' : date.to_s(format)
end

In your views you can call it like so:

<%= format_date @user.last_sign_in_at %>

If the user has never signed in you will see the two dashes that signify there is no last_sign_in_at time set. Otherwise the last_sign_in_at will be formatted with the :long format.

If you want to override the default format you can always pass in a different one.

<%= format_date @user.last_sign_in_at, :db %>

Or use your own format (provided you defined one as outlined in Andy Croll's article).

<%= format_date @user.last_sign_in_at, :myformat %>

Conclusion

Be aware of nils in your code. Anytime you see a . in your code think to yourself, "What happens if the thing on the left side of that . is nil?".