Ruby

Essential Ruby syntax, data structures, and common operations for scripting and web development.

languages
rubyscriptingbackendrails

Hello World

# Print to console
puts "Hello, World!"        # Output with newline

# Print without newline
print "Hello, World!"       # No newline at end

# String interpolation
name = "Ruby"
puts "Hello, #{name}!"      # Output: Hello, Ruby!

# Multiple values
p "Values:", 42, 3.14, true # Debug output (inspect)

Variables

# Variable assignment (dynamic typing)
name = "Alice"              # String
age = 30                    # Integer
height = 5.8                # Float
is_active = true            # Boolean

# Multiple assignment
x, y, z = 1, 2, 3          # Parallel assignment
a = b = c = 0              # Same value to multiple variables

# Constants (uppercase)
PI = 3.14159               # Constants should not be reassigned
MAX_SIZE = 100

Strings

# String creation
single = 'Hello'           # Single quotes (literal)
double = "World"           # Double quotes (interpolation)
name = "Alice"
greeting = "Hello, #{name}!"  # String interpolation

# Common string methods
text = "hello world"
text.upcase                # "HELLO WORLD"
text.capitalize            # "Hello world"
text.reverse               # "dlrow olleh"
text.split                 # ["hello", "world"]
text.include?("world")     # true
text.length                # 11

# Multiline strings
multiline = <<~TEXT
  This is a
  multiline string
TEXT

Numbers

# Integer operations
sum = 10 + 5               # Addition: 15
diff = 10 - 5              # Subtraction: 5
prod = 10 * 5              # Multiplication: 50
quot = 10 / 3              # Integer division: 3
div = 10.0 / 3             # Float division: 3.333...
mod = 10 % 3               # Modulo: 1
power = 2 ** 3             # Exponentiation: 8

# Float operations
pi = 3.14159
pi.round(2)                # 3.14
pi.ceil                    # 4
pi.floor                   # 3

# Useful methods
42.even?                   # true
42.odd?                    # false
-5.abs                     # 5

Arrays

# Array creation
fruits = ['apple', 'banana', 'cherry']
numbers = [1, 2, 3, 4, 5]
mixed = [1, "two", 3.0, true]  # Mixed types allowed

# Accessing elements
fruits[0]                  # "apple" (first element)
fruits[-1]                 # "cherry" (last element)
fruits[1..2]               # ["banana", "cherry"] (range)
fruits.first               # "apple"
fruits.last                # "cherry"

# Common array methods
fruits.push('date')        # Add to end
fruits << 'elderberry'     # Alternative push syntax
fruits.pop                 # Remove and return last element
fruits.unshift('apricot')  # Add to beginning
fruits.shift               # Remove and return first element
fruits.length              # Get size
fruits.include?('banana')  # true
fruits.sort                # Sort alphabetically
fruits.reverse             # Reverse order

# Array operations
[1, 2, 3] + [4, 5]        # Concatenation: [1, 2, 3, 4, 5]
[1, 2, 3, 2, 1].uniq      # Remove duplicates: [1, 2, 3]

Hashes

# Hash creation (key-value pairs)
person = {
  'name' => 'Alice',
  'age' => 30,
  'city' => 'NYC'
}

# Symbol keys (more common)
user = {
  name: 'Bob',             # Modern syntax
  age: 25,
  email: 'bob@example.com'
}

# Accessing values
user[:name]                # "Bob"
user[:phone]               # nil (missing key)
user.fetch(:phone, 'N/A')  # 'N/A' (with default)

# Common hash methods
user[:country] = 'USA'     # Add/update key
user.delete(:email)        # Remove key
user.keys                  # [:name, :age, :country]
user.values                # ["Bob", 25, "USA"]
user.key?(:name)           # true
user.empty?                # false

# Iterating
user.each do |key, value|
  puts "#{key}: #{value}"
end

Control Flow

# If/elsif/else
age = 18
if age >= 18
  puts "Adult"
elsif age >= 13
  puts "Teenager"
else
  puts "Child"
end

# Unless (opposite of if)
unless logged_in?
  redirect_to_login
end

# Ternary operator
status = age >= 18 ? "adult" : "minor"

# Case/when (switch statement)
grade = 'B'
case grade
when 'A'
  puts "Excellent"
when 'B', 'C'              # Multiple values
  puts "Good"
when 'D'
  puts "Needs improvement"
else
  puts "Fail"
end

# Statement modifiers
puts "Hello" if greeting_enabled?
break unless valid?

Loops

# While loop
count = 0
while count < 5
  puts count
  count += 1
end

# Until loop (opposite of while)
until count >= 10
  count += 1
end

# For loop with range
for i in 1..5
  puts i
end

# Loop with break
loop do
  break if done?
end

# Times loop
5.times do |i|
  puts "Iteration #{i}"
end

# Each loop (most common)
[1, 2, 3].each do |num|
  puts num
end

# Loop control
next if skip_this?         # Continue to next iteration
break if should_stop?      # Exit loop

Methods

# Method definition
def greet(name, greeting = "Hello")
  "#{greeting}, #{name}!"
end

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

# Methods with blocks
def repeat(times)
  times.times do
    yield                  # Call the block
  end
end

repeat(3) { puts "Hello" }

# Method with return value
def add(a, b)
  a + b                    # Implicit return (last expression)
end

# Explicit return
def check_age(age)
  return "Invalid" if age < 0
  age >= 18 ? "Adult" : "Minor"
