Syntax and Variables
Ruby variables, types, symbols vs strings, string interpolation, arrays, hashes and control flow.
Variables
Ruby is dynamically typed — you never declare a variable's type, and a variable can be reassigned to a value of a completely different type at any time:
name = "Ali" # a String
name = 42 # now an Integer — perfectly legal, no error
Variable naming conventions in Ruby are meaningful, not just stylistic:
| Prefix | Meaning |
|---|---|
name |
local variable |
@name |
instance variable (belongs to an object) |
@@name |
class variable (shared across all instances of a class) |
$name |
global variable (accessible anywhere — rarely a good idea) |
NAME |
constant (by convention; Ruby warns but doesn't prevent reassignment) |
Basic types
42.class # Integer
3.14.class # Float
"hello".class # String
:hello.class # Symbol
true.class # TrueClass
nil.class # NilClass
[1, 2, 3].class # Array
{a: 1}.class # Hash
Because everything in Ruby is an object, you can call methods directly on literals: 5.times { ... }, "hi".upcase, nil.to_s.
Symbols vs. strings
A symbol (:name) is an immutable, reusable identifier — internally, Ruby stores only one copy of a given symbol no matter how many times it appears, making symbols cheaper than strings for things like hash keys and method names:
:status == :status # true — same object, same identity
"status" == "status" # true (same content) — but two separate String objects
"status".object_id == "status".object_id # false — different objects each time
user = { name: "Ali", status: :active } # symbols are the idiomatic choice for hash keys
Use a String when you need to manipulate text (concatenate, search, mutate). Use a Symbol when you need a lightweight, comparable label — a hash key, a status value, a method name reference.
String interpolation
name = "Ali"
age = 22
puts "#{name} is #{age} years old" # Ali is 22 years old
puts "Next year: #{age + 1}" # any expression works inside #{}
Single-quoted strings do not interpolate — '#{name}' prints the literal text #{name}. Use double quotes whenever you need interpolation or escape sequences like \n.
Arrays
fruits = ["apple", "banana", "cherry"]
fruits << "date" # append — shovel operator
fruits.push("fig") # equivalent to <<
fruits.first # "apple"
fruits.last # "fig"
fruits[1] # "banana"
fruits[-1] # "fig" — negative indices count from the end
fruits.length # 5
fruits.each { |fruit| puts fruit } # iterate with a block
doubled = fruits.map { |f| f.upcase } # transform into a new array
short = fruits.select { |f| f.length < 5 } # filter
Hashes
user = { name: "Ali", age: 22, active: true }
user[:name] # "Ali"
user[:email] = "ali@example.com" # add a new key
user.key?(:age) # true
user.each { |key, value| puts "#{key}: #{value}" }
Control flow
age = 20
if age >= 18
puts "adult"
elsif age >= 13
puts "teen"
else
puts "child"
end
# unless — reads naturally as "if not"
unless age >= 18
puts "not an adult"
end
# statement modifiers — very idiomatic Ruby for short conditionals
puts "adult" if age >= 18
puts "minor" unless age >= 18
# case/when — Ruby's pattern-matching switch
category = case age
when 0..12 then "child"
when 13..17 then "teen"
else "adult"
end
puts category
Loops and iteration
Idiomatic Ruby leans heavily on iterator methods over manual index-based loops:
3.times { |i| puts i } # 0, 1, 2
(1..5).each { |n| puts n } # a Range, iterated
i = 0
while i < 3
puts i
i += 1
end
[1, 2, 3].each do |n|
puts n * 2
end
The do...end and { } block forms above are interchangeable — the community convention is { } for short, single-line blocks and do...end for multi-line ones (covered in depth on the blocks page later in this track).
Common mistakes
- Using a
Stringas a hash key out of habit ("name" => "Ali") where aSymbol(name: "Ali") is idiomatic, faster to compare, and what virtually all Ruby/Rails code expects. - Forgetting single-quoted strings don't interpolate —
'Hello #{name}'prints the literal#{name}, not the variable's value. - Confusing
nilwithfalsein a condition — both are "falsy" in Ruby (everything else, including0and"", is truthy), which surprises people coming from languages where0is falsy.
Interview questions
Q: What's the difference between a Symbol and a String in Ruby?
A Symbol (:name) is immutable and Ruby reuses the same object for every occurrence of that symbol, making comparisons cheap (identity comparison) and memory usage lower. A String ("name") is mutable, and each literal creates a distinct object even if the content is identical. Symbols are the idiomatic choice for hash keys and fixed identifiers; Strings are for text you'll manipulate.
Q: What values are "falsy" in Ruby?
Only nil and false are falsy — everything else, including 0, "" (empty string), and [] (empty array), is truthy. This differs from languages like JavaScript or Python, where 0 and empty collections are also falsy.