Constants, globals and scope
Constants and the warning
A name that starts with a capital is a constant: Ruby lets a program assign it once and warns when a second assignment replaces the value. The warning is the feature; the program keeps running with the new value.
ruby -e 'X = 1; X = 2; puts X'
-e:1: warning: already initialized constant X
-e:1: warning: previous definition of X was here
2
The lookup goes outward: a constant written inside a class is looked up in the class, then in the enclosing modules, then at the top level. That is why VERSION inside a gem module finds the constant of the module and not one from another gem with the same name.
The globals Ruby defines
Ruby has a handful of global variables that are always there. The four a script uses:
- $PROGRAM_NAME (also $0): the file that was run, or -e for a one-liner.
- $LOAD_PATH: the folders a require searches.
- $stdout, $stderr: the two output streams, which a test can replace to capture output.
- $!: the last exception raised, the one rescue without an argument reads.
ruby -e 'puts $PROGRAM_NAME; puts $0 == $PROGRAM_NAME'
-e
true
Write your own globals only in a scratch script. A library that sets $verbose or $debug changes the behaviour of everything that shares the process, and a name collision is impossible to see in a diff.
ENV is not a global
Environment variables look like globals and are not: they live in the process environment and Ruby exposes them through the ENV object, which is a hash-like constant.
ruby -e 'puts ENV.fetch("HOME")'
/home/agent
fetch raises when the variable is missing, which is what a required setting wants. ENV["MODE"] returns nil instead, and ENV.fetch("MODE", "development") gives a default. Lesson 40, later in the course, has the whole configuration lesson.
What to watch for
A constant is not frozen: COLORS = [] can still
be pushed to, and every caller sees the change. Freeze the value when it
is meant to be read-only, as in lesson 88.
The reassignment warning appears with -w or by
default in most setups. Do not silence it with
Warning[:deprecated] tricks; a second assignment
to a constant is almost always a bug or a rename that missed a line.
Next: Random numbers, ids and tokens
Article author: Arthur Isaev