Sunday, May 20, 2007

Can you spot the bug?

In a model class which has 'quantity', 'quantity_already_taken' and 'quantity_requested' properties, I add the following:

def before_save
quantity = 1 if quantity == 0
if quantity + quantity_already_taken > quantity_requested

Tests blow up everywhere with:

TypeError: nil can't be coerced into Fixnum
(on the line with the addition)


After a little more debugging, it is clear that 'quantity' is nil. How could that happen?

The answer lies in the fact that Ruby requires an explicit self reference when using attribute writers (aka, property setters) within the class itself. This feels clunky to me, but for your information, here's a rationalisation of the explicit self requirement.

So, in case you're wondering, what happened above is that the 'if' line created a nil local variable called 'quantity'! This local variable then had higher scope precedence than the class attribute with the same name. The addition line was then using the local 'quantity' rather than the class attribute and hence failed with the nil error.

All fixed by explicity referencing self:

def before_save
self.quantity = 1 if (quantity == 0)
if quantity + quantity_already_taken > quantity_requested

Friday, May 18, 2007

Fixing a Palm Treo's Digitizer (Touch Screen)

Let me tell you a sad tale. One day, out of the blue, the digitizer on my palm started to drift. Every hour, it got worse. This meant that when you tried to click a button like 'Add' the Palm thought you clicked 'Delete' - no fun at all! It was possible to temporarily improve the situation by running the re-calibration program built into the system, but within a few hours, where you clicked again had very little relation to where the Palm thought you had clicked. After about a week, it was not possible to run the re-calibration program, as the digitizer was so far out (program just looped forever so I had to reboot the Palm). I discovered that there are actually keyboard shortcuts for just about everything, and that the 4-way nav button gets you most places, so the device wasn't a total write off. However, it was slow and cumbersome to use.

Now, one month later, I'm sure you'll be thrilled to know that things are better, the sorry tale has had a happy ending (touch wood!). Much googling led to many suggested approaches to fixing the problem including:
  • Various auto-calibration programs (AutoDigi, DigiFix, etc).
  • Running paper around the screen under the casing to remove gunk.
  • Cleaning the insides by putting a vacuum cleaner to all openings.
However, all of these approaches ended with disappointment and no noticeable improvement.

Finally, near buying myself a new device (aside: it is a shame that Palm has not managed to produce a device significantly better than my several year old Treo 600), I came across a site selling replacement Treo 600 digitizer/screen modules. They kindly provide a very useful movie on pulling your Treo apart to help you replace your digitizer/screen module. With little to lose, I decided to open up the case of my Treo and see if there was anything I could fix.

Following the instructions in the movie was not too difficult. I didn't have a small star alan key myself (required for opening the case), but I borrowed one from my dear dad, who has an amazing tool collection. Also, lacking a plastic case opening tool, I used a butter knife - this worked OK, but did damage the plastic of the case a little. If you have something made from thin and strong plastic, like the case opener in the movie, it would be a better tool for the job. I had a great time pulling everything apart and finally had all the components spread out before me. I cleaned the screen carefully (there was a fair bit of grot around the edges), fixed the buckled taping on the side of the screen, and put everything back together, carefully re-seating the various cables.

And now, almost a month later, the digitizer still seems to be working fine! Hurrah! So if you are contemplating what to do about your Palm's broken or drifting digitizer, I recommend pull it apart, clean it all and re-seat cables and then hope for the best!