Watch out for converting nil and empty string to numbers

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the types category.

Last Updated: 2024-04-25

I had the following code for handling refunds:

refund_instructions.map do |line_item_id, amount_to_refund|
  [
    LineItem.find(line_item_id).purchasable,
    BigDecimal(amount_to_refund)
  ]
end

On the front-end was a form where you see all the various line-items and you input the amounts you are supposed to refund for each of the potentially many line items in the order.

When the form is submitted, it is treated as collection of strings by Ruby on Rails, eventually ending up as the refund_instructions variable.

The input field corresponding to amount_to_refund defaults to "0.0" in the front-end form, so this default was what usually got passed to the backend.

But one time I erased the 0.0, causing "" (blank string) to be submitted by the form. This triggered the bug... it had never been tested after a user deleted the form default.

The cause of the bug was that BigDecimal is fussy about the conversions it can handle. This follows on from Ruby being strongly typed.

Generally I should never assume that a number converter knows what to do with blank strings or nils. Always test.

[
  LineItem.find(line_item_id).purchasable,
  BigDecimal(amount_to_refund.blank? ? 0 : amount_to_refund)
]

Lessons