Strings & Symbols

Reviewed & published by Brayan K

Ruby is a dynamic, beginner-friendly programming language, and text is everywhere in real programs — Strings hold readable text while Symbols are fast, immutable labels.

Part of the free Ruby course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

By the end of this lesson you'll build and transform strings, use interpolation, and understand exactly when to reach for a symbol instead.

What You'll Learn in This Lesson

1️⃣ Working with Strings

Strings hold text. The friendliest way to build them is interpolation: inside double quotes, #{...} runs Ruby code and inserts the result. Because a String is an object, it comes with dozens of useful methods you call with a dot.

# Strings hold text. Use double quotes when you want interpolation.
greeting = "Hello"
name = "World"

# Interpolation: #{...} runs Ruby code and drops the result into the string.
puts "#{greeting}, #{name}!"        # -> Hello, World!

# Concatenation joins strings with +
puts greeting + ", " + name + "!"   # -> Hello, World!

# Handy String methods (everything is an object!):
puts "ruby".upcase                  # -> RUBY
puts "RUBY".downcase                # -> ruby
puts "  trim me  ".strip            # -> trim me
puts "hello".length                 # -> 5
puts "hello".reverse                # -> olleh
puts "banana".include?("nan")       # -> true
puts "a-b-c".split("-").inspect     # -> ["a", "b", "c"]

We used .inspect on the split result so you can see the array with its brackets and quotes clearly.

String Interpolation in Ruby: The Complete Rules

Interpolation is the piece beginners hit a wall on, almost always for the same reason: it only works inside double quotes. Single quotes are literal, so the placeholder prints as-is rather than being replaced. Every line below is real output from Ruby 3.3:

Three rules that save most of the remaining confusion:

Heredocs follow the same double/single-quote logic. A plain <<~EOS interpolates; quoting the terminator as <<~'EOS' turns the whole block literal — which is exactly what you want when writing out a template, a shell script or documentation that contains #{...} you do not want evaluated.

2️⃣ Symbols: Lightweight Labels

A Symbol is written with a leading colon, like :active. Think of it as a fixed name rather than editable text. Its superpower is identity: every mention of :active is the same object, so symbols are fast to compare and cheap to reuse. You'll see them constantly as hash keys and status flags.

# A Symbol looks like :name — a lightweight, immutable label.
# Symbols are often used as keys and identifiers, not as text to display.

status = :active
puts status            # -> active
puts status.class      # -> Symbol

# Why symbols? The SAME symbol is the SAME object every time,
# so they are fast and memory-friendly. Two strings are different objects;
# two identical symbols are literally the same object.
puts ("hi".object_id == "hi".object_id)   # -> false (two String objects)
puts (:hi.object_id == :hi.object_id)     # -> true  (one Symbol object)

# Convert between them when needed:
puts "active".to_sym.inspect   # -> :active
puts :active.to_s              # -> active

Your turn. Build an ID badge that mixes strings and a symbol. Replace the three TODO values, then run it.

# 🎯 YOUR TURN — replace each ___, then run with: ruby badge.rb

first = ___        # 👉 replace ___ with "Grace"
last  = ___        # 👉 replace ___ with "Hopper"
role  = ___        # 👉 replace ___ with :admin

# 1) Build a full name with interpolation
full_name = "#{first} #{last}"

# 2) Print a badge line. Notice role is a symbol, so use to_s when displaying.
puts "Name: #{full_name}"
puts "Role: #{role.to_s.upcase}"
puts "Initials: #{first[0]}#{last[0]}"   # [0] grabs the first character

# ✅ Expected output (for Grace Hopper, :admin):
#    Name: Grace Hopper
#    Role: ADMIN
#    Initials: GH

Mini-Challenge: A Slug Maker

Turn a title into a URL-friendly slug using downcase and gsub. Run it with ruby slug.rb.

# 🎯 MINI-CHALLENGE: a slug maker.
# Save as slug.rb and run with: ruby slug.rb
#
# A "slug" is a URL-friendly version of a title.
# 1. Start with a title String, e.g. "Learn Ruby Fast"
# 2. Downcase it.
# 3. Replace spaces with dashes using .gsub(" ", "-")
# 4. Print the original and the slug.
#
# ✅ Example output:
#    Title: Learn Ruby Fast
#    Slug:  learn-ruby-fast

