An intro video to Ruby constants their enforcement pitfalls and how to fix them and why you should care in your code.

In computer programming, a constant is a value that cannot be altered by the program during normal execution, i.e., the value is constant. - Wikipedia

This is what happens in Ruby when redefining a constant with another object.

A_CONST = :first_value A_CONST = :new_value

It outputs a warning.

warning: already initialized constant A_CONST

If you’re not paying attention to warnings in Ruby then enforcing constants is not possible. I would recommend that you listen to this warning and fix them when they come up.

If the constant is attempted to be reassigned dynamically for example with a method this is not just a warning, but a syntax error.

def hello A_CONST = 2 end SyntaxError : dynamic constant assignment A_CONST = 2 ^

It can still be done dynamically it just needs different syntax, but this will also produce a runtime warning.

Object . const_set ( :A_CONST , 3 ) warning: already initialized constant A_CONST warning: previous definition of A_CONST was here

When Warnings Are Not Enough

COMPANY_OWNER = "Dustin Zeisler"

What happens when some code is written while not paying attention and does a destructive action on the String?

COMPANY_OWNER . gsub! ( "i" , "" ) #=> "Dustn Zesler" COMPANY_OWNER #=> "Dustn Zesler"

The String object is still technically the same object, so no Ruby warnings will happen. This does not meet the expectation of what a constant value should be. Is there anything that we can do about it? Glad you asked this is where #freeze comes in.

COMPANY_OWNER = "Dustin Zeisler" . freeze COMPANY_OWNER . frozen? #=> true COMPANY_OWNER . gsub! ( "i" , "" ) RuntimeError : can ' t modify frozen String

If this is not a common mistake you feel you are going to make it also has performance improvements, see www.sitepoint.com/unraveling-string-key-performance-ruby-2-2.

Note: Alternative for String#freeze

With the release of Ruby 2.3, strings can be frozen by default without the use of #freeze. By adding the following magic comment at the top of a file all string literals will default to frozen. til.hashrocket.com

# frozen_string_literal: true

Other common mutable objects in Ruby are Hash and Array. If these objects are being set as a constant I would recommend also freezing them.

There is no built-in way to unfreeze an object, but if you really want to here is a StackOverflow post on how to do it.

If you like this sort of thing subscribe to get new posts delivered directly to your inbox.