dcsimg

Date Handling in Rails Applications

Brief walkthru of capturing, storing, and displaying days with Ruby on Rails.

Date handling is one of the web’s inevitables. Almost any web application you write is going to include some form of date-bound hacking. Whether it’s capturing user input via a web form, calculating the difference between two times, or fetching data via a date range, time and the web are closely linked.

Luckily for us, Rails make handling dates and times, like everything else, fairly trivial; that is, once you have an idea of how everything works.

I recently rewrote the section of our admin site in Rails that handles the creation of back issues. Since I had to hunt all over the web for a complete package of documentation to finalize this small task I thought it might be a good idea to share my experience.

In the interest of time we’ll assume you have a Rails app up and running and have controllers and models in place that you’re looking to add date-handling code to.

Form Helpers

Let’s start with data capture via a simple web form. When storing a back issue in the database the most important data we need to capture is its print date. As far as our back issues are concerned, print date is just a month and a year. To accomplish this, Rails provides a few FormHelpers for picking dates that we’ll use in our view.

/app/view/back_issues/new.rhtml

<%= error_messages_for :back_issue %>
<% form_for :back_issue do |f| %>

Print Month: <%= select_month(Date.today, :field_name => "print_month") %> 

Print Year: <%= select_year(Date.today, :start_year => 1999, :field_name => "print_year") %>

<%= submit_tag value='Create Backissue' %>
<% end %>

select_month() and select_year() generate pulldown menus for picking the issue’s month and year.

Pay special attention the :field_name option. It’s not documented well in the Rails API proper and will come in handy when you need to change the name of these select boxes to something other than the default of date[month] and date[year]; necessary if you are using multiple instances of these helpers in a single form.

For still greater control over a date submitted via a form, you might want to take look at select_datetime, which provides a pulldown for each element of a timestamp. Or for something a little more user friendly, check out the really nice Protoype-based Calendar Date Select.

Storing the Data

There’s no real reason for us to store the values from these two fields in separate database columns. Rather we’ll use the month and year values to construct a date in the controller and store the result in a single datetime field called print_date.

/app/controllers/back_issue_controller.rb

class BackIssuesController < ApplicationController

  def new
    @back_issue = BackIssue.new(params[:back_issue])
    return unless request.post?
    @back_issue.print_date = Date.new(params[:date]['print_year'].to_i, params[:date]['print_month'].to_i)
    @back_issue.save!
    flash[:notice] = "New back issue created."
    redirect_to "/covers/new?bi=" + @back_issue.id.to_s

	# In the event our validations fail
    rescue ActiveRecord::RecordInvalid
      render :action => 'new'
  end

end

Ok, that should do it. Once we’ve created an instance of @back_issue with the parameters from the form, we have access to print_date and can give it a newly constructed datetime with Date.new().

Date.new() can take three parameters (year, month, day). We’re taking the default of 1 on the day parameter by not passing anything to the method. In this example, we’re really only concerned with the month and year so the default is fine.

In reality, the new() method on our BackIssuesController is actually a bit more complex than this– hence the params[:back_issue] — but for the sake of simplicity, we’re just showing how to push a new date into the publish_date column from pulldown menus.

The redirect_to in this case point to our cover upload form, but you can point it to whatever destination you like following a successful save!.

Manipulating Dates

We don’t actually need to modify the date after it’s submitted to our controller, but if we did, Ruby has a few operators for quickly adjusting a Date object.

Operator Function
+(n) Add n days to the date
-(n) Subtract n days to the date
>>(n) Add n months to the date
<<(n) Subtract n months to the date

Pretty simple stuff. To demonstrate, let’s take these operators for a spin on the console.

>> d = Date.new(2007, 8, 23)
=> #
>> d.to_s
=> "2007-08-23"
>> yesterday = d-1
=> #
>> yesterday.to_s
=> "2007-08-22"
>> tomorrow = d+1
=> #
>> tomorrow.to_s
=> "2007-08-24"
>> lastmonth = d<<1
=> #
>> lastmonth.to_s
=> "2007-07-23"
>> nextmonth = d>>1
=> #
>> nextmonth.to_s
=> "2007-09-23"

Displaying Dates

Alright, now that we’ve written our back issue date to the database, all that’s left to do is display it in a view. We probably don’t want to display the date formatted as it’s stored: ‘YYYY-MM-DD’. Rather we want something like the current back issue page that displays the full month name and the year. To accomplish this we’ll use strftime().

If you’re familiar with PHP’s date() method, strftime() is similar, you pass the method a format string that defines how you want the date output. The difference is that while you pass PHP’s date() both a format and a timestamp, strftime() is a method that operates on a Date object. And everything in Rails is an object.

Rails automatically knows to treat our datetime columns in the database as Date objects, so, after you’ve fetched the back issue data from the database in the controller, formatting the date in the view is as simple as:

<%= @back_issue.print_date.strftime('%B %Y') %>

