Ruby Fleebie

Rediscovering the joy of programming

Make sure you are not using methods like “1.day.ago” when dealing with a Date column

TL;DR: Read the title ;)

I spent too many hours debugging a feature spec in an application. Turns out I was simply not paying attention to what I was doing!

In a fixture file, I was setting a field the following way:

some_date: <%=1.day.ago.to_s :db%>

I didn’t pay attention to the fact that “some_date” was a Date and not a DateTime. This single line was responsible for some intermittent failures in my test suite.

The technical explanation
The problem is that methods like “days.ago” return ActiveSupport:TimeWithZone objects which contain, well, the time portion along with the current timezone info. Then there is the to_s(:db) part which convert the resulting DateTime in UTC for storage in the DB. It means that if I call “1.day.ago.to_s :db” on september 7th at 8:00 PM (local timezone, which is UTC -4 for me), the result will be “2014-09-07 00:00:00″ UTC time. And since I was storing this in a Date column, the time portion would simply gets discarded… so I ended up with a date of September 7th instead of the expected September 6th in the DB.

Solution
Of course this problem was very easy to fix once I understood what was causing it. I simply changed the fixture file so that it looks like:

some_date: <%=1.day.ago.to_date.to_s :db%>

This works as well:

some_date: <%=Date.yesterday.to_s :db%>

Hoping this will save others some painful debugging!

Run bundle install with the –binstubs option

It’s been a little while that I have decided to always extract my gem binaries into my rails application “bin” path. That way, I always execute binaries by specifying the relative path. For example “./bin/rails g model User”. At first I wasn’t sure about the idea. I was like: “Wait a minute! I will have to type “./bin/” all the time?! It will get annoying really fast!”. This turned to be an unfounded fear. Having to type “./bin/rails” or “./bin/rake” is a good thing and it feels really natural. When you do this, there is no magic involved: you know exactly WHICH binary is going to be executed.

Isn’t it exactly like typing “bundle exec” ?

Yes, you’re right… it’s more or less the same thing. But I find that having to type “./bin/” is even more obvious. Believe me, you will get the hang of it quickly. Anyway, with TAB completion, it’s not like you have to type “./bin” really. It will look more like “./b” then TAB. It becomes second nature really fast.

Wow! This is the discovery of the century! I’m sold, how can I do this ? (end sarcasm)

Whenever you update your Gemfile, you do

bundle –binstubs

Nested has_many :through

Hi (Oh my God… he just started his blog post with ‘Hi’),

Did you know that as of Rails 3.1, you can have nested has_many :through clauses in your models? Here is a concrete example to understand what I mean:

  class SportSchedule < ActiveRecord::Base
    has_many :gamedays
    has_many :games, :through => :gamedays
    has_many :results, :through => :games # <= You could not do this before Rails 3.1

   ...
   def has_results?
     !self.results.empty?
   end
  end