Ruby Cheatsheet

Variables, data types, collections, blocks, OOP, modules, gems & Rails essentials

Language
Contents
πŸ’Ž

Basics & Types

# Variables
name = "Alice"        # local
@name = "Alice"       # instance variable
@@count = 0           # class variable
$debug = true         # global variable
NAME = "constant"     # constant

# Data types
age = 25              # Integer
pi = 3.14             # Float
name = "Alice"        # String
sym = :active         # Symbol (immutable, fast comparisons)
flag = true           # Boolean (TrueClass/FalseClass)
nothing = nil         # NilClass
arr = [1, 2, 3]      # Array
hash = { a: 1 }      # Hash
range = (1..10)       # Range

# String interpolation & conversion
"Hello #{name}, age #{age}"
age.to_s       # to string
"42".to_i      # to integer
"3.14".to_f    # to float
name.to_sym    # to symbol

# Type checking
name.is_a?(String)   # => true
name.class            # => String
name.respond_to?(:upcase)  # duck typing
πŸ“

Strings

s = "Hello, World!"

# Common methods
s.length              # => 13
s.upcase              # => "HELLO, WORLD!"
s.downcase            # => "hello, world!"
s.capitalize          # => "Hello, world!"
s.reverse             # => "!dlroW ,olleH"
s.strip               # trim whitespace
s.include?("World")   # => true
s.gsub("World", "Ruby")  # => "Hello, Ruby!"
s.split(", ")          # => ["Hello", "World!"]
s.chars               # => ["H","e","l","l","o",...]
s[0..4]               # => "Hello" (slicing)
s.freeze              # make immutable

# Heredoc
text = <<~HEREDOC
  This is a
  multi-line string
HEREDOC
πŸ“¦

Arrays

arr = [1, 2, 3, 4, 5]

# Access
arr[0]            # => 1
arr[-1]           # => 5 (last)
arr[1..3]          # => [2, 3, 4]
arr.first(2)       # => [1, 2]
arr.last            # => 5

# Modify
arr.push(6)        # or arr << 6
arr.pop             # remove last
arr.unshift(0)     # add to front
arr.shift           # remove first
arr.insert(2, 99)  # insert at index
arr.delete(3)      # delete value
arr.flatten         # flatten nested arrays
arr.compact         # remove nils
arr.uniq            # remove duplicates
arr.sort            # sort ascending
arr.reverse         # reverse

# Iterate & Transform
arr.each { |x| puts x }
arr.map { |x| x * 2 }       # => [2,4,6,8,10]
arr.select { |x| x > 3 }     # => [4, 5]
arr.reject { |x| x > 3 }     # => [1, 2, 3]
arr.reduce(0) { |sum, x| sum + x }  # => 15
arr.any? { |x| x > 4 }       # => true
arr.all? { |x| x > 0 }       # => true
arr.min / arr.max / arr.sum
πŸ—‚οΈ

Hashes

# Symbol keys (modern syntax)
user = { name: "Alice", age: 30, role: "admin" }

# Access
user[:name]                   # => "Alice"
user.fetch(:name, "default")  # with default
user.keys / user.values        # arrays of keys/values
user.key?(:age)                # => true
user.value?("Alice")           # => true

# Modify
user[:email] = "a@b.com"     # add/update
user.delete(:role)             # remove key
user.merge({ city: "NYC" })    # merge hashes

# Iterate
user.each { |k, v| puts "#{k}: #{v}" }
user.map { |k, v| [k, v.to_s] }.to_h
user.select { |k, v| v.is_a?(String) }

# Default values
counts = Hash.new(0)
counts[:missing]  # => 0 (instead of nil)
πŸ”€

Control Flow

# if / elsif / else
if age >= 18
  puts "adult"
elsif age >= 13
  puts "teen"
else
  puts "child"
end

# Inline / ternary
puts "adult" if age >= 18
status = age >= 18 ? "adult" : "minor"

# unless (opposite of if)
puts "allowed" unless banned

# case / when
case role
when "admin"  then puts "full access"
when "user"   then puts "limited"
else            puts "guest"
end

# Loops
5.times { |i| puts i }
(1..5).each { |i| puts i }
while x < 10; x += 1; end
until x >= 10; x += 1; end
loop { break if done }
next    # skip iteration (like continue)
break   # exit loop
πŸ”§

Methods & Blocks

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

# Splat args
def sum(*nums)
  nums.reduce(0, :+)
end

# Keyword args
def create_user(name:, age:, role: "user")
  { name: name, age: age, role: role }
end
create_user(name: "Alice", age: 30)

