Ruby’s constants are somewhat of an entertaining surprise if you have never dug into this subject before, or seen Ruby at all. See, unlike many other languages, constants in Ruby are not really enforced to stay constant during the program runtime. Wait, what?

If you try to re-assign the constant, you will get a warning though:

But, as you can see, A ‘s value has not remained constant, instead of [1], we get [2].

Even for the warning, there’s a workaround:

The two operations are different though, as in the first gist we are assigning entirely new object to the constant A, while in the latter example we are pushing new object to an existing array. We are not going to cover locking constant names to a certain object, thus blocking them from any re-assignments, we’ll focus on object changes instead.

The solution will give you the chills.

Say hi to .freeze

.freeze allows you to enforce immutability on mutable objects. Since constant doesn’t force immutability on its value, you need to declare it explicitly, like this:

Okay, but what does it mean?

Freezing means enforcing immutability. I think that the easiest example is the array one.

Consider having an Array object under the constant named A. You are still able to modify value of this constant without any warnings, using the append method ( << ).

This works because technically the A constant has not been re-assigned. It is the content of the object that has changed, but not the object itself. A proof of this is the object_id :

Immutability allows us to lock a certain object from any changes. On attempts of changing content of a frozen object, Ruby will throw a FrozenError :

Freeze all the things!

Yes. See, freezing everything around is not really a bad thing. Actually it makes constants closer to what we would expect — a named value that should not / can not be changed like any other ordinary variable.