Ruby Basics
Variables and Types
Variable types and scoping
# Local variable
name = "Evan"
age = 30
# Constants (uppercase start)
MAX_RETRIES = 3
PI = 3.14159
# Instance variable (object scope)
@hostname = "modestus-aw"
# Class variable (shared across instances)
@@count = 0
# Global variable (avoid these)
$debug = false
Core types
# Integers and Floats
port = 8080
ratio = 0.75
hex = 0xFF # => 255
binary = 0b1010 # => 10
big = 1_000_000 # underscores for readability
# Strings
single = 'no interpolation here'
double = "port #{port} is open"
heredoc = <<~HEREDOC
Multi-line string
with #{name}
HEREDOC
# Symbols — immutable, interned strings
status = :active
config = { host: "localhost", port: 443 }
# Booleans and nil
connected = true
error = nil # nil is falsy; everything else is truthy except false
# Type checking
port.is_a?(Integer) # => true
name.class # => String
port.respond_to?(:even?) # => true — duck typing
Control Flow
Conditionals
# Standard if/elsif/else
if status == :active
puts "running"
elsif status == :degraded
puts "warning"
else
puts "down"
end
# Inline (modifier form)
puts "open" if port == 443
puts "closed" unless connected
# Ternary
state = connected ? "up" : "down"
# Case/when (pattern matching)
case status
when :active then "green"
when :degraded then "yellow"
when :down then "red"
else "unknown"
end
# Case with ranges
case port
when 1..1023 then "privileged"
when 1024..49151 then "registered"
when 49152..65535 then "ephemeral"
end
Loops
# Times
5.times { |i| puts "Attempt #{i + 1}" }
# Each (preferred over for)
[80, 443, 8080].each do |port|
puts "Scanning port #{port}"
end
# While and until
retries = 0
while retries < MAX_RETRIES
retries += 1
end
until connected
attempt_connection
end
# Loop with break
loop do
result = check_status
break if result == :ok
end
Methods
Method definition
# Basic method
def greet(name)
"Hello, #{name}" # implicit return (last expression)
end
# Default arguments
def connect(host, port = 443)
puts "Connecting to #{host}:#{port}"
end
# Keyword arguments
def scan(host:, ports: [80, 443], timeout: 5)
ports.each { |p| probe(host, p, timeout) }
end
scan(host: "10.50.1.20", ports: [22, 443])
# Predicate methods (return boolean, end with ?)
def valid?(input)
input.is_a?(String) && !input.empty?
end
# Bang methods (modify in place, end with !)
name = "evan"
name.upcase! # name is now "EVAN"
# Splat (variable args)
def log(*messages)
messages.each { |m| puts "[LOG] #{m}" }
end
Output and Input
I/O basics
puts "newline added" # adds \n
print "no newline" # no \n
p [1, 2, 3] # inspect output: [1, 2, 3]
pp complex_object # pretty-print
# String formatting
printf "%-20s %5d\n", hostname, port
sprintf("Host: %s", name) # returns formatted string
# Input
print "Enter host: "
host = gets.chomp # chomp removes trailing newline
# ARGV
script_name = $0
first_arg = ARGV[0]