Variables, data types, collections, blocks, OOP, modules, gems & Rails essentials
Language# 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 typings = "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
HEREDOCarr = [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# 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)# 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# 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" }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!"# 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
endnums = [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# 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))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# 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# 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