When chaining assume each object could be nil unless explicitly ruled out

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

Last Updated: 2024-11-21

I wrote the following code in a controller:

@order = current_order(create_order_if_necessary: false)
@special_offer = BundleProduct.includes(individual_products: :subject).find(@order.special_offer.id)

Under tests, it blew up.

For one, there may not be an @order. For two, even when there is an @order, there may not be an @order.special_offer, therefore @order.special_offer.id could blow up in this case.

The fix:

@order = current_order(create_order_if_necessary: false)

if @order && @order.special_offer
  @special_offer = BundleProduct.includes(individual_products: :subject).find(@order.special_offer.id)
end

Lesson

When looking for dot chains that potentially contain nulls, consider not only the main chain, but also any chains passed in as arguments (e.g. here ...find(@order.special_offer.id))