# Blocks, Procs, Lambdas
[1,2,3].each { |x| puts x }      # block (inline)
[1,2,3].each do |x|              # block (multi-line)
  puts x
end

square = Proc.new { |x| x ** 2 }
square.call(5)                      # => 25

multiply = ->(a, b) { a * b }       # lambda
multiply.call(3, 4)                 # => 12

# yield to block
def wrap
  puts "before"
  yield
  puts "after"
end
wrap { puts "inside" }
πŸ—οΈ

OOP

class Animal
  attr_accessor :name, :sound   # getter + setter
  attr_reader :species           # getter only

  def initialize(name, species)
    @name = name
    @species = species
  end

  def speak
    "#{@name} says #{@sound}"
  end

  def to_s
    "#{@name} (#{@species})"
  end

  # Class method
  def self.info
    "I am the Animal class"
  end
end

# Inheritance
class Dog < Animal
  def initialize(name)
    super(name, "Canine")
    @sound = "Woof!"
  end
end

rex = Dog.new("Rex")
rex.speak  # => "Rex says Woof!"
πŸ“¦

Modules & Mixins

# Module as namespace
module Utils
  def self.format_date(date)
    date.strftime("%Y-%m-%d")
  end
end
Utils.format_date(Time.now)

# Module as mixin (shared behavior)
module Printable
  def print_info
    puts to_s
  end
end

class User
  include Printable   # instance methods
  # extend Printable  # class methods
end
πŸ”„

Enumerable

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

nums.map { |x| x * 2 }            # [6,2,8,2,10,18,4,12]
nums.select(&:even?)               # [4, 2, 6]
nums.reject(&:odd?)                # [4, 2, 6]
nums.reduce(:+)                    # 31
nums.sort                          # [1,1,2,3,4,5,6,9]
nums.sort_by { |x| -x }           # descending
nums.group_by(&:even?)             # {false=>[3,1,1,5,9], true=>[4,2,6]}
nums.count { |x| x > 3 }          # 4
nums.flat_map { |x| [x, x*2] }    # flatten mapped arrays
nums.each_with_index { |x, i| }    # with index
nums.each_slice(3).to_a            # chunk into groups
nums.zip(["a","b","c"])            # pair elements
nums.tally                          # {3=>1,1=>2,4=>1,...}
nums.min_by { |x| x }
nums.max_by { |x| x }
nums.find { |x| x > 4 }            # first match
πŸ“

File I/O

# Read entire file
content = File.read("data.txt")
lines = File.readlines("data.txt", chomp: true)

# Write file
File.write("out.txt", "Hello\nWorld")

# Append
File.open("log.txt", "a") { |f| f.puts "new line" }

# Read line by line (memory efficient)
File.foreach("big.txt") { |line| puts line }

# JSON
require 'json'
data = JSON.parse(File.read("data.json"))
File.write("out.json", JSON.pretty_generate(data))
⚠️

Error Handling

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

# Custom exception
class NotFoundError < StandardError; end
raise NotFoundError, "User not found"

# Retry
attempts = 0
begin
  attempts += 1
  risky_operation
rescue
  retry if attempts < 3
end
πŸ“¦

Gems & Bundler

# Install a gem
gem install rails
gem install nokogiri

# Gemfile (for Bundler)
source "https://rubygems.org"
gem "rails", "~> 7.1"
gem "pg"
gem "puma"
gem "redis"

group :development, :test do
  gem "rspec-rails"
  gem "rubocop"
end

# Bundle commands
bundle install         # install deps
bundle update          # update gems
bundle exec rails s    # run with bundled gems
πŸ›€οΈ

Rails Essentials

# Create app
rails new myapp --database=postgresql --api

# Generate scaffold
rails generate scaffold User name:string email:string age:integer
rails db:migrate

# Routes (config/routes.rb)
Rails.application.routes.draw do
  resources :users          # RESTful routes
  get "/about", to: "pages#about"
  root "pages#home"
end

# Controller
class UsersController < ApplicationController
  def index
    @users = User.all
    render json: @users
  end

  def create
    @user = User.new(user_params)
    if @user.save
      render json: @user, status: :created
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  private
  def user_params
    params.require(:user).permit(:name, :email, :age)
  end
end

# Model (Active Record)
class User < ApplicationRecord
  has_many :posts
  validates :email, presence: true, uniqueness: true
  scope :active, -> { where(active: true) }
end

# Active Record queries
User.all / User.find(1) / User.find_by(email: "a@b.com")
User.where(role: "admin").order(created_at: :desc).limit(10)
User.pluck(:email)  # array of emails only