Everything You Need to Know About Ruby Constants

What is a constant in Ruby?

A constant is a type of variable which always starts with a capital letter. They can only be defined outside of methods, unless you use metaprogramming.

Constants are used for values that aren’t supposed to change, but Ruby doesn’t prevent you from changing them.

They look like this:

FRUIT = "orange"

Now:

Because constants are an important topic we’re going to explore them in detail in this article!

How to Define Constants

A constant doesn’t require any special symbol or syntax to declare. You just need to make the first letter an uppercase letter.

The following are valid constants:

ABC = 1
Goo = 2
Foo = 3

Notice that you can’t define constants inside a method.

You will get this cryptic error message:

def the_method
  ABC = 1
end

# "dynamic constant assignment"

So just define your constants outside methods, typically we want to have constant definitions at the top of your class so they are clearly visible.

class RubyBlog
  URL    = "rubyguides.com"
  AUTHOR = "Jesus Castello"
end

You can then access these constants inside the class methods or outside the class using the following syntax:

p RubyBlog::AUTHOR

# "Jesus Castello"

We are going to talk a bit more about the scope of constants later in this post, so stay tuned for that!

Uninitialized Constant Error

One common error that you may get is this:

puts Foo
# "uninitialized constant Foo (NameError)"

I want you to mentally translate this error to “constant not found”.

One important point to understand this error is that Ruby classes are constants.

Examples:

Array
String
Hash

They are constants because the first letter is uppercase.

When you define a class, what you’re really doing is creating a Class object, which is assigned to a constant.

The constant becomes the class name.

Why is this important?

Because the most likely reason that you are seeing an “uninitialized constant” error is that you forgot to require a file or gem that defines the constant.

Or maybe you just misspelled the name of the constant.

So keep an eye open for that.

Constants Can Change

Like I mentioned in the introduction, Ruby constants can change.

Example:

ABC = 1
ABC = 2

But you will see this warning message:

2: warning: already initialized constant ABC

Your program will still work fine, but you want to avoid this.

There is no way to prevent a constant from changing because variables in Ruby are not containers, they are simply pointers to objects.

Or labels, if you prefer.

The best you can do is to use immutable objects.

Example:

AUTHOR = "Jesus Castello".freeze

AUTHOR << "o"
# RuntimeError: can't modify frozen String

Related article: Ruby mutability & the freeze method.

In this example, you can still change what the AUTHOR constant is pointing to, the only thing freeze protects you from is from changing the object itself.

Constant Methods

There are a few methods dedicated to working with constants:

MethodDescription
constantsReturns an array of symbols that represent the constants defined in a class
const_get Returns value for a constant. Takes a symbol or string as parameter
const_setSets the value for a constant. Takes two parameters: constant name as a symbol & constant value
const_missing Same as method_missing but for constants
const_defined?Returns true if a given constant (as a symbol) has been defined
remove_const Removes a constant
private_constantMakes a constant private so it can’t be accessed outside the class with Class::ABC syntax

There are a few metaprogramming tricks you can do using these methods.

Example:

module Food
  class Bacon; end
  class Chocolate; end
end

puts "Classes defined inside #{Food}:"

puts Food.constants

Also you can use a string like “Array” & get the actual class:

array_class = Object.const_get("Array")

But be careful with that one because a user could inject code if the string is coming from params or some other form of user input.

In Rails, there is the constantize method which basically does const_get for you, but keep in mind that it doesn’t do any security checks.

CheatSheet

Ruby Constants CheatSheet

Ruby Constant Scope

When you create a constant outside of any class, at the top-level of your code, that constant will be available anywhere.

Constants are also available in child classes.

class A
  FOO = 1
end

class B < A
  def foo
    puts FOO
  end
end

B.constants

# [:FOO]

Constants defined outside a nested module or class are also available inside the nested classes.

module Food
  STORE_ADDRESS = "The moon"

  class Bacon
    def foo; puts STORE_ADDRESS; end
  end
end

fb = Food::Bacon.new
fb.foo

# "The moon"

Module Mixing

Constants from mixed-in modules are also available:

module Mixin
  A = 123
end

class Product
  include Mixin

  puts A
end

# 123

Notice that this works when including the module, it won’t work if you are extending it.

Example:

class Product
  extend Mixin

  puts A
end

#  uninitialized constant Product::A

Also:

When you use a method that has been included from a module, Ruby will look for constants starting where that method is defined.

Example:

module Parent
  def print_value
    VALUE
  end
end

class Child
  include Parent

  VALUE = 1
end

# Works
p Child::VALUE

# uninitialized constant Parent::VALUE
p Child.new.print_value

Something to keep in mind!

Module Nesting

I want to show you one more example with nested classes (same for modules).

class A
  FOO = 1
end

class A::B
  class C
    puts FOO
  end
end

Notice the A::B notation here, which we tried to use as a shortcut. But the problem is that class C won’t have access to FOO directly.

For that reason, you want to stick to this kind of nesting:

class A
  FOO = 1
end

class A
  class B
    class C
      puts FOO
    end
  end
end

In the first example, you can still do ::A::FOO to access the constant, but if the class name changes then you will get an error.

This ::A::FOO syntax works because it tells Ruby to look in the top-level scope, where constants like Array & String are defined.

Video

Summary

You learned about Ruby constants, a type of variable which has some interesting behavior. You can change the value of a constant but it will print a warning.

You also learned that class names are constants & that you should avoid const_get with user input.

If you enjoyed this post don’t forget to share it so more people can understand how constants work.

2 thoughts on “Everything You Need to Know About Ruby Constants”

  1. Thanks for your post!

    I just wanted to point out that it is possible to access a child-defined constant from the parent by prepending self.class:: to the constant:

    module Parent
      def print_value
        self.class::VALUE
      end
    end
    
    class Child
      include Parent
    
    VALUE = 1
    end
    

    Works

    p Child::VALUE

    Also works

    p Child.new.print_value

Comments are closed.