Comprehensive Ruby cheatsheet covering syntax, data types, OOP, modules, blocks, exceptions, file I/O, regex, Enumerable, and common gems. Includes naming conventions, operators, loops, hashes, arrays, and practical code examples—perfect for beginners and experienced devs needing quick reference.
- Basic Syntax & Execution
- Data Types
- Variables & Constants
- Operators
- Conditionals
- Loops & Iterators
- Arrays
- Hashes
- Strings
- Symbols
- Methods (Functions)
- Classes & Objects (OOP)
- Modules & Mixins
- Blocks, Procs & Lambdas
- Exception Handling
- File I/O
- Regular Expressions
- Enumerable Module
- Common Gems
- Ruby Style Guide
# Single line comment
=begin
Multi-line comment
=end
# Print with newline
puts "Hello World"
# Print without newline
print "Hello"
# Print with inspect (useful for debugging)
p "Hello" # => "Hello"
# Get user input
name = gets.chomp
# Execute: ruby filename.rb
# Interactive: irb or pry# Numbers
integer = 42
float = 3.14
big_num = 1_000_000_000 # underscores for readability
# Boolean
true_obj = true
false_obj = false
nil_obj = nil # represents "nothing" (falsey)
# Strings
str = "double quotes - interpolation: #{2 + 2}"
str2 = 'single quotes - literal: #{2 + 2}'
# Symbols (immutable, memory efficient)
symbol = :name
:hello == "hello".to_sym
# Arrays
arr = [1, 2, 3, "four", :five]
# Hashes
hash = { name: "Alice", age: 30 } # Ruby 1.9+ syntax
old_hash = { :name => "Bob", :age => 25 }
# Ranges
range = 1..10 # inclusive
range2 = 1...10 # exclusive (10 not included)# Variable naming conventions
local_var = "lowercase with underscores" # local variable
@instance_var = "starts with @" # instance variable
@@class_var = "starts with @@" # class variable
$global_var = "starts with $" # global variable
CONSTANT = "ALL_CAPS" # constant (warning if reassigned)
# Parallel assignment
a, b, c = 1, 2, 3
x, y = [10, 20] # x=10, y=20
# Swap variables
a, b = b, a
# Variable existence
defined? some_var # returns nil if not defined# Arithmetic
+ - * / % ** # add, subtract, multiply, divide, modulo, exponent
# Comparison
== != > < >= <= <=> # <=> returns -1, 0, or 1
# Logical
&& || ! # logical and, or, not
and or not # lower precedence versions
# Assignment shortcuts
x += 5 # x = x + 5
x -= 2
x *= 3
x /= 2
x %= 4
x **= 2
# Special operators
defined? # check if variable/method defined
.. ... # range operators
& | ^ # bitwise AND, OR, XOR
<< >> # bitwise shift
# Safe navigation (Ruby 2.3+)
user&.address&.city # returns nil if any part missing# If/else
if condition
# code
elsif other_condition
# code
else
# code
end
# Inline if
puts "Yes" if x > 10
# Unless (opposite of if)
unless condition
# runs if condition is false
end
# Inline unless
puts "No" unless x > 10
# Ternary
result = age >= 18 ? "Adult" : "Minor"
# Case statement
case grade
when "A"
puts "Excellent"
when "B", "C"
puts "Good"
else
puts "Try harder"
end
# Case with expressions
case
when score > 90
puts "A"
when score > 80
puts "B"
end# While loop
while condition
# code
end
# Until loop
until condition
# code
end
# For loop (rarely used, prefer iterators)
for i in 1..5
puts i
end
# Times iterator
5.times { |i| puts i } # 0,1,2,3,4
# Each iterator (most common)
[1,2,3].each { |num| puts num }
(1..5).each do |num|
puts num
end
# Other iterators
array.each_with_index { |val, idx| puts "#{idx}: #{val}" }
array.map { |x| x * 2 } # transform
array.select { |x| x.even? } # filter
array.reject { |x| x.odd? } # opposite of select
# Loop control
break # exit loop
next # skip to next iteration
redo # repeat current iteration
retry # restart loop (begin/rescue)
# Infinite loop
loop do
puts "forever"
break if condition
end# Creation
arr = Array.new(3) # [nil, nil, nil]
arr = Array.new(3, "x") # ["x", "x", "x"]
arr = %w[apple banana] # ["apple", "banana"]
arr = %i[name age] # [:name, :age]
# Access
arr[0] # first element
arr[-1] # last element
arr[1..3] # range
arr[1, 3] # start, length
# Modification
arr << 4 # push
arr.push(5)
arr.unshift(0) # prepend
arr.pop # remove last
arr.shift # remove first
arr.delete(3) # delete all 3's
arr.delete_at(2) # delete index 2
arr.insert(2, 'new') # insert at index
# Combination
arr1 + arr2 # concatenation
arr1 - arr2 # difference
arr1 & arr2 # intersection
arr1 | arr2 # union
# Useful methods
arr.length # size
arr.empty?
arr.include?(5)
arr.flatten # flatten nested arrays
arr.uniq # remove duplicates
arr.sort
arr.reverse
arr.sample # random element
arr.shuffle
arr.join(", ") # to string
# Array destructuring
first, *rest = [1, 2, 3, 4] # first=1, rest=[2,3,4]# Creation
hash = { name: "Alice", age: 30 }
hash = Hash.new(default_value)
hash = Hash[:a, 1, :b, 2]
# Access
hash[:name] # "Alice"
hash.fetch(:name) # with error handling
hash[:missing] # nil
hash.dig(:a, :b) # nested hash access
# Modification
hash[:city] = "NYC"
hash.delete(:age)
hash.merge!(other_hash) # destructive merge
# Iteration
hash.each { |key, value| puts "#{key}: #{value}" }
hash.each_key { |key| puts key }
hash.each_value { |value| puts value }
# Transform
hash.map { |k, v| [k.to_s, v] }.to_h
hash.select { |k, v| v > 18 }
hash.transform_values { |v| v * 2 }
# Default values
hash = Hash.new(0) # default 0 for missing keys
hash = Hash.new { |h, k| h[k] = [] } # auto-vivification
# Useful methods
hash.key?(:name) # check key
hash.value?("Alice")
hash.invert # swap keys and values
hash.keys
hash.values
hash.length# Interpolation
name = "Ruby"
puts "Hello #{name}" # Hello Ruby
puts %Q(Hello #{name}) # alternative
puts %(Hello #{name}) # same
# Special syntax
%q(no interpolation) # like single quotes
%w(word1 word2) # array of words
%W(word1 #{name}) # interpolated words
# Manipulation
str = "Hello World"
str.length # 11
str.upcase # "HELLO WORLD"
str.downcase
str.capitalize
str.reverse
str.strip # remove whitespace
str.chomp # remove newline
str.gsub("World", "Ruby")
str.sub("World", "Ruby") # first occurrence
# Slicing
str[0] # "H"
str[0,5] # "Hello"
str[6..10] # "World"
str["World"] # "World"
str[/[A-Z]/] # "H"
# Splitting/Joining
str.split(" ") # ["Hello", "World"]
words.join("-") # "Hello-World"
# Predicates
str.empty?
str.include?("World")
str.start_with?("Hello")
str.end_with?("World")
# Formatting
"%.2f" % 3.1415 # "3.14"
"%03d" % 5 # "005"
"Name: %s, Age: %d" % ["Bob", 25]
# Escaping
puts "Quote: \"Hello\""
puts 'It\'s Ruby'# Creation
sym = :name
sym = :"name with spaces"
# Properties
:name.object_id == :name.object_id # true (immutable)
"name".object_id == "name".object_id # false
# Conversion
:name.to_s # "name"
"name".to_sym # :name
# Use cases
# As hash keys (more efficient than strings)
hash = { :name => "Alice" } # old syntax
hash = { name: "Alice" } # new syntax
hash = Hash[[:a, 1], [:b, 2]]
# As method arguments
attr_reader :name, :age
# Checking existence
Symbol.all_symbols.include?(:name)# Basic method
def greet(name)
return "Hello, #{name}"
end
# Implicit return (last expression)
def add(a, b)
a + b
end
# Default arguments
def greet(name = "World")
puts "Hello, #{name}"
end
# Keyword arguments
def create_user(name:, age: 18, city: "NYC")
{ name: name, age: age, city: city }
end
create_user(name: "Alice", city: "LA")
# Variable arguments (*splat)
def sum(*numbers)
numbers.sum
end
sum(1,2,3,4) # 10
# Double splat for keyword args
def process(**options)
options.each { |k,v| puts "#{k}: #{v}" }
end
# Method with block
def repeat(n)
n.times { yield if block_given? }
end
repeat(3) { puts "Hi" }
# Predicate method (returns boolean)
def even?(num)
num % 2 == 0
end
# Dangerous/Bang method (modifies object)
def upcase!
@name = @name.upcase
end
# Method alias
alias new_name old_name
# Method visibility (in classes)
private
protected
public# Basic class
class Person
# Attributes
attr_accessor :name, :age # getter + setter
attr_reader :id # getter only
attr_writer :secret # setter only
# Class variable
@@population = 0
# Constant
SPECIES = "Homo sapiens"
# Constructor
def initialize(name, age)
@name = name
@age = age
@@population += 1
end
# Instance method
def introduce
"I'm #{@name}, #{@age} years old"
end
# Class method
def self.population
@@population
end
# To string
def to_s
"Person: #{@name}"
end
# Equality
def ==(other)
@name == other.name && @age == other.age
end
end
# Inheritance
class Student < Person
def initialize(name, age, grade)
super(name, age) # call parent constructor
@grade = grade
end
# Override
def introduce
super + " and I'm a student"
end
end
# Usage
alice = Person.new("Alice", 30)
puts alice.name # getter
alice.age = 31 # setter
puts alice.introduce
puts Person.population
# Class with metaclass methods
class MathUtils
class << self
def square(x)
x * x
end
end
end
# Singleton methods (on a single object)
str = "Hello"
def str.shout
upcase + "!!!"
end# Module as namespace
module MathUtils
PI = 3.14159
def self.square(x)
x * x
end
end
MathUtils.square(5) # 25
# Module as mixin (include)
module Swimmable
def swim
"Swimming!"
end
end
module Flyable
def fly
"Flying!"
end
end
class Duck
include Swimmable
include Flyable
end
duck = Duck.new
duck.swim # "Swimming!"
duck.fly # "Flying!"
# Module with instance methods
module Serializable
def to_json
instance_variables.each_with_object({}) do |var, hash|
hash[var.to_s.delete('@')] = instance_variable_get(var)
end.to_json
end
end
# Extend (adds class methods)
module ClassMethods
def create
new
end
end
class Product
extend ClassMethods
end
Product.create # class method
# Prepend (overrides methods)
module Logger
def save
puts "Logging before save"
super
puts "Logging after save"
end
end
class Document
prepend Logger
def save
puts "Saving document"
end
end
# Outputs: Logging before save, Saving document, Logging after save
# Include vs Prepend vs Extend
# include: adds as superclass (instance methods)
# prepend: adds before class (overrides)
# extend: adds class methods# Blocks (anonymous, not objects)
def perform
puts "Before"
yield if block_given?
puts "After"
end
perform { puts "Inside block" }
# Block with parameters
def with_params
yield(5, 10)
end
with_params { |a, b| puts a + b }
# Procs (blocks as objects)
my_proc = Proc.new { |x| puts x * 2 }
my_proc = proc { |x| puts x * 2 } # shorthand
my_proc.call(5) # 10
my_proc[5] # 10
my_proc === 5 # 10 (case w/ procs)
# Lambdas (more strict than procs)
my_lambda = lambda { |x| puts x * 2 }
my_lambda = ->(x) { puts x * 2 } # stabby lambda
my_lambda.call(5)
# Differences between Proc and Lambda
# 1. Lambda checks argument count, Proc doesn't
lambda { |x| x }.call(1,2) # Error
proc { |x| x }.call(1,2) # Ignores extra args
# 2. Return behavior
def test_proc
proc { return "from proc" }.call
"after proc"
end
def test_lambda
lambda { return "from lambda" }.call
"after lambda"
end
test_proc # => "from proc" (returns from method)
test_lambda # => "after lambda"
# Passing blocks to methods
def each_with_custom_block(&block)
[1,2,3].each(&block)
end
# Converting symbol to proc
[1,2,3].map(&:to_s) # ["1","2","3"]# Basic rescue
begin
result = 10 / 0
rescue ZeroDivisionError => e
puts "Error: #{e.message}"
end
# Multiple rescues
begin
file = File.open("missing.txt")
rescue Errno::ENOENT => e
puts "File not found"
rescue StandardError => e
puts "Other error: #{e.class}"
end
# Ensure (always runs)
begin
file = File.open("data.txt")
# process file
rescue
puts "Error occurred"
ensure
file.close if file
end
# Raising exceptions
def validate_age(age)
raise ArgumentError, "Age must be positive" if age <= 0
end
# Custom exception
class MyCustomError < StandardError
attr_reader :code
def initialize(message, code)
super(message)
@code = code
end
end
# Retry
attempts = 0
begin
attempts += 1
risky_operation
rescue NetworkError
retry if attempts < 3
end
# Else clause
begin
# code that might raise
rescue
# error handling
else
# runs if no exception
end
# Rescue modifier
result = risky_operation rescue "default value"# Reading files
File.open("file.txt", "r") do |file|
content = file.read
lines = file.readlines
end
# Shortcuts
content = File.read("file.txt")
lines = File.readlines("file.txt")
# Writing files
File.open("output.txt", "w") do |file|
file.write("Hello World\n")
file.puts("Another line")
end
# Append mode
File.open("log.txt", "a") do |file|
file.puts("New log entry")
end
# Shortcut write
File.write("file.txt", "content")
# File operations
File.exist?("file.txt")
File.delete("file.txt")
File.rename("old.txt", "new.txt")
File.size("file.txt")
File.directory?("dir")
File.file?("file.txt")
# Directory operations
Dir.mkdir("new_dir")
Dir.delete("empty_dir")
Dir.entries(".") # list contents
Dir.glob("*.rb") # match files
Dir["*.{rb,erb}"] # multiple patterns
# Working with paths
require 'pathname'
path = Pathname.new("folder/file.txt")
path.basename # "file.txt"
path.dirname # "folder"
path.extname # ".txt"
path.absolute?
path = Pathname.pwd + "new_file.txt"
# IO streams
$stdin # standard input
$stdout # standard output
$stderr # standard error
STDIN.gets
STDOUT.puts "message"# Creation
regex = /pattern/
regex = %r{pattern}
regex = Regexp.new("pattern")
# Matching
if "Hello World" =~ /World/
puts "Match found"
end
# Match operator
match = "Ruby 2.7" =~ /\d+\.\d+/ # returns index
match = /World/.match("Hello World")
# MatchData object
match = /(\w+):\s(\d+)/.match("Age: 25")
match[0] # "Age: 25" (full match)
match[1] # "Age"
match[2] # "25"
match[:key] # named capture
# Named captures
pattern = /(?<name>\w+):\s(?<age>\d+)/
match = pattern.match("Bob: 30")
match[:name] # "Bob"
match[:age] # "30"
# Scan (find all matches)
"one two three".scan(/\w+/) # ["one","two","three"]
"a1 b2 c3".scan(/(\w)(\d)/) # [["a","1"],["b","2"],["c","3"]]
# Substitution
"Hello World".sub(/World/, "Ruby") # "Hello Ruby"
"Hello World".gsub(/[aeiou]/, '*') # "H*ll* W*rld"
# Split
"one,two,three".split(/,/) # ["one","two","three"]
# Common patterns
/\d+/ # digits
/\w+/ # word characters
/\s+/ # whitespace
/./ # any character
/^/ # start of line
/$/ # end of line
/[aeiou]/ # character class
/[^aeiou]/ # negated class
/\A/ # start of string
/\z/ # end of string
# Options
/pattern/i # case insensitive
/pattern/m # multiline
/pattern/x # extended (ignore whitespace)# Each (base iterator)
[1,2,3].each { |x| puts x }
# Map / Collect (transform)
[1,2,3].map { |x| x * 2 } # [2,4,6]
(1..5).collect { |x| x ** 2 } # [1,4,9,16,25]
# Select / Find All (filter)
[1,2,3,4,5].select { |x| x.even? } # [2,4]
# Reject (opposite of select)
[1,2,3].reject { |x| x > 2 } # [1,2]
# Detect / Find (first match)
[1,2,3].find { |x| x > 1 } # 2
# Reduce / Inject (accumulate)
[1,2,3,4].reduce(0) { |sum, n| sum + n } # 10
[1,2,3].inject(:*) # 6
# Any? / All? / None? / One? (predicates)
[1,2,3].any?(&:even?) # true (at least one even)
[1,2,3].all?(&:even?) # false
[1,2,3].none?(&:even?) # false
[1,2,3].one?(&:even?) # false (two evens)
# Group By
[1,2,3,4].group_by(&:even?) # {true=>[2,4], false=>[1,3]}
# Partition
[1,2,3,4].partition(&:even?) # [[2,4], [1,3]]
# Sort
[3,1,4,2].sort # [1,2,3,4]
[3,1,4,2].sort_by { |x| -x } # [4,3,2,1]
# Chaining
[1,2,3,4,5]
.select(&:even?)
.map { |x| x * 10 }
.reduce(:+) # 2*10 + 4*10 = 60
# Lazy evaluation (for large collections)
(1..Float::INFINITY)
.lazy
.select(&:even?)
.first(5) # [2,4,6,8,10]# In Gemfile or install: gem install <name>
# Pry (better IRB)
require 'pry'
binding.pry # start debugger
# HTTP requests
require 'httparty'
response = HTTParty.get('https://api.example.com')
response.body
response.code
# JSON parsing
require 'json'
hash = JSON.parse('{"name":"Alice"}')
json = {name: "Bob"}.to_json
# Database (ActiveRecord)
require 'active_record'
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: 'db.sqlite3'
)
class User < ActiveRecord::Base
end
# Testing (RSpec)
# spec/my_spec.rb
RSpec.describe "Example" do
it "works" do
expect(2 + 2).to eq(4)
end
end
# Web framework (Sinatra)
require 'sinatra'
get '/' do
"Hello World"
end
# Web scraping (Nokogiri)
require 'nokogiri'
doc = Nokogiri::HTML(html_string)
doc.css('a').each { |link| puts link['href'] }
# File utilities (FileUtils)
require 'fileutils'
FileUtils.cp('src.txt', 'dest.txt')
FileUtils.mkdir_p('path/to/dir')
FileUtils.rm_rf('directory')
# Date/Time (ActiveSupport)
require 'active_support/all'
1.day.ago
3.hours.from_now
Date.today.beginning_of_week# Naming
# snake_case for methods and variables
# CamelCase for classes and modules
# SCREAMING_SNAKE_CASE for constants
# Spacing
# 2 spaces indentation (no tabs)
def method
if condition
do_something
end
end
# Method parentheses
# Omit when no arguments
def greet
puts "hello"
end
# Use when arguments
def add(a, b)
a + b
end
# Hash syntax
# Use 1.9+ style when keys are symbols
{ name: "Alice", age: 30 }
# String literals
# Prefer single quotes unless interpolation needed
name = 'Ruby'
puts "Hello #{name}" # interpolation requires double
# Conditional modifiers
puts "Yes" if condition # inline when short
# Use block form for multi-line
# Avoid `for` loops (use each)
# Avoid `and`/`or` (use `&&`/`||`)
# Use `each` without block returns Enumerator
# Use `map` instead of `collect`
# Use `select` instead of `find_all`
# Freeze mutable constants
ARRAY = [1,2,3].freeze
# Use `%w` for word arrays
%w[apple banana cherry]
# Use `%i` for symbol arrays
%i[name age city]
# Use `_` for unused block parameters
hash.each { |key, _| puts key }
# Comment style
# Single line comment with space after #
# FIXME: fix this later
# TODO: implement this
# Magic comment for UTF-8 encoding
# frozen_string_literal: true
# coding: utf-8| Task | Ruby Code |
|---|---|
| Run Ruby file | ruby filename.rb |
| Interactive shell | irb or pry |
| Install gem | gem install gem_name |
| Check version | ruby -v |
| Syntax check | ruby -c filename.rb |
| Debug mode | ruby -r debug filename.rb |
| Watch file | ruby -w filename.rb |
- Everything is an object - even numbers, classes, and
nil - Duck typing - "If it walks like a duck..."
- Open classes - modify existing classes at runtime
- Method missing - powerful metaprogramming
- Blocks everywhere - Ruby's secret sauce