# your code here

Common Errors (and the fix)

Pro Tips

📋 Quick Reference — Strings & Symbols

ConceptRuby Syntax
Interpolate"Hi #{name}"
Concatenate"a" + "b"
Upcase / strips.upcase / s.strip
Split / joins.split(",")
Replace alls.gsub("a","b")
String to symbol"a".to_sym

🎉 Lesson Complete!

Practice quiz

How is a Symbol written in Ruby?

  • With double quotes
  • With single quotes
  • With a leading colon, like :name
  • With a trailing colon

Answer: With a leading colon, like :name. A Symbol is written with a leading colon, such as :name or :active.

Why are two identical symbols faster to compare than two identical strings?

  • Every reference to the same symbol is the SAME object
  • Symbols are sorted
  • Symbols are shorter
  • Strings are not comparable

Answer: Every reference to the same symbol is the SAME object. Each identical symbol is literally the same object in memory, so comparison and storage are cheap.

What does "hi".object_id == "hi".object_id evaluate to?

  • true
  • nil
  • an error
  • false

Answer: false. Two string literals are two separate objects, so their object_ids differ — the result is false.

What does :hi.object_id == :hi.object_id evaluate to?

  • false
  • true
  • nil
  • an error

Answer: true. :hi is always the same single object, so the object_ids match and the result is true.

Which kind of string literal performs interpolation with #{...}?

  • Double quotes
  • Single quotes
  • Both
  • Neither

Answer: Double quotes. Only double-quoted strings interpolate; single quotes treat #{...} as literal text.

How do you convert the string "active" into a symbol?

  • "active".to_symbol
  • Symbol("active")
  • "active".to_sym
  • :active.to_s

Answer: "active".to_sym. to_sym converts a string to a symbol; "active".to_sym gives :active.

What does :a == "a" return?

  • true
  • false
  • nil
  • an error

Answer: false. A symbol and a string are different types, so :a == "a" is false.

Are Symbols mutable or immutable?

  • Mutable
  • Mutable only in blocks
  • Depends on the value
  • Immutable (frozen)

Answer: Immutable (frozen). Symbols are immutable, lightweight labels — they are frozen and cannot be changed.

What is the recommended use for a Symbol versus a String?

  • Symbols for editable display text
  • Symbols for fixed identifiers like hash keys; Strings for arbitrary text
  • Always use symbols
  • Always use strings

Answer: Symbols for fixed identifiers like hash keys; Strings for arbitrary text. Use symbols for fixed, known identifiers (like :name); use strings for arbitrary or user-supplied text.

What does "hi"[0] return?

  • "i"
  • 0
  • "h"
  • "hi"

Answer: "h". Strings are zero-indexed, so [0] grabs the first character, "h".

Continue this course

Frequently asked questions

What's the real difference between a String and a Symbol?

A String is mutable text meant to be read, changed, and displayed — "hello" can be upcased, reversed, or built from pieces. A Symbol like :hello is an immutable, lightweight label, typically used as an identifier such as a hash key or a status flag. Crucially, every reference to the same symbol points to the exact same object in memory, while two identical strings are two separate objects. That makes symbols faster to compare and lighter to store when you need a fixed name.

When should I use single quotes versus double quotes?

Use double quotes when you need interpolation (#{...}) or escape sequences like for a newline. Use single quotes for plain literal text where you want exactly what you typed — single quotes do not interpolate, so 'Hi #{name}' prints the #{name} literally. Many Ruby developers default to double quotes for consistency, but single quotes are slightly faster and clearer when no interpolation is needed.

How do I join strings together?

There are three common ways. Interpolation, "#{a} #{b}", is usually the cleanest and is preferred. Concatenation with + joins strings, as in a + b, but both sides must already be strings. The shovel operator << appends to an existing string in place. For combining many pieces — like a list — Array#join is ideal: ["a", "b", "c"].join("-") gives "a-b-c".

Are symbols garbage collected like strings?

Historically symbols were never garbage collected, which is why you should avoid creating symbols dynamically from untrusted input. In modern Ruby (2.2 and later) symbols created at runtime can be collected, so the old memory-leak worry is largely gone. Still, the guidance stands: use symbols for fixed, known identifiers (like :name or :active), and use strings for arbitrary or user-supplied text.