Constants in Ruby
A constant in Ruby is any kind of variable whose name begins with an uppercase letter (A-Z). Constants are typically assumed to have values that remain unchanged while the program runs, much like “final” variables in other languages. Class and module names themselves are considered constants, in addition to expressly defined constants.
Naming Conventions
Although any identifier that begins with a capital letter is always used, some naming conventions are dictated by common practice:
General Constants: The standard way to write constants is with all capital letters and underscores to separate terms (LIKE_THIS, MY_CONSTANT, etc.). It is seen to be a best practice.
Class and Module Names: These are typically written in camel case with initial capital letters (e.g., MyClass, ConstModule).
Reassignment and Mutability
Ruby takes a more relaxed stance on constants than some other languages:
Warning, Not Error: Ruby will display an error message but still carry out the assignment if you try to reassign a different value to a constant that has already been initialized. A constant cannot be completely prevented from being altered.
Object Modification: You can change an object’s internal state without raising an error if a constant points to a mutable object (such as a string or array). By making the object immutable through the use of the.freeze method, this can be avoided.
Cannot Be Defined in Methods: The body of a method cannot define constants. This is because reassigning a constant repeatedly would result in warnings on each subsequent call once Ruby assumes that methods may be invoked many times.
Scope and Access
Generally speaking, constants are accessible from anywhere in a Ruby program due to their global visibility. Nevertheless, they can also be localised to create namespaces inside classes and modules:
Unqualified Access: An unqualified, straightforward name can be used to refer to a constant inside the class or module in which it is defined.
Qualified Access: A constant can be referenced outside of its defining class or module by using the double-colon operator (::
). For example, Point::ORIGIN, MyModule::MODULE_CONST
, or any other class or module name that comes before :: indicates the location of the constant. Another way to avoid naming clashes is to use modules as namespaces.
Global Scope: The Object class is implicitly meant to be looked up in the global scope if the left-hand side of :: is left out (for example, ::ARGV).
Lookup Algorithm: Ruby uses a particular resolution technique when a constant is referred without a qualifying namespace:
- The present class or module and its enclosing ones are the first lexically enclosing scopes that are searched. You can see this search path in Module.nesting.
- It then looks via the enclosing class or module’s inheritance structure if it cannot be discovered lexically.
- Lastly, top-level constant definitions (those found in Object) are checked. The modules that a class includes are searched before its superclass, and constants declared in enclosing modules are retrieved first.
Initialization and Uninitialized Constants
- A constant isn’t formed by a non-evaluated expression; they don’t exist until a value is actually given to them.
- A NameError exception will be raised when an uninitialized constant is attempted to be accessed.
- The value nil will only be allocated to a constant if it is expressly assigned to it.
- In order to enable dynamic or lazy constant initialisation, the const_missing method (if specified in a module) is a hook that is called whenever a reference is made to an undefined constant.
Predefined Constants
Ruby predefines several useful constants upon startup, such as ARGF
, ARGV
(command-line arguments), DATA
(for data after __END__
in a script), STDERR
, STDIN
, STDOUT
(standard I/O streams), TOPLEVEL_BINDING
(top-level scope binding), __FILE__
(current file path), and __LINE__
(current line number).
Code Examples: Basic Constant Definition and Reassignment Warning
# Global constant
GLOBAL_MESSAGE = "Hello, Ruby world!"
puts GLOBAL_MESSAGE # => Hello, Ruby world!
# Reassigning a constant generates a warning
GLOBAL_MESSAGE = "Updated message."
puts GLOBAL_MESSAGE # => Updated message.
# (warning: already initialized constant GLOBAL_MESSAGE)
Output
Hello, Ruby world!
main.rb:6: warning: already initialized constant GLOBAL_MESSAGE
main.rb:2: warning: previous definition of GLOBAL_MESSAGE was here
Updated message.