Ruby
01 / 07

Language Fundamentals

Ruby: Language Fundamentals

Ruby is a dynamic, object-oriented language designed for developer happiness. Everything is an object. Known for its elegant syntax and the Rails framework.

Data Types & Variables

# Variables
local_var = 42          # local
@instance_var = "hello" # instance (within class)
@@class_var = []        # class (shared by all instances)
$global_var = "global"  # global (avoid)
CONSTANT = 3.14         # constant (convention: ALL_CAPS)

# Symbols (immutable identifiers — like frozen strings)
:name    # cheaper than strings for hash keys, comparisons
:name == :name  # always the same object in memory

# String
name = "Alice"
greeting = "Hello, #{name}!"    # interpolation (double quotes only)
multiline = <<~HEREDOC
  Line one
  Line two
HEREDOC

# Ranges
(1..10)   # inclusive: 1 to 10
(1...10)  # exclusive: 1 to 9
('a'..'z').to_a  # ['a', 'b', ..., 'z']

# Array
arr = [1, "two", :three, [4, 5]]
arr.first    # 1
arr.last     # [4, 5]
arr[-1]      # [4, 5]  (negative indexing)
arr[1..2]    # ["two", :three]

# Hash
user = { name: "Alice", age: 30 }  # symbol keys (modern syntax)
user[:name]     # "Alice"
user[:missing]  # nil (no KeyError)
user.fetch(:missing, "default")  # "default"

Control Flow

# Conditionals
if score >= 90
  "A"
elsif score >= 80
  "B"
else
  "C"
end

# Unless (if not)
unless user.admin?
  redirect_to root_path
end

# Ternary
status = active ? "on" : "off"

# Case (powerful — matches with ===)
case value
when 1..10       then "low"
when String      then "it's a string"
when /error/i    then "error pattern"
else             "other"
end

# Loops
5.times { |i| puts i }
(1..5).each { |i| puts i }

[1, 2, 3].each do |n|
  puts n
end

while condition
  # ...
  break if done
  next if skip
end

Methods & Blocks

# Method definition
def greet(name, greeting: "Hello")  # keyword argument with default
  "#{greeting}, #{name}!"
end

greet("Alice")                  # "Hello, Alice!"
greet("Bob", greeting: "Hi")   # "Hi, Bob!"

# Variadic arguments
def sum(*numbers)
  numbers.reduce(0, :+)
end

# Block — anonymous function passed to a method
[1, 2, 3].each { |n| puts n }
[1, 2, 3].each do |n|
  puts n
end

# yield — call the block passed to a method
def repeat(n)
  n.times { yield }
end
repeat(3) { puts "Hello" }

# Explicit block parameter
def log(&block)
  result = block.call
  puts "Result: #{result}"
end

# Proc and Lambda
double = Proc.new { |x| x * 2 }
triple = lambda { |x| x * 3 }   # or: ->(x) { x * 3 }
double.call(5)   # 10
triple.(5)       # 15

Enumerables

nums = [1, 2, 3, 4, 5, 6]

nums.map { |n| n * 2 }           # [2, 4, 6, 8, 10, 12]
nums.select { |n| n.even? }      # [2, 4, 6]
nums.reject { |n| n.even? }      # [1, 3, 5]
nums.find { |n| n > 3 }          # 4
nums.reduce(0) { |sum, n| sum + n }  # 21 (also: nums.sum)
nums.min    # 1
nums.max    # 6
nums.sort   # [1, 2, 3, 4, 5, 6]
nums.sort_by { |n| -n }          # [6, 5, 4, 3, 2, 1]
nums.group_by(&:even?)           # {false=>[1,3,5], true=>[2,4,6]}
nums.any? { |n| n > 5 }         # true
nums.all? { |n| n > 0 }         # true
nums.none? { |n| n > 10 }       # true
nums.count { |n| n.odd? }       # 3
nums.flat_map { |n| [n, n * 2] }  # [1,2,2,4,3,6,...]
nums.each_with_object({}) { |n, h| h[n] = n**2 }  # {1=>1, 2=>4, ...}

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free