Ruby Symbols

Efficient immutable identifiers in Ruby

🔖 What are Ruby Symbols?

Symbols are immutable, reusable identifiers prefixed with a colon (:). They're more memory-efficient than strings because each symbol is stored only once in memory, making them perfect for hash keys and constants.


# Creating symbols
name = :john
status = :active

puts name    # Output: john
puts status  # Output: active
                                    

Output:

john

active

Symbol Concepts

Memory Efficient

Stored once in memory

:name.object_id
:name.object_id
# Same ID!
🔒

Immutable

Cannot be changed

sym = :hello
# sym cannot be modified
🗝️

Hash Keys

Perfect for hash keys

user = { name: "Bob" }
puts user[:name]
🔄

Conversion

Convert to/from strings

:hello.to_s
"hello".to_sym

🔹 Creating Symbols

Symbols are created by prefixing a name with a colon. They look like variables but behave differently. Once created, a symbol with the same name always refers to the same object in memory, unlike strings which create new objects each time.

# Simple symbols
first_name = :john
last_name = :doe
status = :active

# Symbols with underscores
user_type = :admin
is_verified = :true

# Symbols in arrays
colors = [:red, :green, :blue]

puts first_name      # Output: john
puts colors[0]       # Output: red
                            

Output:

john

red

🔹 Symbols vs Strings

Symbols and strings may look similar but have key differences. Strings are mutable and create new objects each time, while symbols are immutable and reuse the same object. This makes symbols faster and more memory-efficient for identifiers and hash keys.

# Strings create new objects
string1 = "hello"
string2 = "hello"
puts string1.object_id == string2.object_id  # Output: false

# Symbols reuse the same object
symbol1 = :hello
symbol2 = :hello
puts symbol1.object_id == symbol2.object_id  # Output: true

# Memory comparison
puts "hello".object_id   # Different each time
puts "hello".object_id   # Different ID
puts :hello.object_id    # Same each time
puts :hello.object_id    # Same ID
                            

Output:

false

true

🔹 Symbols as Hash Keys

Symbols are the preferred choice for hash keys in Ruby because they're faster to compare and use less memory. Modern Ruby syntax allows you to write symbol keys without the hash rocket (=>), making code cleaner and more readable.

# Old syntax with hash rocket
person = { :name => "Alice", :age => 25 }

# Modern syntax (preferred)
person = { name: "Alice", age: 25, city: "Boston" }

# Accessing values
puts person[:name]   # Output: Alice
puts person[:age]    # Output: 25

# Mixed example
config = {
  host: "localhost",
  port: 3000,
  debug: true
}

puts config[:host]   # Output: localhost
                            

Output:

Alice

25

localhost

🔹 Converting Between Symbols and Strings

Ruby provides simple methods to convert between symbols and strings. Use to_s to convert a symbol to a string, and to_sym or intern to convert a string to a symbol. This is useful when working with user input or external data.

# Symbol to string
symbol = :hello
string = symbol.to_s
puts string              # Output: hello
puts string.class        # Output: String

# String to symbol
text = "world"
sym = text.to_sym
puts sym                 # Output: world
puts sym.class           # Output: Symbol

# Alternative method
sym2 = "ruby".intern
puts sym2                # Output: ruby

# Practical example
user_input = "name"
hash_key = user_input.to_sym
person = { name: "Bob" }
puts person[hash_key]    # Output: Bob
                            

Output:

hello

String

world

Symbol

ruby

Bob

🔹 When to Use Symbols

Use symbols for identifiers that won't change, like hash keys, method names, or status values. Use strings for text that might be modified or displayed to users. Symbols are ideal for internal code labels, while strings are better for user-facing content.

# Good use of symbols
user = {
  name: "Alice",        # Symbol key
  role: :admin,         # Symbol value for status
  status: :active
}

# Good use of strings
message = "Hello, #{user[:name]}!"  # String for display
puts message                         # Output: Hello, Alice!

# Symbols for method parameters
def greet(person:, greeting: :formal)
  if greeting == :formal
    puts "Good day, #{person}"
  else
    puts "Hey #{person}!"
  end
end

greet(person: "Bob", greeting: :casual)  # Output: Hey Bob!
                            

Output:

Hello, Alice!

Hey Bob!

🧠 Test Your Knowledge

What is the main advantage of using symbols over strings?