A collection of computer systems and programming tips that you may find useful.
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Monday, February 15, 2010

Rails check_box_tag and Rails 2.3.x

Basic HTML checkboxes have an inherent problem in that there is no explicit value passed to the server when the box is unchecked.

Under Rails 2.2.2 (and thereabouts) you could circumvent this limitation with an ugly hack.

If you wanted to use a check_box_tag helper in a form you had to use a had to follow it with a hidden_field_tag that contained the unchecked value. For instance:

<%= check_box_tag :approval_check_box, '1' %>
<%= hidden_field_tag :approval_check_box, '0' %>

If the check box was not checked then value in the hidden field would be passed. Ugly, but it worked fine.

But at some point in the move to Rails 2.3.x this hack was turned on its head and the construct show above will now always pass the unchecked value to the server.

The fix is simple - just reverse the two lines:
<%= hidden_field_tag :approval_check_box, '0' %>
<%= check_box_tag :approval_check_box, '1' %>

The real solution if to use a check_box helper where you can explicitly specify the unchecked value, rather than a check_box_tag.

I stumbled across this while updating an older app from Rails 2.2.2 to 2.3.5. It took a while to narrow the issue down to this problem.


Wednesday, February 10, 2010

Rails, Time Zones and the current local time

Since version 2.1 it has been easy to handle user-specific time zones in Rails. Take a look at Railscast #106 for details.

Rails takes care of converting times in your models back and forth from local timezones and UTC in the database and it works great.

But I wanted to put the current local time at the bottom of each page, so that if they printed out the page they had a time stamp right there.

My server is set up to with UTC as its time zone and Rails picks up on that, such that if I simply print out Time.now I get it in UTC, regardless of having set Time.zone to 'US Pacific...', which is not what I want.

Because I'm not accessing the time from a database record, it doesn't apply the user specific conversion.

The way to do this is to add 'in_time_zone' which forces Time to use the current Time.zone.

Bottom Line:

To display the current time in a user's local time zone, use Time.now.in_time_zone


Wednesday, February 3, 2010

Rails, searchlogic and will_paginate

The searchlogic gem, for active record searching, integrates well with will_paginate, for pagination of the results in index pages, and it comes with simple helpers for setting up sortable column headers.

But I had trouble setting the default sort order for the results if not filtering had taken place or if no column header had been clicked. What I found on the web was a little confusing. Here's how it works (as of Feb 2010).

The model has a list of companies and I want the default search order to use their names.

In your controller:

@search = Company.search(params[:search])
@search.order ||= :ascend_by_name
@companies = @search.all.paginate :page => params[:page], :per_page => 20

Note that you set the order in @search and leave out the :order parameter to paginate.

Simple, elegant, love it...


Tuesday, February 2, 2010

Rails, Searchlogic and Dates

I've been using the searchlogic gem from Ben Johnson and its a great way to build complex search forms for your models. Railscast #176 is a great introduction to the topic by Ryan Bates (You can't go wrong with Railscasts!).

One topic missing from the documentation is how searchlogic handles Dates, but the functionality is in there. Here is how you use it.

You treat a date effectively as a number and you can use 'equals', 'gte', 'lte', etc. as comparison operators.

Assuming you have a column named 'date', of type 'date' in your model, you can put something like this in your form:

<%= f.label :date, "Date" %>
<%= f.text_field :date_gte, :size => 12 %> -
<%= f.text_field :date_lte, :size => 12 %>

You can then enter dates into one or both of the fields to retrieve records that fall into that date range.

But what date format should you use? This is where it gets clever. It wants to use YYYY-MM-DD format but if you enter MM/DD/YYYY it accepts is and converts it for you. Brilliant! It even takes text like 'Dec 1 2009' and converts that. Interestingly it won't accept invalid dates like '2009-11-31' and just gives you back the form with the field cleared out.

With a column of type 'Datetime' it converts your entries as well but this time it converts '2010-01-01' into 'Fri Jan 01 00:00:00 -0800 2010'. I'm sure it does something similar with columns of type 'Time'.

Undoubtedly the code is leveraging the Ruby time and date libraries to make the conversions, which can be lifesavers. Incorporating the functionality into searchlogic makes your forms much more tolerant of user inputs and it does so in a totally unobtrusive way.


Archive of Tips