Which will print something like “January 2007″ to the screen.

For a full list of format codes for strftime(), see the table below.

Format Meaning
%a The abbreviated weekday name (“Sun”)
%A The full weekday name (“Sunday”)
%b The abbreviated month name (“Jan”)
%B The full month name (“January”)
%c The preferred local date and time representation
%d Day of the month (01..31)
%H Hour of the day, 24-hour clock (00..23)
%I Hour of the day, 12-hour clock (01..12)
%j Day of the year (001..366)
%m Month of the year (01..12)
%M Minute of the hour (00..59)
%p Meridian indicator (“AM” or “PM”)
%S Second of the minute (00..60)
%U Week number of the current year, starting with the first Sunday as the first day of the first week (00..53)
%W Week number of the current year, starting with the first Monday as the first day of the first week (00..53)
%w Day of the week (Sunday is 0, 0..6)
%x Preferred representation for the date alone, no time
%X Preferred representation for the time alone, no date
%y Year without a century (00..99)
%Y Year with century
%Z Time zone name
%% Literal “%” character

Rails Magic Wishlist

And that’s about it. Not too difficult but it’s actually a little more work that I’d like to do. Frankly, I wish there was some Rails magic that did the date handling in the controller for me.

Creating a new date and casting parameters in the controller isn’t how I’d like this to function — ultimately it doesn’t strike me as terribly DRY. Rather, I would like to have the option of passing the form fields to the controller as back_issue[print_date_month] and back_issue[print_date_year] and have Rails realize that these are components of my print_date field and compile these elements into a date for me. But all-in-all the solution we have here is reasonably clean and maybe I can build some of that magic into a plugin or helper at a later date.

Comments on "Date Handling in Rails Applications"

That would be the finish of this article. Right here you will uncover some websites that we believe you?ll appreciate, just click the links.

That is the end of this write-up. Right here you?ll locate some websites that we consider you will enjoy, just click the hyperlinks.

Just beneath, are numerous totally not connected sites to ours, nevertheless, they’re surely worth going over.

The information mentioned in the report are several of the most effective accessible.

fantastic points altogether, you simply
received a logo new reader. What would you recommend
with regards to your publish that you just made some days ago?
Any certain?

Stop by my web page … KoriMBound

One of our visitors not too long ago proposed the following website.

Very few websites that take place to be in depth beneath, from our point of view are undoubtedly nicely worth checking out.

Always a large fan of linking to bloggers that I adore but don?t get a great deal of link adore from.

Please go to the websites we adhere to, like this 1, because it represents our picks in the web.

We came across a cool internet site that you just could possibly love. Take a appear in the event you want.

Just beneath, are many entirely not associated web-sites to ours, nevertheless, they are certainly worth going over.

Please check out the web sites we follow, like this one, as it represents our picks through the web.

Wonderful story, reckoned we could combine several unrelated information, nonetheless definitely really worth taking a appear, whoa did a single discover about Mid East has got much more problerms as well.

Very handful of internet websites that transpire to be detailed below, from our point of view are undoubtedly effectively really worth checking out.

The information talked about within the write-up are a few of the best accessible.

Wonderful story, reckoned we could combine a handful of unrelated data, nevertheless seriously worth taking a search, whoa did one particular study about Mid East has got much more problerms at the same time.

Below you will discover the link to some internet sites that we believe you’ll want to visit.

Here are some links to websites that we link to simply because we believe they may be worth visiting.

I head to see daily a couple of websites and sites to read posts, however
this website provides quality based posts.

Here is my weblog – TheronPHoger

Every the moment inside a whilst we pick out blogs that we read. Listed beneath would be the most recent sites that we choose.

Please take a look at the internet sites we comply with, such as this one, because it represents our picks from the web.

That is the finish of this report. Here you?ll uncover some web-sites that we assume you will appreciate, just click the hyperlinks.

You made some first rate factors there. I seemed on the web for the issue and found most individuals will associate with together with your website.

One of our guests lately advised the following website.

Con el tema de no tener frío en la parte del refrigerador, calculo que puede ser sensor, lo que no se es cuanto me tiene que medir en ohm. Tengo un combi FAGOR no-frost que en verano se dispara la alarma acústica a la más mínima. En segundo lugar, distinguir tu generosidad y gran persona que debes ser, ya que tomarte tanto tiempo para dedicar a ayudar a otros, habla por si solo. Hola, comparto con ustedes las experiencias que tenemos de ser sufridos pero contentos usuarios de una heladera NF General Electric TBG 16 ZBC desde el año 1995.

One of our guests lately suggested the following website.

Wonderful story, reckoned we could combine a couple of unrelated data, nevertheless really really worth taking a appear, whoa did a single learn about Mid East has got much more problerms also.

Always a huge fan of linking to bloggers that I love but do not get lots of link enjoy from.

Usually posts some pretty fascinating stuff like this. If you?re new to this site.

Leave a Reply