Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
Years ago I was working on a very large Ruby on Rails codebase that used constants to hold lists of credit card transaction states. For example:
# example 1class Txn ACTIONABLE_STATES = [:authenticated, :to_settle] DONE_STATES = [:settled, :declined]
# ...end
However, we had a bug in which a settled transaction could pass a txn.state.in? ACTIONABLE_STATES check. After hours of searching, we found the offending code in a completely different part of the codebase.
# example 2all_states = ACTIONABLE_STATES.concat(DONE_STATES)all_states.each do |state| # ...end
If you’re already knowledgeable of the Ruby Array class, you’ve probably spotted the offending line already. #concat mutates the original list, even though it doesn’t end with the idiomatic !, and because ACTIONABLE_STATES is held statically in memory, when this code gets executed it changes ACTIONABLE_STATES state for the rest of that Ruby virtual machine’s life.
In other words, after example 2 gets executed, ACTIONABLE_STATES becomes[:authenticated, :to_settle, :settled, :declined] until you reboot the server.
If you have multiple Ruby boxes running behind a Load Balancer (as we did), this can further obfuscate the problem. Because example 2 might only have been run on certain boxes, you might get cases where one request will not exhibit the bug while another identical one will.
The solution? Freeze your constants.
# example 3ACTIONABLE_STATES = [:authenticated, :to_settle].freezeDONE_STATES = [:settled, :declined].freeze
This would cause example 2 to produce a can't modify frozen array (RuntimeError), and if you’ve unit tested example 2, you would’ve hopefully caught this before it was ever even deployed.
Freeze Your Constants in Ruby was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.