A Lesson From Fixing a Bug

I was looking over my Presidential Data Charts site in order to get it ready for the next president. (No matter what I happen to think of that next president, there will be one.)

And I found an error in my existing code!

One of the drop-down charts is “Length of presidency.” Most of these are four years (1461 days) or eight years (2922 days). The length of Obama’s presidency should appear today as 2908 days (2922 minus the 14 days left in his term). But it was about a year too short. What had happened? I first made these charts a year ago, but somehow Obama’s “length of presidency” had never updated since then.

I eventually realized the problem: I had originally seeded my database incorrectly. In my seeds.rb file, I had scraped all the stats from a Wikipedia chart (using Nokogiri). I scraped the “left office” date for a president from president.elements[5].children[0]. But if a president didn’t have a “left office” date in the chart (i.e. Obama), I had defaulted to today’s date:

president.elements[5].children[0] ? prez.left_office = president.elements[5].children[0].text : prez.left_office = Date.today

What I forgot, of course, is that seeds.rb only runs once. So Obama’s “left office” date was “baked in” a year ago, when I first uploaded the project to Heroku. (I have other code that uses Date.today, but since it’s in a file that runs each time a chart gets displayed, that “today” is always correct.)

It was a simple fix. I changed the above line of code to:

prez.left_office = president.elements[5].children[0].text if president.elements[5].children[0]

Now when seeds.rb runs, a president won’t be given a “left office” date unless there is one.

This led me to simplify my code in another place as well. Previously, I had calculated a president’s retirement_in_days as follows:

def retirement_in_days
  if self.left_office > Date.parse("2009-01-20")
    0
  elsif alive?
    (Date.today - self.left_office).to_i
  else
    (self.death_date - self.left_office).to_i
  end
end

That particular if line, to account for Obama, always bothered me. The date of 2009-01-20 was tailored to Obama, but if you didn’t know that, it would seem arbitrary. And it was brittle, because once Obama left office, it wouldn’t be accurate anymore. But now that I’d just changed the seed file so that a sitting president wasn’t given a left_office attribute, I could change the if line:

def retirement_in_days
  if !self.left_office
    0
  elsif alive?
    (Date.today - self.left_office).to_i
  else
    (self.death_date - self.left_office).to_i
  end
end

0
elsif alive?
(Date.today – self.left_office).to_i
else
(self.death_date – self.left_office).to_i
end

Now that method works for whoever the sitting president happens to be, and it’s one less thing I’ll have to change when the new president takes office.

And the moral is: sometimes, when fixing a bug, it helps you improve other parts of your code!