Custom Date Output Using Rails
Here is another one of those instances when I just can't believe how much easier something could be than the way that I have done it in the past. I find myself thinking that a lot while I am learning Rails, particularly because one of the most intimidating and tedious parts of application development for me has been writing all the configuration code to get to the point of actually creating something. With Rails, most of that is done for me!
The issue of dealing with dates in a database has always been a hassle for me. The reason for this is that often it is best to store dates in a database as either a UNIX timestamp or as a DATETIME field, which stores the date as YYYY-MM-DD HH:MM:SS. A couple of releases ago MySQL decided that it was better to use a DATETIME field, which is good because I prefer that anyway. You can always calculate out the timestamp value (a UNIX timestamp is the number of seconds that have passed since the epoch) if you need it, and I prefer to have something more human-readable in the database. So how do I take that DATETIME field and format it for display?
It seems easy enough, and it is. In the past I would have created a function in PHP that would hack up the value from the database and put it back together again the way that I want it. There are also function in PHP that have preset values, allowing you to pass the database DATETIME value (and in some cases a UNIX timestamp) into the method and letting PHP do the formatting. In most cases, this works just fine, but it does mean keeping track of formatting functions and such.
Rails appears to have a much easier system for doing that. Let's say that I want to output a date on a web page, but it is stored in the database as a DATETIME field. There are some defaults in Rails, such as if I were to run the code:
article.createdat.tos(:long)
In this example, I am telling Ruby to convert the date value from the database (article.createdat) into a string for display. The "tos" method is passed a parameter telling it that I want the long format, which is preset to output:
May 23, 2007 03:03
This is an example date, but you see the formatting. However, let's say that I want my date to show up in the following format on multiple places across my site:
Wednesday, May 23, 2007
Additionally, I may have a few other formats for the same dates in my application, which I also might use in multiple places. Rails makes this easy. If you go into your "config/environment.rb" file, at the very bottom you can add application-specific settings that will work across your entire app. In the example of formatting a date, I would put in the following line of code:
Time::DATE_FORMATS[:article] = "%A, %B %d, %Y"
Essentially, I am telling Rails that when I format a date, in addition to the default options (:long, :short, etc.) I also want to define my own option called :article. Developers will recognize the symbols that follow, which declare that the date should be output as the full day of the week (written out), the month (written out), the day of the month, and the year in four digits. Easy enough.
Now to use this, I simply replace the :long in my to_s methods with the :article value that I just defined. Using the example from above, we now have some Rails code that looks like:
article.createdat.tos(:article)
Which outputs the date as:
Wednesday, May 23, 2007
We are in business. Not only that, but as I mentioned you can create multiple date formats and use them anywhere in your application. Once defined in the "environment.rb" file, you can take advantage of these in any view.