Constants & Freezing
A constant in Ruby is any name that begins with a capital letter, meant to hold a value you don't intend to change — and freeze is how you make that promise enforceable.
Learn Constants & Freezing in our free Ruby course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Ruby course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You'll learn how constants are named and scoped with :: , why reassignment only warns, and how freeze / frozen? protect against accidental mutation.
What You'll Learn in This Lesson
1️⃣ Naming Constants & the Reassignment Warning
Capitalise the first letter and you've made a constant. Ruby lets you reassign it, but it prints a warning so a real typo doesn't slip by silently. Treat that warning as an error in your own code.
2️⃣ Scoping Constants with ::
Constants belong to the class or module that defines them. From outside, reach them with the scope-resolution operator :: , as in Config::TIMEOUT . A leading :: (like ::GREETING ) jumps straight to the top-level constant, skipping any nested one with the same name.
3️⃣ freeze, frozen?, and the Mutable Gotcha
freeze makes an object immutable; any mutation afterwards raises FrozenError . Symbols, numbers, true , false and nil are always frozen. Use frozen? to check.
Two traps to remember: freeze is shallow (the container is frozen, the items inside are not), and a constant that points at a mutable object can be changed in place with no warning at all . Freezing the value closes that loophole.
For whole files, the frozen_string_literal magic comment freezes every string literal automatically — common in real projects and gems.
🎯 Your Turn
Replace the ___ so the constant is frozen and mutating it raises a FrozenError .
Build a small configuration module whose constants are genuinely immutable. Run with ruby app_config.rb .
📋 Quick Reference — Constants & Freezing
Practice quiz
What makes a name a constant in Ruby?
- Prefixing it with $
- Using the const keyword
- Beginning the name with a capital letter
- Wrapping it in ALL_CAPS quotes
Answer: Beginning the name with a capital letter. Any identifier starting with an uppercase letter is a constant — that's why class names are constants too.
What happens when you reassign an existing constant, like PI = 3.14?
- Ruby prints an 'already initialized constant' warning but allows it
- Ruby raises an error and stops
- It silently changes with no notice
- The program freezes
Answer: Ruby prints an 'already initialized constant' warning but allows it. Constants are constant by convention; reassigning only warns, it doesn't raise.
How do you access a constant TIMEOUT defined inside module Config from outside?
- Config.TIMEOUT
- Config->TIMEOUT
- Config@TIMEOUT
- Config::TIMEOUT
Answer: Config::TIMEOUT. Use the scope-resolution operator ::, as in Config::TIMEOUT.
What does a LEADING :: mean, as in ::GREETING?
- The nearest nested constant
- The top-level (global) constant, skipping nested ones
- A frozen constant
- A syntax error
Answer: The top-level (global) constant, skipping nested ones. A leading :: jumps straight to the top-level constant, bypassing any nested one of the same name.
After name = "Ruby".freeze, what does name << "!" raise?
- FrozenError
- NoMethodError
- ArgumentError
- Nothing — it appends fine
Answer: FrozenError. Mutating a frozen object raises FrozenError (can't modify frozen String).
Which of these is ALWAYS frozen automatically in Ruby?
- Every Array
- Every String
- Symbols, integers, true, false, and nil
- Every Hash
Answer: Symbols, integers, true, false, and nil. Symbols, integers, floats, true, false and nil are frozen by default; arrays/strings are not.
freeze is described as 'shallow'. What does that mean?
- It only works on small objects
- Freezing a container doesn't freeze the objects inside it
- It freezes only the first character of a string
- It can be undone with thaw
Answer: Freezing a container doesn't freeze the objects inside it. Freezing an array stops push/pop, but its elements stay mutable unless you freeze them too.
Why is SETTINGS = { retries: 3 }; SETTINGS[:retries] = 99 a dangerous 'gotcha'?
- It raises FrozenError
- It deletes the constant
- It prints two warnings
- It mutates the constant's value in place with NO warning at all
Answer: It mutates the constant's value in place with NO warning at all. Mutating (not reassigning) a constant's object dodges the warning entirely — freeze the value to prevent it.
What does the # frozen_string_literal: true magic comment do?
- Freezes every variable in the file
- Makes every string literal in that file frozen by default
- Disables warnings
- Speeds up file loading only
Answer: Makes every string literal in that file frozen by default. Placed on line one, it freezes all string literals in the file, saving memory and catching mutation.
Which method checks whether an object is already frozen?
- object.freeze?
- object.is_frozen
- object.frozen?
- frozen(object)
Answer: object.frozen?. frozen? returns true if the object has been frozen.