ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!( :default => '%d %b %Y' )
When it comes to setting a default date display format for both display elements and form input elements in Rails it gets quite tricky (a good explanation can be found on the Rails forum post http://www.ruby-forum.com/topic/57923).
In this article I'll show you how to set a global display format for all your dates and how to input and validate dates with user friendly date formats using a date_field helper plus a lightweight JavaScript calendar control.
A tarball containing code for the date validator, date_field helper and calendar control can be download here http://www.methods.co.nz/rails_date_kit/rails_date_kit_1.1.0.tar.gz.
Take a look at the calendar_example.html to see the calendar control in action. The calendar look and feel copies the Swazz Calendar but the underlying code has been rewritten (see calendar.README).
Look at the documentation header in calendar.js for the calendar control options and how it is used.
Add to your preferred date display format into ./config/environment.rb:
ActiveSupport::CoreExtensions::Date::Conversions::DATE_FORMATS.merge!( :default => '%d %b %Y' )
Now this is fine for automatically formatting dates in display elements but there are a couple of problems:
Rails uses the :default format for writing the database — so if your database does not understand the default format you'll store null dates, not so good.
|
Note
|
This is the case in Rails 1.2.1 but seems to have been fixed by Edge Rails revision 6270, March 2007. See TRAC ticket http://dev.rubyonrails.org/ticket/7411 (alternatively 1.2.1 users could patch the quote method in lib/active_record/connection_adapters/abstract/quoting.rb). |
Date values put into text input field helpers are not formatted with the :default date format, the raw database format is used. To get around this restriction I explicitly set the field values when using text input elements for dates (see the date_field example in the next section).
Put calendar.js in ./public/javascripts.
Put calendar.css in ./public/stylesheets.
Put calendar_prev.png and calendar_next.png in ./public/images.
Put date_helper.rb in ./app/helpers.
In controllers that input dates (or in the application base controller ./app/controllers/application.rb) put:
helper :date
Put the following lines in your page headers:
<%= stylesheet_link_tag 'calendar.css' %> <%= javascript_include_tag 'calendar' %>
In templates with forms that input dates use the date_field helper. For example:
<%= date_field('person', 'birthday', :value => @person.birthday) %>
|
Note
|
The date value is passed explicitly to ensure it's formatted with the :default date format (see explanation in previous section). |
We can now view and input date values, all that remains is to validate them. The date_validator.rb library module adds a validates_dates date validator to Rails and accepts a range of user friendly date formats.
Drop date_validator.rb into ./lib.
Require the validator in your models and add date validations. For example:
require_dependency 'date_validator'
validates_dates :birthday,
:from => '1 Jan 1930',
:to => Date.today,
:allow_nil => true
Dates are particularly vexing in a global web environment as there are many acceptable abbreviated and locale dependent formats. Rather than try to support multiple locale dependent formats I side-stepped the issue and choose two unambiguous formats along with abbreviations and date intervals.
These formats coupled with the calendar control result in painless date input.
Where d is the day number; mmmm is the month name; yyyy is the year number. This unambiguous format has been combined with a number of abbreviations relative to the current date. Examples: 22, 22 feb, 22 feb 06, 22 february 2006
Using the +n[unit] or -n[unit] format you can assign a date by adding or subtracting days, weeks, months or years from the current date by entering a number prefixed by a plus or minus character and followed by an interval unit. Examples: +22, +22 days, +22d, -4 weeks, -4w, -4week, +6 months, +6m, +6month, -2 years, -2y
The ISO yyyy-mm-dd date format, although verbose, is the only locale independent universally accepted standard. For example 2001-12-25.
Handy Patriawan has written a step-by-step tutorial.
Added optional next/previous year buttons (thanks to Ian Miller for contributing this feature).
If the last row of the calendar contains no dates it is not shown (thanks to Ian Miller for contributing this feature).
Blank day cells are distinguished from cells with day numbers.
Weekend days are distinguished from weekdays.
Day names displayed as 3 letter abbreviations (previously just the first letter of the day name was displayed).
Added tooltip titles to next/previous month/year buttons.
Documentation errata.
Added day_names option.
The date_field helper will now use the format option (if specified) to display the initial date value (previously used the default format). Thanks to Chris Gernon for this patch.
Added calendar control month_names option.
Updated date_field helper to pass locale month names to calendar control.
First public release.