Consider the following
Connection class, defined using the
Straightforward, right? Here’s where things get interesting.
What just happened?
The answer to this riddle has to do with
Struct.new. As it turns out, calling
Struct.new and passing a block does not create a new scope as far as constants are concerned. In other words, while the indentation implies that
DEBUG is contained within the scope of
Connection, in truth
DEBUG gets registered as a global constant.
So as far as Ruby is concerned, what we actually declared was this:
Later when we write
Connection::DEBUG = true, what do we really mean? This is where Ruby 1.9.2 and 1.9.3 diverge.
In Ruby 1.9.2, the interpreter assumes you meant to write
DEBUG = true and changes the global constant. This behavior is arguably a bug.
Ruby 1.9.3 “corrects” this behavior. It interprets
Connection::DEBUG = true to mean “create a brand new constant named
Connection::DEBUG and assign it to true”. And so the global
DEBUG remains unchanged.
Now the results make sense:
Now that we know what’s going on, how would we change the code to make it less ambiguous?
One option is to expicitly declare the scope of the constant, like this:
The best approach is to probably drop the
Struct.new fanciness and just use a simple class:
Have something else to add? Contribute your ideas to the Gist for this post at GitHub.comments powered by Disqus