end

# Splat operator (variable arguments)
def sum(*numbers)
  numbers.reduce(0, :+)
end

sum(1, 2, 3, 4)            # 10

Blocks and Iterators

# Block with do...end
[1, 2, 3].each do |num|
  puts num * 2
end

# Block with curly braces (one-liners)
[1, 2, 3].each { |num| puts num * 2 }

# Map (transform elements)
doubled = [1, 2, 3].map { |n| n * 2 }  # [2, 4, 6]

# Select (filter elements)
evens = [1, 2, 3, 4].select { |n| n.even? }  # [2, 4]

# Reject (inverse of select)
odds = [1, 2, 3, 4].reject { |n| n.even? }  # [1, 3]

# Reduce (accumulate)
sum = [1, 2, 3, 4].reduce(0) { |acc, n| acc + n }  # 10
sum = [1, 2, 3, 4].reduce(:+)  # Shorthand: 10

# Find (first match)
first_even = [1, 3, 4, 5].find { |n| n.even? }  # 4

# Any? and all?
[2, 4, 6].all?(&:even?)    # true
[1, 2, 3].any?(&:even?)    # true

Classes and Objects

# Class definition
class Person
  # Class variable
  @@count = 0
  
  # Attribute accessors
  attr_accessor :name      # getter and setter
  attr_reader :age         # getter only
  attr_writer :email       # setter only
  
  # Constructor
  def initialize(name, age)
    @name = name           # Instance variable
    @age = age
    @@count += 1
  end
  
  # Instance method
  def greet
    "Hello, I'm #{@name}"
  end
  
  # Class method
  def self.count
    @@count
  end
end

# Creating objects
person = Person.new("Alice", 30)
person.name                # "Alice"
person.greet               # "Hello, I'm Alice"
Person.count               # 1

# Inheritance
class Student < Person
  def initialize(name, age, major)
    super(name, age)       # Call parent constructor
    @major = major
  end
  
  def greet
    "#{super}. I study #{@major}."
  end
end

Modules

# Module definition (namespace + mixins)
module Greetable
  def greet
    "Hello from #{self.class}"
  end
end

class Person
  include Greetable        # Include module (instance methods)
end

module Math
  PI = 3.14159
  
  def self.circle_area(radius)
    PI * radius ** 2
  end
end

Math::PI                   # 3.14159
Math.circle_area(5)        # 78.53975

File I/O

# Reading files
content = File.read('file.txt')  # Read entire file

File.open('file.txt', 'r') do |file|
  file.each_line do |line|
    puts line
  end
end

lines = File.readlines('file.txt')  # Array of lines

# Writing files
File.write('file.txt', 'Hello, World!')  # Overwrite

File.open('file.txt', 'w') do |file|
  file.puts "Line 1"
  file.puts "Line 2"
end

# Appending
File.open('file.txt', 'a') do |file|
  file.puts "New line"
end

# Check file existence
File.exist?('file.txt')    # true/false

Exception Handling

# Basic exception handling
begin
  result = 10 / 0
rescue ZeroDivisionError => e
  puts "Error: #{e.message}"
rescue StandardError => e
  puts "General error: #{e.message}"
ensure
  puts "This always runs"
end

# Raise exceptions
def validate_age(age)
  raise ArgumentError, "Age must be positive" if age < 0
  age
end

# Retry
attempts = 0
begin
  risky_operation
rescue
  attempts += 1
  retry if attempts < 3
  raise                    # Re-raise if max attempts reached
end

Regular Expressions

# Pattern matching
text = "Email: user@example.com"
text =~ /\w+@\w+\.\w+/     # Returns match position

# Match method
match = text.match(/(\w+)@(\w+\.\w+)/)
match[0]                   # "user@example.com" (full match)
match[1]                   # "user" (first group)
match[2]                   # "example.com" (second group)

# Scan (find all matches)
numbers = "Call 123-456-7890 or 098-765-4321"
numbers.scan(/\d{3}-\d{3}-\d{4}/)  # ["123-456-7890", "098-765-4321"]

# Substitution
text = "hello world"
text.sub('world', 'Ruby')  # "hello Ruby" (first match)
text.gsub('l', 'L')        # "heLLo worLd" (all matches)

Symbols

# Symbols (immutable, reusable identifiers)
status = :pending          # More memory efficient than strings
state = :active

# Common use in hashes
options = {
  color: 'red',            # :color symbol as key
  size: :large             # :large symbol as value
}

# Convert between strings and symbols
:hello.to_s                # "hello"
"hello".to_sym             # :hello
"hello".intern             # :hello (alternative)

Common Idioms

# Safe navigation operator
user&.profile&.email       # Returns nil if any part is nil

# Double pipe (or-equals)
name ||= "Default"         # Assign only if name is nil/false

# Ranges
(1..10).to_a               # [1, 2, 3, ..., 10] (inclusive)
(1...10).to_a              # [1, 2, 3, ..., 9] (exclusive)

# Array/String multiplication
"ha" * 3                   # "hahaha"
[1, 2] * 3                 # [1, 2, 1, 2, 1, 2]

# Spaceship operator (comparison)
1 <=> 2                    # -1 (less than)
2 <=> 2                    # 0 (equal)
3 <=> 2                    # 1 (greater than)

# Method chaining
text = "  hello world  "
text.strip.upcase.reverse  # "DLROW OLLEH"