Ruby — Reference
Source: https://www.ruby-lang.org/en/documentation/
Ruby
- Created: 1995 by Yukihiro “Matz” Matsumoto (1.0 in 1996)
- Latest stable: 4.0.3 (as of 2026-05; the Ruby 4.0 series is current — Ruby has shipped a year-end major release every December since 2013, the so-called “Christmas Ruby”)
- Paradigms: Multi-paradigm — pure object-oriented (everything is an object, including
nil, integers, classes), functional-leaning (blocks, procs, lambdas, immutability viafreeze), reflective, dynamic - Typing: Dynamic, strong, duck-typed; gradual typing via Sorbet (community) or RBS + Steep / TypeProf (official, since Ruby 3.0)
- Memory: Garbage-collected — generational, incremental mark-and-sweep with compaction (
GC.compactsince 2.7); since Ruby 3.3 the MMTk GC is pluggable as an experimental alternative - Compilation: Bytecode-interpreted by YARV (Yet Another Ruby VM); YJIT (Shopify’s lazy basic-block versioning JIT, written in Rust) is production-ready and default-on for many workloads since 3.3
- Primary domains: Web (Rails, Sinatra), DevOps (Chef, Puppet, Vagrant), automation/scripting, CI tooling, internal DSLs, packaging (Homebrew is Ruby)
- Official docs: https://docs.ruby-lang.org/en/master/
At a glance
- Steward: Matz + the ruby-core team; design discussion happens at the Ruby Developer Meeting and on bugs.ruby-lang.org. The reference implementation is CRuby / MRI.
- Other implementations: JRuby (JVM, real threads), TruffleRuby (GraalVM, often the fastest), mruby (embeddable), historically Rubinius and IronRuby.
- License: BSD-style (Ruby License or 2-clause BSD). Community-driven, no single corporate owner.
- Annual major release every December 25 — Ruby 3.0 (2020-12-25) introduced Ractors, Fibers scheduler, RBS, type-narrowing; 3.3 (2023-12-25) made YJIT production-grade. Ruby 4.0 dropped December 2025.
Getting started
-
Install / version manager:
rbenv+ruby-build(most common),chruby,RVM,asdf, ormise. Windows: RubyInstaller (https://rubyinstaller.org/). macOS:brew install rubyworks but most devs userbenvto avoid the system Ruby. -
Hello world (
hello.rb):puts "Hello, world!"Run:
ruby hello.rb. -
Project layout (Bundler / standard gem skeleton):
lib/<gem_name>.rb,lib/<gem_name>/version.rb,spec/ortest/,Gemfile,<name>.gemspec,Rakefile. Generated bybundle gem <name>. -
Package/build tool: RubyGems is the package format and registry (https://rubygems.org); Bundler (
Gemfile+Gemfile.lock) is the resolver/locker. Both ship with Ruby.Rake(Ruby make) is the canonical task runner. -
REPL:
irb(ships with Ruby; gained autocomplete + multi-line editing in 3.1 via Reline).pry(third-party) is the power-user alternative withbinding.pryfor breakpoints.debuggem is the official replacement for byebug since 3.1. (https://docs.ruby-lang.org/en/master/IRB.html)
Basics
- Types/literals:
Integer(arbitrary precision;Bignum/Fixnumunified in 2.4),Float,Rational(1/2r),Complex(1+2i),String,Symbol(:foo, interned),Array,Hash,Range(1..10,1...10),nil,true,false. Numeric literals:1_000_000,0xFF,0b1010,0o777. - Variables: Sigil-based scoping —
local,@instance,@@class,$global,CONSTANT(capitalized). Novar/let— first assignment defines. - Scoping: Methods do not close over enclosing locals (they create a fresh scope); blocks/procs/lambdas do close over them.
defopens a new scope;do...end/{}blocks inherit. - Control flow:
if/unless/while/until(also as suffix modifiers:puts x if x);case/when(uses===for matching) — gained pattern matching in 2.7 (experimental) and stabilized in 3.0 (case obj in [a, b, *]). Exceptions:begin/rescue/ensure/end.loop do ... endfor infinite. - Functions:
def name(args); ...; end. Implicit return of last expression. Default args, keyword args (def f(x:, y: 0)), splat (*args), double-splat (**kwargs), block param (&block). Method visibility:public(default),private,protected. Methods are not first-class — usemethod(:name)to get aMethodobject, orProc/lambdafor closures. - Strings: Double-quoted with
#{expr}interpolation; single-quoted (literal, no interpolation). Heredocs (<<~ENDfor indent-stripped). Encoded as UTF-8 by default since 2.0; per-stringString#encoding. Frozen string literals via# frozen_string_literal: truemagic comment (default-on planned for 4.x). - Collections:
Array([1,2,3]),Hash({a: 1, b: 2}),Set(require "set"). All supportEnumerablemixin:map,select,reject,reduce/inject,each_with_object,group_by,chunk_while,lazyfor lazy chains.
Intermediate
- Type system depth: Dynamic + duck-typed by default. RBS (Ruby Signature) is the official type-declaration language living in
.rbsfiles alongside.rb. Steep does static checking; TypeProf does abstract-interpretation type inference. Sorbet (Stripe) is a competing ecosystem with inline# typed: truesigs and a faster checker. (https://github.com/ruby/rbs) - Modules: Files are
required (loaded once) orloaded (re-runs every call). Bundler’sbundle execensures the right gem versions.Moduleis a namespace + mixin mechanism —includeadds instance methods,extendadds class methods,prepend(Ruby 2.0+) puts the module before the class in the ancestor chain. - Error handling: Exception class hierarchy rooted at
Exception→StandardError→ …rescuewithout args catchesStandardError(notException— this is intentional, to not catchSystemExit/Interrupt).raise,retry,ensure,else. Custom errors subclassStandardError. - Concurrency primitives:
- Threads: real OS threads but constrained by the GVL (Global VM Lock) — only one thread executes Ruby code at a time. I/O releases the GVL.
- Fibers: coroutines (cooperative). Since 3.0,
Fiber.schedulerlets gems likeasync(socketry/async) plug in event-loop scheduling —sleep,Net::HTTP, etc., become non-blocking transparently. - Ractors: truly parallel actors with no shared mutable state, introduced experimentally in 3.0 — share only frozen/copied/movable objects. Still considered experimental in 4.0 (many gems are not Ractor-safe).
- Process for true parallelism (fork-based;
Process.fork).
- I/O:
File.read,File.open,IO.copy_stream,Pathname(object-oriented paths),StringIOfor in-memory streams.Net::HTTPin stdlib (low-level);URI.openfor quick fetches. Thesocketlib for TCP/UDP/Unix. - Stdlib highlights:
JSON,YAML(Psych),CSV,OpenStruct,Set,Date/DateTime/Time,OptionParser(CLI flags),Logger,Tempfile,Tmpdir,Open3(subprocess with stdout/stderr/exit),Forwardable(delegation DSL),Comparable/Enumerablemixins.
Advanced
- Memory/GC: Tri-color incremental mark-and-sweep, generational since 2.1, compacting since 2.7 (
GC.compact), object-shape-aware allocation since 3.2. MMTk (Memory Management Toolkit, from the JVM/Java research lineage) was integrated as a pluggable GC in 3.3 — build with--with-mmtk. Heap is divided into pages of 40-byte slots (RVALUE); larger objects allocate auxiliary memory viaxmalloc. (https://shopify.engineering/understanding-ruby-gc-through-gc-stat) - Concurrency deep dive:
- GVL is per-Ractor (not per-process), so Ractors get true parallelism. Within a Ractor, threads share a GVL.
- YJIT is GVL-aware and ships in the CRuby binary; enable with
--yjitorRUBY_YJIT_ENABLE=1. Stats viaRubyVM::YJIT.runtime_stats. - Async (https://github.com/socketry/async) is the leading Fiber-scheduler implementation —
Async { ... }blocks become cooperative.
- FFI:
fiddle(stdlib, libffi-based). The third-partyffigem is more popular and works on JRuby too. C extensions (.c+extconf.rb+Init_<name>) are still common for high-perf gems (Nokogiri, OJ). - Reflection: Ruby’s metaprogramming is the headline feature —
Object#class,Object#methods,Method#source_location,instance_variable_get/set,define_method,class_eval,instance_eval,Module#prepend,ObjectSpace.each_object,Kernel#caller.TracePointfor instrumentation. - Performance tools:
benchmark(stdlib),benchmark-ips(gem),stackprof(sampling profiler, the Rails-world standard),ruby-prof,vernier(newer, Ractor-aware),memory_profiler,derailed_benchmarks(Rails),rbspy(out-of-process sampler, written in Rust).
God mode
method_missing+respond_to_missing?: the canonical metaprogramming hook — intercept any unknown method call. Always pair them; only overridingmethod_missingbreaksrespond_to?/duck-typing checks.- Refinements: scoped monkey-patches (
refine String do ... end+using StringExtin a file/module). Avoids polluting global classes; lexically scoped per file. BasicObject: the truly empty parent class (noKernel, noObjectmethods). Used forDelegator, transparent proxies, DSL evaluators.TracePoint: subscribe to events (:call,:return,:line,:raise,:b_call) at runtime — powersbyebug,ruby-debug, coverage tools, and can be used for AOP. (https://docs.ruby-lang.org/en/master/TracePoint.html)binding: captures the local scope as an object;binding.eval("x")evaluates a string in that scope;binding.irb(built-in since 2.5) andbinding.prydrop into a REPL with full local access at the call site.RubyVM::InstructionSequence: compile and inspect YARV bytecode —RubyVM::InstructionSequence.compile("1+1").disasmprints opcodes. Lets you build code at runtime, cache compiled bytecode (Bootsnap), or write custom interpreters.- MJIT → YJIT → ZJIT: MJIT (the original method-based JIT, generated C and called the system compiler) was deprecated in 3.3 in favor of YJIT (Shopify’s basic-block-versioning JIT in Rust). ZJIT is the next-gen IR-based JIT in development for the 4.x series.
- GVL hacks:
rb_thread_call_without_gvlin C extensions releases the lock;Thread#priorityis mostly cosmetic. UseProcess.forkor Ractors for true parallelism. - Frozen string optimization:
# frozen_string_literal: truemagic comment freezes all string literals in the file at parse time, allowing the VM to deduplicate and skip allocation. Performance + safety win; default on the roadmap for 4.x. - Ripper: stdlib SAX-like parser that exposes the lexer/parser events (
Ripper.sexp,Ripper.lex,Ripper.tokenize). Powers RuboCop’s AST (via theparsergem, which is a more user-friendly wrapper). Lets you build linters, formatters, refactoring tools. - Prism parser: new universal Ruby parser written in C, replacing the legacy
parse.ygrammar — adopted by Ruby 3.3+ as a parallel parser, default in 3.4 / 4.0. Used by Sorbet, RuboCop, Solargraph, IRB. - Object shapes: since 3.2, instance variable layout is tracked via a shape tree (similar to V8 hidden classes) — drastically faster
@ivaraccess. RunRubyVM::Shape.find_by_id(obj.shape_id)to inspect.
Idioms & style
- Naming:
snake_casefor methods/locals,CamelCasefor classes/modules,SCREAMING_SNAKE_CASEfor constants. Predicates end in?(empty?), mutating methods end in!(sort!). - Formatter / linter: RuboCop (https://docs.rubocop.org/) — both linter and formatter, with the official Ruby Style Guide at https://rubystyle.guide. Standard (Ruby Standard) is a zero-config RuboCop preset.
rubocop -afor auto-fix. - Idiomatic patterns: prefer iterators (
each,map) over indexedfor; use blocks over explicit Procs; “tell, don’t ask”;Enumerablemixin everywhere; small methods (Sandi Metz’s “five rules”); guard clauses (return unless x);||=for memoization;tapfor side-effects in chains;then/yield_selffor pipelining. - Expert review focus: monkey-patching of stdlib without refinements,
eval/instance_evalof user input, N+1 queries (Rails), unfrozen string literals in hot paths, blocking I/O insideAsync/Ractor contexts, Ractor-unsafe constants, mutable default keyword args.
Ecosystem
- Web/server: Rails (the dominant full-stack framework — convention over configuration), Sinatra (microframework), Hanami (clean-architecture alternative), Roda (routing tree). App servers: Puma (default since Rails 5), Unicorn, Falcon (Async-based), Rack is the universal web server interface.
- API: Grape, Rails API mode.
- Background jobs: Sidekiq (Redis-backed, threads), GoodJob (Postgres-backed, Rails-native), Resque, Solid Queue (Rails 8+ default).
- DevOps / infra: Chef, Puppet, Vagrant, Fastlane (iOS/Android automation), Capistrano (deploy), Berkshelf.
- Data: ActiveRecord (Rails ORM), Sequel (lighter ORM), ROM-rb (data mapper), pg / mysql2 / sqlite3 native gems.
- Testing: RSpec (BDD, dominant), Minitest (stdlib, Rails default), Cucumber (Gherkin), Capybara (browser/system tests), VCR (record HTTP), WebMock, factory_bot, shoulda-matchers.
- Docs: YARD (
yardoc) — the de-facto documentation generator; RDoc ships with Ruby. Public hosting at https://rubydoc.info. - Notable users: GitHub (Rails monolith), Shopify (Rails + sponsors much of CRuby/YJIT), Airbnb, Stripe (Sorbet), Basecamp/37signals (Rails inventors), Heroku, Twitch (originally), Square.
Gotchas
nil,falseare the only falsy values —0,"",[]are all truthy.==vseql?vsequal?:==is value equality (overridable),eql?is stricter (1 == 1.0true,1.eql?(1.0)false),equal?is object identity. Don’t overrideequal?.String#+allocates; useString#<<orString#concatto mutate in-place. Frozen strings can’t be mutated —FrozenError.- Default keyword args / hash params evaluated once at definition if mutable —
def f(arr = []); arr << 1; arr; enddoes not leak (unlike Python), because Ruby re-evaluates default expressions per call. procvslambda: lambdas check arity strictly andreturnreturns from the lambda; procs are lax andreturnreturns from the enclosing method.attr_accessor :name+name = "x"inside an instance method creates a local — must writeself.name = "x".- Ractors don’t share class-level state —
@@class_var, mutable constants, ENV writes — reads are usually fine, writes raise. - Monkey-patching is easy and dangerous; use refinements when possible.
requirepaths are relative to$LOAD_PATH, not the calling file — userequire_relativefor sibling files.||=short-circuits onnil/false, soflag ||= truewon’t resetflag = false.eachreturns the original collection;mapreturns a new array — confusing the two is a classic bug.- YJIT must be explicitly enabled in older 3.x; default-on for many apps in 3.3+ but check
RubyVM::YJIT.enabled?.
Citations
- Documentation index: https://www.ruby-lang.org/en/documentation/
- Master API docs: https://docs.ruby-lang.org/en/master/
- Downloads / current stable: https://www.ruby-lang.org/en/downloads/
- Style guide (RuboCop): https://rubystyle.guide
- RuboCop docs: https://docs.rubocop.org/
- IRB: https://docs.ruby-lang.org/en/master/IRB.html
- TracePoint: https://docs.ruby-lang.org/en/master/TracePoint.html
- RBS (type signatures): https://github.com/ruby/rbs
- YJIT design (Shopify): https://shopify.engineering/yjit-just-in-time-compiler-for-ruby
- Bundler: https://bundler.io/
- RubyGems: https://rubygems.org/
- Async (Fiber scheduler): https://github.com/socketry/async
- Ractor docs: https://docs.ruby-lang.org/en/master/ractor_md.html
- Prism parser: https://github.com/ruby/prism
- Version verified 2026-05-06: 4.0.3 (current stable on ruby-lang.org/en/downloads)