<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ruby Archives | Abdul Wahab Junaid</title>
	<atom:link href="https://awjunaid.com/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>https://awjunaid.com/tag/ruby/</link>
	<description>Offensive Security Researcher &#38; Quantum Cryptography Analyst</description>
	<lastBuildDate>Wed, 29 Jul 2026 22:40:41 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://i0.wp.com/awjunaid.com/wp-content/uploads/2023/06/cropped-1668274976669.jpeg?fit=32%2C32&#038;ssl=1</url>
	<title>ruby Archives | Abdul Wahab Junaid</title>
	<link>https://awjunaid.com/tag/ruby/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">220030102</site>	<item>
		<title>Socket and Network Libraries in Ruby: Complete Guide to Network Programming with TCPSocket and UDPSocket</title>
		<link>https://awjunaid.com/ruby/socket-and-network-libraries-in-ruby-complete-guide-to-network-programming-with-tcpsocket-and-udpsocket/</link>
					<comments>https://awjunaid.com/ruby/socket-and-network-libraries-in-ruby-complete-guide-to-network-programming-with-tcpsocket-and-udpsocket/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Fri, 01 Sep 2023 20:10:39 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4508</guid>

					<description><![CDATA[<p>Network programming is one of those areas where Ruby quietly punches above its weight. Under the hood of&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/socket-and-network-libraries-in-ruby-complete-guide-to-network-programming-with-tcpsocket-and-udpsocket/">Socket and Network Libraries in Ruby: Complete Guide to Network Programming with TCPSocket and UDPSocket</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Network programming is one of those areas where Ruby quietly punches above its weight. Under the hood of every web server, chat application, and API client sits a socket doing the actual work of moving bytes across a wire. Ruby&#8217;s standard library ships with a mature, Berkeley-sockets-based networking stack that lets you build everything from a simple TCP echo server to a full UDP-based telemetry system without installing a single gem.</p>



<p class="wp-block-paragraph">This guide walks through Ruby&#8217;s socket libraries from the ground up — starting with what a socket actually is, moving through <code>TCPSocket</code> and <code>UDPSocket</code> in detail, and finishing with performance, memory, and production-readiness concerns that matter once code leaves a tutorial and enters a real system.</p>



<h2 class="wp-block-heading">What Is a Socket, Really?</h2>



<p class="wp-block-paragraph">A socket is an endpoint for communication between two machines (or two processes on the same machine). When you open a socket in Ruby, you&#8217;re really asking the operating system kernel to create a file-descriptor-backed communication channel. Ruby&#8217;s <code>Socket</code> class is a thin, object-oriented wrapper around the same system calls a C program would use: <code>socket()</code>, <code>bind()</code>, <code>connect()</code>, <code>listen()</code>, <code>accept()</code>, <code>send()</code>, and <code>recv()</code>.</p>



<p class="wp-block-paragraph">Ruby exposes this functionality through the <code>socket</code> library, which you load with:</p>



<pre class="wp-block-code"><code>require 'socket'
</code></pre>



<p class="wp-block-paragraph">This single require gives you access to a family of classes:</p>



<ul class="wp-block-list">
<li><code>TCPSocket</code> — for connection-oriented, reliable, stream-based communication</li>



<li><code>TCPServer</code> — for accepting incoming TCP connections</li>



<li><code>UDPSocket</code> — for connectionless, best-effort datagram communication</li>



<li><code>UNIXSocket</code> / <code>UNIXServer</code> — for local inter-process communication</li>



<li><code>Socket</code> — the low-level base class giving direct access to socket options</li>
</ul>



<p class="wp-block-paragraph">Understanding the distinction between TCP and UDP is the foundation everything else builds on.</p>



<h2 class="wp-block-heading">TCP vs UDP: Choosing the Right Tool</h2>



<p class="wp-block-paragraph">TCP (Transmission Control Protocol) is connection-oriented. Before any data moves, a three-way handshake establishes a reliable, ordered, error-checked stream between two endpoints. If a packet is lost, TCP retransmits it automatically. This reliability comes at the cost of overhead and latency — TCP is ideal for HTTP APIs, database connections, file transfers, and anything where losing or reordering data is unacceptable.</p>



<p class="wp-block-paragraph">UDP (User Datagram Protocol) is connectionless. Each datagram is fired off independently with no handshake, no guaranteed delivery, and no guaranteed ordering. In exchange, UDP has almost no overhead. It&#8217;s the right choice for DNS lookups, video/audio streaming, game state updates, and metrics collection, where a dropped packet just means you wait for the next one rather than stall the whole connection.</p>



<p class="wp-block-paragraph">Ruby gives you dedicated classes for both, so the choice mostly comes down to what your protocol actually needs.</p>



<h2 class="wp-block-heading">Working with TCPSocket: Client-Side Networking</h2>



<p class="wp-block-paragraph"><code>TCPSocket</code> is Ruby&#8217;s class for making outbound TCP connections. Creating one and connecting to a remote host takes a single line:</p>



<pre class="wp-block-code"><code>require 'socket'

# Connect to a host on a given port
socket = TCPSocket.new('example.com', 80)

# Send a minimal HTTP GET request
socket.write("G ET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")

# Read the full response
response = socket.read
puts response

socket.close
</code></pre>



<p class="wp-block-paragraph"><strong>Output (truncated):</strong></p>



<pre class="wp-block-code"><code>HTTP/ 1.1 200 OK
Content-Type: text/html; charset=UTF-8
...
</code></pre>



<p class="wp-block-paragraph">A few things are happening internally that are worth understanding:</p>



<ol class="wp-block-list">
<li><code>TCPSocket.new</code> performs a DNS resolution (if given a hostname), opens a socket file descriptor via the <code>socket()</code> system call, and calls <code>connect()</code> to complete the TCP three-way handshake.</li>



<li><code>socket.write</code> pushes bytes into the kernel&#8217;s send buffer; the actual transmission over the wire happens asynchronously, managed by the OS network stack.</li>



<li><code>socket.read</code> blocks the current thread until data arrives or the connection is closed by the peer.</li>
</ol>



<h3 class="wp-block-heading">Reading Line by Line</h3>



<p class="wp-block-paragraph">Since <code>TCPSocket</code> inherits from <code>IO</code>, you get all the familiar IO methods for free — <code>gets</code>, <code>each_line</code>, <code>read</code>, <code>readpartial</code>, and so on.</p>



<pre class="wp-block-code"><code>require 'socket'

socket = TCPSocket.new('example.com', 80)
socket.write("GE T / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")

while line = socket.gets
  puts line.chomp
end

socket.close
</code></pre>



<p class="wp-block-paragraph">This is important: because <code>TCPSocket</code> is a subclass of <code>IO</code>, anything you already know about file handling in Ruby transfers directly to network handling. That includes buffering behavior, encoding concerns, and the need to always close what you open.</p>



<h2 class="wp-block-heading">Building a TCP Server with TCPServer</h2>



<p class="wp-block-paragraph">While <code>TCPSocket</code> handles the client side, <code>TCPServer</code> handles the listening/accepting side. Here&#8217;s a minimal echo server:</p>



<pre class="wp-block-code"><code>require 'socket'

server = TCPServer.new('127.0.0.1', 4481)
puts "Echo server listening on port 4481..."

loop do
  client = server.accept
  Thread.new(client) do |conn|
    conn.puts "Welcome! Type something and I'll echo it back."
    while line = conn.gets
      conn.puts "Echo: #{line.chomp}"
    end
    conn.close
  end
end
</code></pre>



<p class="wp-block-paragraph"><strong>What&#8217;s happening internally:</strong></p>



<ul class="wp-block-list">
<li><code>TCPServer.new</code> calls <code>socket()</code>, <code>bind()</code>, and <code>listen()</code> under the hood, putting the socket into a passive listening state on the specified address and port.</li>



<li><code>server.accept</code> blocks until a client connects, then returns a new <code>TCPSocket</code> object representing that specific connection. The original listening socket stays open to accept further connections.</li>



<li>Wrapping each connection in <code>Thread.new</code> lets the server handle multiple clients concurrently, since <code>accept</code> and <code>gets</code> are both blocking calls that would otherwise serialize every client behind the current one.</li>
</ul>



<p class="wp-block-paragraph">You can test this server from another terminal using <code>telnet</code> or <code>nc</code>:</p>



<pre class="wp-block-code"><code>$ nc 127.0.0.1 4481
Welcome! Type something and I'll echo it back.
hello
Echo: hello
</code></pre>



<h3 class="wp-block-heading">A Word on Thread-Per-Connection Servers</h3>



<p class="wp-block-paragraph">The thread-per-connection pattern above is simple and works well for low-to-moderate connection counts, but it doesn&#8217;t scale indefinitely. Each Ruby <code>Thread</code> maps to a native OS thread (in MRI/CRuby), and each carries real memory overhead — typically a few hundred KB to a few MB for its stack, depending on OS defaults. Thousands of concurrent idle connections will exhaust memory and put pressure on the OS scheduler long before CPU becomes the bottleneck.</p>



<p class="wp-block-paragraph">For high-concurrency servers, production Ruby code typically reaches for:</p>



<ul class="wp-block-list">
<li><strong><code>IO.select</code></strong> or the <code>Reactor</code> pattern for single-threaded, event-driven I/O multiplexing</li>



<li><strong>Fibers</strong> combined with a scheduler (Ruby 3.x&#8217;s <code>Fiber::Scheduler</code>) for lightweight, cooperative concurrency</li>



<li>Battle-tested libraries like <strong>EventMachine</strong>, <strong>Async</strong>, or web servers like <strong>Puma</strong> and <strong>Falcon</strong> that already solve this problem</li>
</ul>



<h2 class="wp-block-heading">Working with UDPSocket</h2>



<p class="wp-block-paragraph">UDP communication in Ruby follows a similar but simpler pattern since there&#8217;s no connection to establish or tear down.</p>



<h3 class="wp-block-heading">UDP Sender</h3>



<pre class="wp-block-code"><code>require 'socket'

socket = UDPSocket.new
socket.send("Hello via UDP!", 0, '127.0.0.1', 4482)
socket.close
</code></pre>



<h3 class="wp-block-heading">UDP Receiver</h3>



<pre class="wp-block-code"><code>require 'socket'

socket = UDPSocket.new
socket.bind('127.0.0.1', 4482)
puts "UDP listener ready on port 4482..."

loop do
  message, sender_info = socket.recvfrom(1024)
  puts "Received: #{message} from #{sender_info&#91;3]}:#{sender_info&#91;1]}"
end
</code></pre>



<p class="wp-block-paragraph"><strong>Output when a message arrives:</strong></p>



<pre class="wp-block-code"><code>UDP listener ready on port 4482...
Received: Hello via UDP! from 127.0.0.1:53211
</code></pre>



<p class="wp-block-paragraph">Notice <code>recvfrom</code> returns both the message and metadata about the sender (<code>sender_info</code>), since — unlike TCP — a UDP socket isn&#8217;t bound to a single peer. This is exactly why UDP is well suited to scenarios like a DNS server or a metrics collector that needs to accept messages from many different, unpredictable sources without maintaining per-client state.</p>



<h3 class="wp-block-heading">Practical Example: A Simple UDP-Based Logger</h3>



<p class="wp-block-paragraph">A common real-world use of UDP is fire-and-forget logging, where an application sends log events to a central collector without waiting for acknowledgment (this is essentially how StatsD works):</p>



<pre class="wp-block-code"><code>require 'socket'
require 'json'

class UDPLogger
  def initialize(host = '127.0.0.1', port = 9999)
    @socket = UDPSocket.new
    @host = host
    @port = port
  end

  def log(event, data = {})
    payload = { event: event, data: data, timestamp: Time.now.to_f }.to_json
    @socket.send(payload, 0, @host, @port)
  end
end

logger = UDPLogger.new
logger.log('user_signup', user_id: 42, plan: 'pro')
</code></pre>



<p class="wp-block-paragraph">Because UDP doesn&#8217;t block waiting for a response, this call returns almost instantly, making it safe to sprinkle throughout hot code paths without introducing latency.</p>



<h2 class="wp-block-heading">Object-Oriented Design Around Sockets</h2>



<p class="wp-block-paragraph">Raw socket code tends to get messy fast if scattered directly through application logic. Idiomatic Ruby wraps socket behavior inside purpose-built classes, leaning on Ruby&#8217;s object model.</p>



<pre class="wp-block-code"><code>require 'socket'

class ChatClient
  def initialize(host, port)
    @socket = TCPSocket.new(host, port)
  end

  def send_message(text)
    @socket.puts(text)
  end

  def listen(&amp;block)
    Thread.new do
      while (line = @socket.gets)
        block.call(line.chomp)
      end
    end
  end

  def close
    @socket.close
  end
end

client = ChatClient.new('127.0.0.1', 4481)
client.listen { |msg| puts "Server says: #{msg}" }
client.send_message("hello from the client")
sleep 1
client.close
</code></pre>



<p class="wp-block-paragraph">This design follows encapsulation — the caller never touches the raw <code>TCPSocket</code> directly, which means the underlying transport could later be swapped (say, for a <code>UNIXSocket</code> in tests) without changing any calling code. This is the same principle behind Ruby&#8217;s duck typing: as long as an object responds to the right methods, it can stand in for a socket.</p>



<h2 class="wp-block-heading">Internal Working: Sockets, File Descriptors, and the OS</h2>



<p class="wp-block-paragraph">It helps to understand what&#8217;s actually happening beneath Ruby&#8217;s abstractions:</p>



<ol class="wp-block-list">
<li><strong>File descriptors.</strong> Every socket Ruby creates is backed by an OS-level file descriptor, the same kind of integer handle used for open files. This is why <code>TCPSocket</code> and <code>UDPSocket</code> both inherit from <code>IO</code> — at the OS layer, sockets and files are accessed through the same read/write system calls.</li>



<li><strong>Kernel buffers.</strong> Data written via <code>write</code> or <code>send</code> doesn&#8217;t go directly onto the wire; it&#8217;s copied into a kernel-managed send buffer, and the kernel&#8217;s network stack handles actual transmission, retransmission (for TCP), and flow control.</li>



<li><strong>Blocking vs non-blocking I/O.</strong> By default, socket operations in Ruby block the calling thread until data is available or the buffer has room. Methods like <code>read_nonblock</code> and <code>write_nonblock</code> exist for building non-blocking, event-driven systems, but they require careful handling of <code>IO::WaitReadable</code> and <code>IO::WaitWritable</code> exceptions.</li>



<li><strong>Garbage collection and sockets.</strong> A <code>TCPSocket</code> object is a Ruby object like any other, subject to garbage collection. However, GC only reclaims Ruby-level memory — it does <strong>not</strong> guarantee the underlying file descriptor is closed promptly. Leaving sockets to be closed by the GC&#8217;s finalizer is a common source of &#8220;too many open files&#8221; errors in long-running services. Always close sockets explicitly, ideally with <code>ensure</code> or a block form.</li>
</ol>



<pre class="wp-block-code"><code>require 'socket'

TCPSocket.open('example.com', 80) do |socket|
  socket.write("GE T / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")
  puts socket.read
end
# socket is automatically closed here, even if an exception occurs
</code></pre>



<h2 class="wp-block-heading">Performance Considerations</h2>



<ul class="wp-block-list">
<li><strong>Buffering.</strong> Reading one byte at a time is expensive because each <code>read</code> call is a system call. Prefer reading in reasonably sized chunks (<code>socket.read(4096)</code>) or using buffered methods like <code>gets</code> for line-oriented protocols.</li>



<li><strong>Nagle&#8217;s Algorithm.</strong> TCP by default batches small writes together to reduce packet overhead, which can add latency for latency-sensitive protocols. You can disable this with <code>socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)</code> when you need every write flushed immediately.</li>



<li><strong>Thread overhead.</strong> As mentioned earlier, thread-per-connection models don&#8217;t scale past a few thousand connections. For high-throughput servers, non-blocking I/O with <code>IO.select</code> or a reactor-based gem is the more scalable path.</li>



<li><strong>UDP packet size.</strong> UDP datagrams larger than the network&#8217;s MTU (typically 1500 bytes on Ethernet) get fragmented at the IP layer, which increases the chance of packet loss since losing any one fragment loses the whole datagram. Keeping UDP payloads under roughly 512–1400 bytes is a common safe practice.</li>
</ul>



<h2 class="wp-block-heading">Common Mistakes and Debugging Tips</h2>



<ul class="wp-block-list">
<li><strong>Forgetting to close sockets.</strong> This leaks file descriptors and will eventually crash a long-running process with <code>Errno::EMFILE</code>. Use <code>TCPSocket.open</code> with a block, or <code>ensure socket.close</code>.</li>



<li><strong>Assuming <code>read</code> returns everything at once.</strong> TCP is a stream; a single <code>write</code> on one end can arrive as multiple <code>read</code>s on the other, and vice versa. Never assume message boundaries align with individual read/write calls — build your own framing (e.g., newline-delimited messages, or length-prefixed messages) into your protocol.</li>



<li><strong>Ignoring <code>Errno::ECONNRESET</code> and <code>Errno::EPIPE</code>.</strong> Network connections can drop at any time. Production code should rescue these and handle reconnection or cleanup gracefully rather than letting the process crash.</li>



<li><strong>Blocking the whole server on one slow client.</strong> In a naive loop without threading, one slow or malicious client can stall every other connection. Always isolate per-connection work.</li>



<li><strong>Using UDP where you need reliability.</strong> If your application logic assumes messages always arrive and arrive in order, UDP is the wrong transport — you&#8217;d be reimplementing TCP badly. Use UDP only when occasional loss is genuinely acceptable.</li>
</ul>



<p class="wp-block-paragraph">Debugging network code is easier with the right tools:</p>



<pre class="wp-block-code"><code># Watch what's happening on a port
$ sudo tcpdump -i lo0 port 4481

# Check what's currently listening
$ lsof -i :4481

# Simple manual TCP testing
$ nc 127.0.0.1 4481
</code></pre>



<h2 class="wp-block-heading">Real-World Applications</h2>



<ul class="wp-block-list">
<li><strong>Custom protocol servers</strong> — chat systems, multiplayer game servers, IoT device gateways</li>



<li><strong>Health checks and service discovery</strong> — lightweight TCP &#8220;ping&#8221; checks between microservices</li>



<li><strong>Log and metrics shipping</strong> — UDP-based fire-and-forget telemetry (StatsD-style)</li>



<li><strong>Proxying and tunneling</strong> — building lightweight TCP proxies for local development</li>



<li><strong>Testing HTTP clients/servers</strong> — raw sockets are often used in test suites to simulate malformed or edge-case server responses that higher-level HTTP libraries won&#8217;t let you construct</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby&#8217;s socket library gives you direct, unopinionated access to the same networking primitives used across the industry, wrapped in an object-oriented, IO-compatible interface. <code>TCPSocket</code> and <code>TCPServer</code> cover reliable, connection-oriented communication for anything where message integrity and order matter, while <code>UDPSocket</code> covers lightweight, connectionless communication where speed matters more than guaranteed delivery. Understanding what happens beneath these classes — file descriptors, kernel buffers, blocking behavior, and the cost of thread-per-connection models — is what separates code that works in a demo from code that survives in production. Combine that understanding with disciplined resource cleanup, sensible framing of your protocol, and awareness of where non-blocking I/O becomes necessary, and Ruby is a genuinely capable language for serious network programming.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li><a href="https://docs.ruby-lang.org/en/master/Socket.html">Ruby Socket Library Documentation</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/TCPSocket.html">TCPSocket — Ruby Standard Library</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/TCPServer.html">TCPServer — Ruby Standard Library</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/UDPSocket.html">UDPSocket — Ruby Standard Library</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/IO.html">Ruby IO Class Documentation</a></li>



<li><a href="https://rubygems.org/gems/async">RubyGems — Async Gem for Event-Driven I/O</a></li>



<li><a href="https://rubygems.org/gems/eventmachine">RubyGems — EventMachine</a></li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ruby/socket-and-network-libraries-in-ruby-complete-guide-to-network-programming-with-tcpsocket-and-udpsocket/">Socket and Network Libraries in Ruby: Complete Guide to Network Programming with TCPSocket and UDPSocket</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/socket-and-network-libraries-in-ruby-complete-guide-to-network-programming-with-tcpsocket-and-udpsocket/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4508</post-id>	</item>
		<item>
		<title>Controlling the Thread Scheduler in Ruby: Thread Management, Fiber, and Concurrency Control Explained</title>
		<link>https://awjunaid.com/ruby/controlling-the-thread-scheduler-in-ruby-thread-management-fiber-and-concurrency-control-explained/</link>
					<comments>https://awjunaid.com/ruby/controlling-the-thread-scheduler-in-ruby-thread-management-fiber-and-concurrency-control-explained/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Fri, 01 Sep 2023 19:55:03 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4505</guid>

					<description><![CDATA[<p>Concurrency in Ruby is one of those topics that trips up even experienced developers, mostly because Ruby offers&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/controlling-the-thread-scheduler-in-ruby-thread-management-fiber-and-concurrency-control-explained/">Controlling the Thread Scheduler in Ruby: Thread Management, Fiber, and Concurrency Control Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Concurrency in Ruby is one of those topics that trips up even experienced developers, mostly because Ruby offers several different concurrency primitives — threads, fibers, and the newer <code>Fiber::Scheduler</code> — that solve overlapping but distinct problems. Understanding how Ruby actually schedules work, what the Global VM Lock does, and when to reach for a <code>Thread</code> versus a <code>Fiber</code> is the difference between writing concurrent Ruby code that scales and writing concurrent Ruby code that quietly serializes everything anyway.</p>



<p class="wp-block-paragraph">This guide covers Ruby&#8217;s concurrency model end to end: how the thread scheduler works internally, how to manage threads directly, how fibers give you fine-grained control over execution, and how modern Ruby lets you influence scheduling decisions that used to be entirely opaque.</p>



<h2 class="wp-block-heading">Ruby&#8217;s Concurrency Model: The Big Picture</h2>



<p class="wp-block-paragraph">Before touching any code, it&#8217;s worth being precise about terms Ruby developers often use loosely:</p>



<ul class="wp-block-list">
<li><strong>Concurrency</strong> is about structuring a program to handle multiple tasks that can be in progress at once, even if only one is actually executing at any given instant.</li>



<li><strong>Parallelism</strong> is about literally executing multiple tasks at the same instant, on multiple CPU cores.</li>
</ul>



<p class="wp-block-paragraph">In MRI (Matz&#8217;s Ruby Interpreter, the reference implementation most people mean when they say &#8220;Ruby&#8221;), threads give you concurrency but generally <strong>not</strong> parallelism for pure Ruby code, because of the Global VM Lock.</p>



<h2 class="wp-block-heading">The Global VM Lock (GVL/GIL)</h2>



<p class="wp-block-paragraph">MRI has a Global VM Lock (historically called the GIL, Global Interpreter Lock) that ensures only one thread executes Ruby code at a time, even on a multi-core machine. This exists because MRI&#8217;s internal object model and garbage collector are not thread-safe by design, and the GVL is the mechanism that protects them.</p>



<pre class="wp-block-code"><code>require 'benchmark'

def cpu_heavy_task
  1_000_000.times { |i| i * i }
end

# Two threads doing CPU-bound work
time = Benchmark.realtime do
  t1 = Thread.new { cpu_heavy_task }
  t2 = Thread.new { cpu_heavy_task }
  t1.join
  t2.join
end

puts "Two threads: #{time.round(3)}s"
</code></pre>



<p class="wp-block-paragraph">Run this and you&#8217;ll find it&#8217;s roughly the same speed as running the two tasks sequentially — sometimes even slightly slower due to context-switching overhead. That&#8217;s the GVL at work: only one thread actually runs Ruby bytecode at any instant, so CPU-bound work doesn&#8217;t parallelize across threads in MRI.</p>



<p class="wp-block-paragraph"><strong>Where threads do help</strong> is I/O-bound work. The GVL is released whenever a thread performs a blocking I/O operation (reading a file, waiting on a network socket, querying a database), letting another thread run during that wait:</p>



<pre class="wp-block-code"><code>require 'net/http'
require 'benchmark'

urls = &#91;'https://example.com'] * 5

time = Benchmark.realtime do
  threads = urls.map do |url|
    Thread.new { Net::HTTP.get(URI(url)) }
  end
  threads.each(&amp;:join)
end

puts "Five requests concurrently: #{time.round(3)}s"
</code></pre>



<p class="wp-block-paragraph">Here, while one thread waits on a network response, the GVL is free for another thread to make progress — so five concurrent HTTP requests complete in roughly the time of the slowest one, not the sum of all five.</p>



<h2 class="wp-block-heading">Thread Management Fundamentals</h2>



<h3 class="wp-block-heading">Creating and Controlling Threads</h3>



<pre class="wp-block-code"><code>thread = Thread.new do
  puts "Running in a new thread"
  sleep 1
  puts "Thread finishing"
end

puts "Main thread continues immediately"
thread.join  # Block main thread until 'thread' finishes
puts "Both threads are done"
</code></pre>



<p class="wp-block-paragraph"><strong>Output:</strong></p>



<pre class="wp-block-code"><code>Main thread continues immediately
Running in a new thread
Thread finishing
Both threads are done
</code></pre>



<p class="wp-block-paragraph">Key thread lifecycle methods:</p>



<pre class="wp-block-code"><code>t = Thread.new { sleep 2 }

t.alive?     # =&gt; true, while running
t.status     # =&gt; "sleep", "run", "aborting", false (finished normally), or nil (finished with exception)
t.join(1)    # wait up to 1 second, then return even if not finished
t.kill       # forcibly terminate the thread (use sparingly)
t.value      # blocks until the thread finishes, then returns its final expression's value
</code></pre>



<h3 class="wp-block-heading">Passing Data Into Threads</h3>



<p class="wp-block-paragraph">Always pass data into a <code>Thread.new</code> block as arguments rather than relying on closures over loop variables, especially in older Ruby versions or tight loops:</p>



<pre class="wp-block-code"><code>threads = (1..5).map do |i|
  Thread.new(i) do |n|
    sleep(rand(0.1..0.3))
    puts "Thread #{n} finished"
  end
end
threads.each(&amp;:join)
</code></pre>



<p class="wp-block-paragraph">Passing <code>i</code> explicitly as a block parameter (<code>Thread.new(i) { |n| ... }</code>) avoids subtle bugs where all threads end up referencing the same final value of a shared loop variable.</p>



<h3 class="wp-block-heading">Handling Exceptions in Threads</h3>



<p class="wp-block-paragraph">By default, an exception raised inside a thread does <strong>not</strong> crash the main program — it silently terminates just that thread, unless you check for it:</p>



<pre class="wp-block-code"><code>Thread.abort_on_exception = true  # globally: propagate thread exceptions to main thread

t = Thread.new do
  raise "Something broke inside the thread"
end

begin
  t.join
rescue =&gt; e
  puts "Caught: #{e.message}"
end
</code></pre>



<p class="wp-block-paragraph"><strong>Output:</strong></p>



<pre class="wp-block-code"><code>Caught: Something broke inside the thread
</code></pre>



<p class="wp-block-paragraph">Without <code>abort_on_exception = true</code> (or calling <code>t.join</code>/<code>t.value</code>, which re-raises the stored exception), a failing thread can fail completely silently — a classic source of &#8220;why didn&#8217;t this work?&#8221; bugs in production systems.</p>



<h2 class="wp-block-heading">Thread Synchronization: Mutex, ConditionVariable, and Queue</h2>



<p class="wp-block-paragraph">Even with the GVL, race conditions are very real in Ruby, because the GVL can switch between threads at almost any bytecode boundary — including in the middle of a &#8220;simple&#8221; operation like <code>+=</code> on a shared variable.</p>



<pre class="wp-block-code"><code>counter = 0
mutex = Mutex.new

threads = 10.times.map do
  Thread.new do
    1000.times do
      mutex.synchronize { counter += 1 }
    end
  end
end
threads.each(&amp;:join)

puts counter  # =&gt; 10000, reliably, because of the mutex
</code></pre>



<p class="wp-block-paragraph">Without the <code>mutex.synchronize</code> block, this same code will non-deterministically produce a number less than 10,000, because two threads can read the same value of <code>counter</code> before either writes back the incremented result — a textbook race condition.</p>



<h3 class="wp-block-heading">Thread::Queue for Producer-Consumer Patterns</h3>



<p class="wp-block-paragraph"><code>Thread::Queue</code> is a thread-safe FIFO queue purpose-built for coordinating work between threads, and it&#8217;s usually a better tool than manually managing mutexes for this kind of pattern:</p>



<pre class="wp-block-code"><code>require 'thread'

queue = Queue.new

producer = Thread.new do
  5.times do |i|
    queue &lt;&lt; "job-#{i}"
    puts "Produced job-#{i}"
    sleep 0.1
  end
  queue.close
end

consumer = Thread.new do
  while (job = queue.pop)
    puts "Consumed #{job}"
  end
end

producer.join
consumer.join
</code></pre>



<p class="wp-block-paragraph"><code>Queue#pop</code> blocks automatically when empty and unblocks automatically once a producer adds work, so you get correct coordination without hand-rolling condition variables.</p>



<h2 class="wp-block-heading">Fibers: Cooperative, Fine-Grained Control</h2>



<p class="wp-block-paragraph">Where <code>Thread</code> gives you preemptively scheduled concurrency managed by the VM, <code>Fiber</code> gives you <strong>cooperative</strong> concurrency that you control explicitly. A fiber only yields control when it chooses to, via <code>Fiber.yield</code>, and only resumes when explicitly told to via <code>resume</code>.</p>



<pre class="wp-block-code"><code>fiber = Fiber.new do
  puts "Fiber: step 1"
  Fiber.yield
  puts "Fiber: step 2"
  Fiber.yield
  puts "Fiber: step 3"
end

fiber.resume  # =&gt; "Fiber: step 1"
puts "Main: control returned to me"
fiber.resume  # =&gt; "Fiber: step 2"
fiber.resume  # =&gt; "Fiber: step 3"
</code></pre>



<p class="wp-block-paragraph"><strong>Output:</strong></p>



<pre class="wp-block-code"><code>Fiber: step 1
Main: control returned to me
Fiber: step 2
Fiber: step 3
</code></pre>



<p class="wp-block-paragraph">This is fundamentally different from a thread: there&#8217;s no scheduler deciding when the fiber runs. Execution passes explicitly back and forth between <code>resume</code> and <code>Fiber.yield</code>, like a hand-off between two functions that remember exactly where they left off.</p>



<h3 class="wp-block-heading">Passing Values Between Fiber and Caller</h3>



<pre class="wp-block-code"><code>generator = Fiber.new do |start|
  value = start
  loop do
    value = Fiber.yield(value * 2)
  end
end

puts generator.resume(1)   # =&gt; 2
puts generator.resume(5)   # =&gt; 10
puts generator.resume(10)  # =&gt; 20
</code></pre>



<p class="wp-block-paragraph">This pattern — a fiber acting as a lazily-evaluated generator — is exactly how <code>Enumerator</code> is implemented internally in Ruby. Every time you call <code>.next</code> on a lazy enumerator, you&#8217;re resuming a fiber under the hood.</p>



<pre class="wp-block-code"><code>fib_enum = Enumerator.new do |y|
  a, b = 0, 1
  loop do
    y &lt;&lt; a
    a, b = b, a + b
  end
end

puts fib_enum.take(10).inspect
# =&gt; &#91;0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
</code></pre>



<h2 class="wp-block-heading">Controlling the Thread Scheduler: What You Can and Can&#8217;t Influence</h2>



<p class="wp-block-paragraph">Ruby doesn&#8217;t expose a general-purpose &#8220;set thread priority and it will be honored precisely&#8221; API the way some lower-level languages do, but it does give you real levers.</p>



<h3 class="wp-block-heading">Thread Priority</h3>



<pre class="wp-block-code"><code>low = Thread.new { loop { Thread.pass } }
low.priority = -1

high = Thread.new { puts "High priority work" }
high.priority = 1
</code></pre>



<p class="wp-block-paragraph"><code>Thread#priority=</code> is a <strong>hint</strong> to the VM&#8217;s scheduler, not a hard guarantee — MRI&#8217;s scheduler uses it to bias which runnable thread gets the GVL next, but it doesn&#8217;t preempt a thread mid-execution just because a higher-priority thread became runnable.</p>



<h3 class="wp-block-heading">Thread.pass</h3>



<pre class="wp-block-code"><code>Thread.new do
  5.times do |i|
    puts "Worker: #{i}"
    Thread.pass  # voluntarily yield remaining time slice to another thread
  end
end.join
</code></pre>



<p class="wp-block-paragraph"><code>Thread.pass</code> is a cooperative hint that tells the scheduler &#8220;you can run someone else now if you want,&#8221; useful in tight loops where you want to be a good citizen toward other runnable threads.</p>



<h3 class="wp-block-heading">Fiber::SchedulerInterface (Ruby 3.0+)</h3>



<p class="wp-block-paragraph">The most powerful and modern lever is the <code>Fiber::Scheduler</code> interface, introduced in Ruby 3.0. It lets you implement a custom scheduler object that intercepts blocking operations (<code>sleep</code>, I/O waits, mutex waits) and decides what happens during those waits — typically, running other fibers instead of blocking the whole thread.</p>



<pre class="wp-block-code"><code>require 'fiber'

class SimpleScheduler
  def initialize
    @waiting = &#91;]
  end

  def kernel_sleep(duration)
    @waiting &lt;&lt; &#91;Fiber.current, Time.now + duration]
    Fiber.yield
  end

  def block(blocker, timeout = nil)
    Fiber.yield
  end

  def unblock(blocker, fiber)
    fiber.resume
  end

  def run
    until @waiting.empty?
      @waiting.each do |fiber, ready_at|
        if Time.now &gt;= ready_at
          @waiting.delete(&#91;fiber, ready_at])
          fiber.resume
        end
      end
    end
  end

  def close
    run
  end
end

Fiber.set_scheduler(SimpleScheduler.new)

Fiber.schedule do
  puts "Task A starts"
  sleep 1
  puts "Task A resumes"
end

Fiber.schedule do
  puts "Task B starts"
  sleep 0.5
  puts "Task B resumes"
end
</code></pre>



<p class="wp-block-paragraph">This is a simplified illustration — production schedulers (like the ones inside the <code>async</code> gem) implement the full <code>Fiber::SchedulerInterface</code>, covering <code>io_wait</code>, <code>io_read</code>, <code>io_write</code>, <code>process_wait</code>, and more. But the core idea is exactly what&#8217;s shown here: <strong>you get to define what &#8220;waiting&#8221; means</strong>, replacing thread-blocking I/O with fiber-yielding I/O, so thousands of lightweight fibers can share a single OS thread efficiently.</p>



<p class="wp-block-paragraph">This is precisely the mechanism modern async Ruby frameworks (like the <code>async</code> gem, and <code>Falcon</code> web server) use to achieve extremely high concurrency without the memory overhead of one OS thread per connection.</p>



<h2 class="wp-block-heading">Internal Working: What Actually Happens During a Context Switch</h2>



<ol class="wp-block-list">
<li><strong>Thread context switches</strong> in MRI involve the VM saving the current thread&#8217;s execution context (its call stack, instruction pointer, and local state) and releasing the GVL, then another runnable thread acquires the GVL and resumes. This happens either voluntarily (blocking I/O, <code>Thread.pass</code>, <code>sleep</code>) or involuntarily, at periodic checkpoints the VM inserts between bytecode instructions (roughly every 100ms of execution by default, configurable via <code>RUBY_THREAD_TIMESLICE</code> in some builds).</li>



<li><strong>Fiber context switches</strong> are far cheaper because there&#8217;s no GVL release/reacquire involved and no OS-level thread switch — a fiber switch just swaps the Ruby-level call stack pointer to a different pre-allocated stack. This is why fibers can comfortably scale into the tens of thousands, while OS threads realistically cap out in the low thousands.</li>



<li><strong>Memory footprint.</strong> Each <code>Thread</code> in MRI allocates a full native OS thread stack, typically defaulting to around 1MB depending on platform (tunable but not trivially so). Each <code>Fiber</code>, by contrast, uses a much smaller allocated stack (historically around 4KB–16KB depending on Ruby version and platform, growing as needed), which is why fiber-based concurrency is dramatically more memory-efficient at scale.</li>
</ol>



<h2 class="wp-block-heading">Common Mistakes and Debugging Tips</h2>



<ul class="wp-block-list">
<li><strong>Assuming threads give CPU parallelism in MRI.</strong> They don&#8217;t, for pure Ruby code, because of the GVL. Use <code>Process.fork</code> or external worker processes (e.g., via <code>Parallel</code> gem or Sidekiq&#8217;s multi-process model) for genuine CPU-bound parallelism, or consider JRuby/TruffleRuby, which don&#8217;t have a GVL.</li>



<li><strong>Forgetting <code>Thread.abort_on_exception = true</code> (or checking <code>thread.value</code>).</strong> Silent thread failures are one of the most common production surprises in Ruby.</li>



<li><strong>Mutating shared state without a Mutex.</strong> Even simple operations like <code>array &lt;&lt; item</code> or <code>hash[key] += 1</code> are not guaranteed atomic across threads; wrap shared mutable state access in <code>Mutex#synchronize</code>.</li>



<li><strong>Deadlocks from nested mutex locking.</strong> Locking the same, non-reentrant mutex twice from the same thread will deadlock. Keep lock scopes small and avoid calling code that might re-acquire the same lock.</li>



<li><strong>Resuming a dead fiber.</strong> Calling <code>.resume</code> on a fiber that has already run to completion raises <code>FiberError: dead fiber called</code>. Track fiber state explicitly if you need to resume conditionally.</li>



<li><strong>Mixing fibers and threads carelessly.</strong> A <code>Fiber</code> is tied to the thread that created it and cannot be resumed from a different thread. Passing a fiber across threads is a common source of confusing <code>FiberError</code> exceptions.</li>
</ul>



<p class="wp-block-paragraph">Debugging tools worth knowing:</p>



<pre class="wp-block-code"><code>Thread.list.each { |t| puts "#{t}: #{t.status}" }  # inspect all live threads

# Ruby's built-in tracing for deep debugging
Thread.new { ... }.report_on_exception = true  # per-thread exception reporting (default true since Ruby 2.5+)
</code></pre>



<h2 class="wp-block-heading">Real-World Applications</h2>



<ul class="wp-block-list">
<li><strong>Web servers</strong> (Puma) use a thread pool per worker process to handle concurrent requests, relying on the GVL releasing during I/O (database queries, external API calls) to serve many requests &#8220;at once.&#8221;</li>



<li><strong>Background job processors</strong> (Sidekiq) use threads for I/O-bound job concurrency within each process, while using multiple OS processes for genuine parallelism.</li>



<li><strong>Async I/O frameworks</strong> (the <code>async</code> gem, <code>Falcon</code> web server) use <code>Fiber::Scheduler</code> to handle tens of thousands of concurrent connections on a single thread, avoiding the memory cost of thread-per-connection.</li>



<li><strong>Lazy data pipelines</strong> use fibers (via <code>Enumerator</code>) to process large or infinite sequences without loading everything into memory at once.</li>



<li><strong>Rate limiters and batch processors</strong> commonly use <code>Thread::Queue</code> to coordinate producer/consumer work safely across a fixed pool of worker threads.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby&#8217;s concurrency toolkit is more nuanced than a single &#8220;use threads&#8221; answer suggests. Threads give you real concurrency for I/O-bound work, governed by the GVL, which means they shine for network calls and database queries but don&#8217;t deliver CPU parallelism in MRI. Fibers give you cheap, cooperative, fully controllable concurrency — the same mechanism quietly powering <code>Enumerator</code> under the hood — and become genuinely powerful once combined with <code>Fiber::Scheduler</code>, which lets modern async frameworks handle massive connection counts on minimal OS resources. Getting comfortable with <code>Mutex</code>, <code>Thread::Queue</code>, and the cooperative yield/resume model of fibers, along with a clear mental model of what the GVL actually does and doesn&#8217;t protect you from, is what turns &#8220;I used threads and it kind of worked&#8221; into concurrent Ruby code you can actually trust in production.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li><a href="https://docs.ruby-lang.org/en/master/Thread.html">Ruby Thread Class Documentation</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Fiber.html">Ruby Fiber Class Documentation</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Thread/Mutex.html">Ruby Mutex (Thread::Mutex) Documentation</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Thread/Queue.html">Ruby Thread::Queue Documentation</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Fiber/SchedulerInterface.html">Fiber::SchedulerInterface Documentation</a></li>



<li><a href="https://rubygems.org/gems/async">RubyGems — async gem</a></li>



<li><a href="https://rubygems.org/gems/sidekiq">RubyGems — Sidekiq</a></li>



<li><a href="https://rubygems.org/gems/parallel">RubyGems — Parallel gem</a></li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ruby/controlling-the-thread-scheduler-in-ruby-thread-management-fiber-and-concurrency-control-explained/">Controlling the Thread Scheduler in Ruby: Thread Management, Fiber, and Concurrency Control Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/controlling-the-thread-scheduler-in-ruby-thread-management-fiber-and-concurrency-control-explained/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4505</post-id>	</item>
		<item>
		<title>Talking to Networks in Ruby: HTTP, FTP, and Client-Server Communication Complete Guide</title>
		<link>https://awjunaid.com/ruby/talking-to-networks-in-ruby-http-ftp-and-client-server-communication-complete-guide/</link>
					<comments>https://awjunaid.com/ruby/talking-to-networks-in-ruby-http-ftp-and-client-server-communication-complete-guide/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Fri, 01 Sep 2023 19:44:04 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4502</guid>

					<description><![CDATA[<p>When I first started writing scripts that needed to reach out beyond my own machine — pulling data&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/talking-to-networks-in-ruby-http-ftp-and-client-server-communication-complete-guide/">Talking to Networks in Ruby: HTTP, FTP, and Client-Server Communication Complete Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">When I first started writing scripts that needed to reach out beyond my own machine — pulling data from an API, uploading a file to a remote server, or just checking if a host was alive — I quickly realized that Ruby&#8217;s networking story is a lot bigger than most tutorials let on. It&#8217;s not just <code>Net::HTTP.get</code>. There&#8217;s a whole stack underneath: sockets, protocols, buffering, timeouts, and a standard library that gives you as much rope as you want to hang yourself with (or build something genuinely solid). In this guide I want to walk through everything I&#8217;ve learned about talking to networks in Ruby, from the lowest-level socket to the highest-level HTTP client, in a way that actually makes sense when you sit down to build something real.</p>



<h2 class="wp-block-heading">Why Networking Matters in Ruby</h2>



<p class="wp-block-paragraph">Ruby isn&#8217;t usually the first language people associate with networking — that reputation tends to go to Go or C — but Ruby has had solid networking support since its earliest days, largely inherited from its Unix roots. Rails itself is built on top of Ruby&#8217;s networking stack, and so is nearly every gem that talks to an external service: <code>httparty</code>, <code>faraday</code>, <code>net-ftp</code>, <code>aws-sdk</code>, you name it. Understanding the layer beneath these gems makes you a far more effective Ruby developer, because when something breaks — a connection resets, a timeout fires, an SSL handshake fails — you need to know what&#8217;s actually happening under the hood.</p>



<h2 class="wp-block-heading">The Building Blocks: Ruby&#8217;s Networking Libraries</h2>



<p class="wp-block-paragraph">Ruby ships with several networking-related libraries in its standard library:</p>



<ul class="wp-block-list">
<li><strong><code>Socket</code></strong> — the lowest-level interface, a thin wrapper around the OS socket API (BSD sockets on Unix-like systems).</li>



<li><strong><code>Net::HTTP</code></strong> — the built-in HTTP client, used for most web requests.</li>



<li><strong><code>Net::FTP</code></strong> — for File Transfer Protocol operations.</li>



<li><strong><code>OpenURI</code></strong> — a convenience layer on top of <code>Net::HTTP</code> (and others) for quick, one-line resource fetching.</li>



<li><strong><code>URI</code></strong> — for parsing and constructing URLs, which almost always accompanies the above.</li>
</ul>



<p class="wp-block-paragraph">Let&#8217;s go through each of these in a logical order: sockets first (because everything else is built on them), then HTTP, then FTP.</p>



<h2 class="wp-block-heading">Sockets: The Foundation</h2>



<p class="wp-block-paragraph">Every network conversation in Ruby, no matter how high-level the API looks, eventually becomes a socket. A socket is just an endpoint for sending and receiving data across a network — think of it as a phone line between two programs.</p>



<p class="wp-block-paragraph">Here&#8217;s a minimal TCP server and client using Ruby&#8217;s <code>Socket</code> library:</p>



<pre class="wp-block-code"><code># server.rb
require 'socket'

server = TCPServer.new('127.0.0.1', 4481)
puts "Server listening on port 4481..."

loop do
  client = server.accept
  request = client.gets
  puts "Received: #{request.chomp}"
  client.puts "Hello, #{request.chomp}! The server says hi."
  client.close
end
</code></pre>



<pre class="wp-block-code"><code># client.rb
require 'socket'

socket = TCPSocket.new('127.0.0.1', 4481)
socket.puts "Ruby Developer"
response = socket.gets
puts response
socket.close
</code></pre>



<p class="wp-block-paragraph">Running the server and then the client produces:</p>



<pre class="wp-block-code"><code>$ ruby server.rb
Server listening on port 4481...
Received: Ruby Developer

$ ruby client.rb
Hello, Ruby Developer! The server says hi.
</code></pre>



<p class="wp-block-paragraph">What&#8217;s happening internally here is worth understanding. <code>TCPServer.new</code> calls the operating system&#8217;s <code>socket()</code>, <code>bind()</code>, and <code>listen()</code> system calls. <code>accept</code> blocks the current thread until a client connects, then hands back a new socket object representing that specific connection. <code>gets</code> and <code>puts</code> on a socket behave almost exactly like they do on <code>STDIN</code>/<code>STDOUT</code>, because <code>Socket</code> objects are a subclass of Ruby&#8217;s <code>IO</code> class — this is one of Ruby&#8217;s nicer design decisions, since it means anything that works with files or standard input generally works with sockets too.</p>



<p class="wp-block-paragraph">One thing that trips people up: <code>TCPServer#accept</code> is a <strong>blocking</strong> call. In a single-threaded script, your server can only handle one client at a time unless you explicitly fork a process or spawn a thread per connection:</p>



<pre class="wp-block-code"><code>loop do
  client = server.accept
  Thread.new(client) do |conn|
    request = conn.gets
    conn.puts "Echo: #{request}"
    conn.close
  end
end
</code></pre>



<p class="wp-block-paragraph">Because of Ruby&#8217;s Global VM Lock (GVL) in MRI, threads don&#8217;t give you true CPU parallelism, but for I/O-bound work like network communication, this is fine — threads release the GVL while waiting on I/O, so a thread-per-connection model scales reasonably well for many concurrent, mostly-idle connections.</p>



<h2 class="wp-block-heading">HTTP: The Workhorse Protocol</h2>



<p class="wp-block-paragraph">Most real-world Ruby networking code talks HTTP, not raw sockets. Ruby&#8217;s built-in <code>Net::HTTP</code> is verbose but complete, and understanding it well means you&#8217;ll never be stuck when a gem like Faraday doesn&#8217;t quite do what you need.</p>



<h3 class="wp-block-heading">A Simple GET Request</h3>



<pre class="wp-block-code"><code>require 'net/http'
require 'uri'
require 'json'

uri = URI('https://api.github.com/users/octocat')
response = Net::HTTP.get_response(uri)

puts response.code       # =&gt; "200"
puts response.message    # =&gt; "OK"

data = JSON.parse(response.body)
puts data&#91;'name']
puts data&#91;'public_repos']
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>200
OK
The Octocat
8
</code></pre>



<h3 class="wp-block-heading">POST Requests with a Body</h3>



<pre class="wp-block-code"><code>require 'net/http'
require 'uri'
require 'json'

uri = URI('https://httpbin.org/post')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri.path, 'Content-Type' =&gt; 'application/json')
request.body = { name: 'Ruby', type: 'language' }.to_json

response = http.request(request)
puts response.code
puts JSON.parse(response.body)&#91;'json']
</code></pre>



<p class="wp-block-paragraph">This gives you:</p>



<pre class="wp-block-code"><code>200
{"name"=&gt;"Ruby", "type"=&gt;"language"}
</code></pre>



<p class="wp-block-paragraph">Notice a few important pieces here. <code>http.use_ssl = true</code> is required for any <code>https://</code> URL — Ruby doesn&#8217;t infer it automatically from the URI scheme when you build the connection this way, which is a classic gotcha. Forgetting this line either raises a connection error or, worse, silently fails depending on your Ruby version.</p>



<h3 class="wp-block-heading">Timeouts and Error Handling</h3>



<p class="wp-block-paragraph">In production code, you should always set explicit timeouts. Without them, a hung connection can block your process indefinitely:</p>



<pre class="wp-block-code"><code>http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.open_timeout = 5   # seconds to establish connection
http.read_timeout = 10  # seconds to wait for response

begin
  response = http.request(request)
rescue Net::OpenTimeout, Net::ReadTimeout =&gt; e
  puts "Request timed out: #{e.message}"
rescue SocketError =&gt; e
  puts "Could not resolve host: #{e.message}"
rescue =&gt; e
  puts "Something went wrong: #{e.class} - #{e.message}"
end
</code></pre>



<h3 class="wp-block-heading">OpenURI: The Quick-and-Dirty Option</h3>



<p class="wp-block-paragraph">For fast, one-off fetches, <code>OpenURI</code> is genuinely convenient:</p>



<pre class="wp-block-code"><code>require 'open-uri'

content = URI.open('https://www.ruby-lang.org').read
puts content.length
</code></pre>



<p class="wp-block-paragraph">I use this for scripts and quick data pulls, but I&#8217;ve learned to avoid it in production HTTP clients — it hides a lot of the configurability (custom headers, retries, connection pooling) that <code>Net::HTTP</code> or a gem like Faraday gives you directly, and it has had a history of security advisories related to how it handles redirects and local file access, so I always pin recent Ruby/OpenURI versions when I use it.</p>



<h2 class="wp-block-heading">FTP: Moving Files Across the Network</h2>



<p class="wp-block-paragraph">FTP feels old-fashioned in a world of S3 buckets and REST APIs, but it&#8217;s still alive in plenty of legacy systems — payment processors, government data feeds, and internal enterprise tools still use it constantly. Ruby&#8217;s <code>Net::FTP</code> (distributed as the <code>net-ftp</code> gem since Ruby 3.1, since many standard libraries were unbundled) handles this cleanly.</p>



<pre class="wp-block-code"><code>require 'net/ftp'

Net::FTP.open('ftp.example.com', username: 'myuser', password: 'mypass') do |ftp|
  ftp.passive = true
  puts ftp.pwd
  puts ftp.list.first(5)

  ftp.chdir('/reports')
  ftp.get('quarterly_report.csv', 'local_report.csv')

  ftp.putbinaryfile('local_upload.zip', 'remote_upload.zip')
end
</code></pre>



<p class="wp-block-paragraph">A few notes from experience:</p>



<ul class="wp-block-list">
<li><strong>Always use passive mode</strong> (<code>ftp.passive = true</code>) unless you have a specific reason not to. Active mode requires the server to connect back to your client, which almost never works behind NAT or a firewall.</li>



<li><code>get</code> and <code>put</code> transfer files in text mode by default, which can corrupt binary files like images or zip archives — use <code>getbinaryfile</code> and <code>putbinaryfile</code> for anything that isn&#8217;t plain text.</li>



<li>FTP credentials go over the wire unencrypted unless you&#8217;re using FTPS (<code>Net::FTP.new(host, ssl: true)</code>) or switching to SFTP entirely (which is a different protocol built on SSH, handled by the separate <code>net-sftp</code> gem).</li>
</ul>



<h2 class="wp-block-heading">Internal Working: What Happens Under the Hood</h2>



<p class="wp-block-paragraph">It&#8217;s worth understanding what&#8217;s actually going on when you call <code>Net::HTTP.get</code>. Ruby opens a TCP socket to the target host and port (443 for HTTPS, 80 for HTTP), performs a TCP three-way handshake, and — for HTTPS — layers a TLS handshake on top using OpenSSL bindings compiled into Ruby. Once the encrypted channel exists, Ruby writes the raw HTTP request line, headers, and body as plain text (even though it&#8217;s flowing through an encrypted socket), then reads the response back the same way: status line, headers, then body, following the HTTP/1.1 spec&#8217;s rules about <code>Content-Length</code> and chunked transfer encoding.</p>



<p class="wp-block-paragraph">Every <code>Net::HTTP</code> connection object wraps a <code>TCPSocket</code> (or <code>OpenSSL::SSL::SSLSocket</code> for HTTPS) internally. Ruby&#8217;s <code>IO</code> buffering means reads and writes aren&#8217;t hitting the kernel on every single call — there&#8217;s a buffer in userspace that Ruby fills and drains, which is part of why explicit <code>flush</code> calls matter in some low-level socket code but rarely matter with <code>Net::HTTP</code>, since it handles buffering correctly for you.</p>



<p class="wp-block-paragraph">Memory-wise, response bodies are read fully into a Ruby <code>String</code> by default unless you stream them. For large files, use block-form reading to avoid loading gigabytes into memory:</p>



<pre class="wp-block-code"><code>http.request(request) do |response|
  response.read_body do |chunk|
    file.write(chunk)
  end
end
</code></pre>



<h2 class="wp-block-heading">Real-World Applications</h2>



<p class="wp-block-paragraph">I&#8217;ve used the patterns above for:</p>



<ul class="wp-block-list">
<li><strong>API integrations</strong> — pulling data from third-party REST APIs, handling pagination, retries, and rate limits.</li>



<li><strong>Webhook receivers</strong> — small Sinatra or plain <code>TCPServer</code>-based services listening for incoming POST requests from services like Stripe or GitHub.</li>



<li><strong>Health check scripts</strong> — simple TCP socket checks (<code>TCPSocket.new(host, port)</code> inside a <code>Timeout.timeout</code> block) to verify a service is reachable before deploying.</li>



<li><strong>Legacy data sync jobs</strong> — nightly cron scripts that pull CSV exports off a partner&#8217;s FTP server and load them into a database.</li>
</ul>



<h2 class="wp-block-heading">Best Practices</h2>



<p class="wp-block-paragraph">A few things I&#8217;ve learned to do consistently:</p>



<ol class="wp-block-list">
<li><strong>Always set timeouts.</strong> Every HTTP or socket connection should have both an open timeout and a read timeout.</li>



<li><strong>Rescue specific exceptions</strong>, not a blanket <code>rescue => e</code> that swallows everything silently.</li>



<li><strong>Reuse connections</strong> where possible using <code>Net::HTTP.start</code> with a block, rather than opening a fresh TCP connection for every request.</li>



<li><strong>Verify SSL certificates.</strong> Never set <code>http.verify_mode = OpenSSL::SSL::VERIFY_NONE</code> outside of local debugging — it disables protection against man-in-the-middle attacks.</li>



<li><strong>Close what you open.</strong> Sockets and file handles left open leak resources; prefer block forms (<code>Net::HTTP.start(...) { ... }</code>, <code>Net::FTP.open(...) { ... }</code>) which close automatically.</li>



<li><strong>Reach for a gem like Faraday or HTTParty</strong> once your HTTP needs grow beyond simple requests — they add retry logic, middleware, and cleaner syntax on top of <code>Net::HTTP</code>.</li>
</ol>



<h2 class="wp-block-heading">Common Mistakes</h2>



<ul class="wp-block-list">
<li>Forgetting <code>use_ssl = true</code> for HTTPS URLs.</li>



<li>Not handling redirects — <code>Net::HTTP</code> does <strong>not</strong> follow redirects automatically; you have to check for <code>Net::HTTPRedirection</code> and re-request the <code>Location</code> header yourself.</li>



<li>Reading entire large responses into memory instead of streaming.</li>



<li>Using active-mode FTP behind a firewall and wondering why the connection hangs.</li>



<li>Assuming <code>gets</code> on a socket won&#8217;t block forever — always wrap blocking socket calls in <code>Timeout.timeout</code> or set socket-level timeouts.</li>
</ul>



<h2 class="wp-block-heading">Debugging Tips</h2>



<p class="wp-block-paragraph">When something isn&#8217;t working, <code>Net::HTTP</code> has a built-in debug flag that&#8217;s saved me hours:</p>



<pre class="wp-block-code"><code>http.set_debug_output($stdout)
</code></pre>



<p class="wp-block-paragraph">This prints the raw request and response, including headers, straight to your terminal — invaluable for spotting a missing header or an unexpected redirect. For raw socket issues, tools like <code>tcpdump</code> or <code>Wireshark</code> outside of Ruby are your best friends when you need to see exactly what&#8217;s crossing the wire.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby gives you a full spectrum of networking tools: raw <code>Socket</code> objects when you need full control, <code>Net::HTTP</code> for the vast majority of web communication, and <code>Net::FTP</code> for the file-transfer use cases that refuse to die. Understanding how these layer on top of each other — sockets underneath, protocols on top, your application logic on top of that — makes debugging network issues far less mysterious. Start with the standard library, understand what it&#8217;s really doing, and only reach for a heavier HTTP gem once you know exactly what problem it&#8217;s solving for you.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>Ruby&#8217;s official <code>Net::HTTP</code> documentation: https://docs.ruby-lang.org/en/master/Net/HTTP.html</li>



<li>Ruby&#8217;s official <code>Socket</code> documentation: https://docs.ruby-lang.org/en/master/Socket.html</li>



<li><code>net-ftp</code> gem on RubyGems: https://rubygems.org/gems/net-ftp</li>



<li><code>OpenURI</code> documentation: https://docs.ruby-lang.org/en/master/OpenURI.html</li>



<li>Faraday gem: https://rubygems.org/gems/faraday</li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ruby/talking-to-networks-in-ruby-http-ftp-and-client-server-communication-complete-guide/">Talking to Networks in Ruby: HTTP, FTP, and Client-Server Communication Complete Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/talking-to-networks-in-ruby-http-ftp-and-client-server-communication-complete-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4502</post-id>	</item>
		<item>
		<title>Basic Input and Output in Ruby: gets, puts, print, and File I/O Operations Explained</title>
		<link>https://awjunaid.com/ruby/basic-input-and-output-in-ruby-gets-puts-print-and-file-i-o-operations-explained/</link>
					<comments>https://awjunaid.com/ruby/basic-input-and-output-in-ruby-gets-puts-print-and-file-i-o-operations-explained/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Fri, 01 Sep 2023 19:42:25 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4499</guid>

					<description><![CDATA[<p>Every programmer&#8217;s first real program usually involves printing something to the screen or reading something typed by a&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/basic-input-and-output-in-ruby-gets-puts-print-and-file-i-o-operations-explained/">Basic Input and Output in Ruby: gets, puts, print, and File I/O Operations Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Every programmer&#8217;s first real program usually involves printing something to the screen or reading something typed by a user, and Ruby makes that step almost deceptively easy. But I remember being surprised, once I started building actual tools with Ruby — CLI utilities, log parsers, config readers — at how much depth was hiding behind <code>puts</code> and <code>gets</code>. In this article I want to walk through Ruby&#8217;s input and output model properly: the console methods everyone learns first, the differences between them that actually matter, and then the file I/O operations you&#8217;ll need the moment you move past toy scripts.</p>



<h2 class="wp-block-heading">The Console Basics: puts, print, and p</h2>



<p class="wp-block-paragraph">Ruby gives you three main ways to write to the standard output, and each behaves differently in ways that matter more than people expect.</p>



<h3 class="wp-block-heading">puts</h3>



<p class="wp-block-paragraph"><code>puts</code> writes its argument followed by a newline. If the argument already ends in a newline, it won&#8217;t add a second one. If you pass an array, <code>puts</code> prints each element on its own line.</p>



<pre class="wp-block-code"><code>puts "Hello, Ruby!"
puts &#91;"apple", "banana", "cherry"]
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Hello, Ruby!
apple
banana
cherry
</code></pre>



<h3 class="wp-block-heading">print</h3>



<p class="wp-block-paragraph"><code>print</code> writes its argument with no trailing newline and no automatic array flattening the way <code>puts</code> does — array elements are just joined without separators.</p>



<pre class="wp-block-code"><code>print "Loading"
print "."
print "."
print "."
puts   # just to move to a new line after
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Loading...
</code></pre>



<h3 class="wp-block-heading">p</h3>



<p class="wp-block-paragraph"><code>p</code> is the one people forget about, but it&#8217;s the one I use most while debugging. It calls <code>.inspect</code> on its argument instead of <code>.to_s</code>, which means it shows you the <em>literal</em> Ruby representation of an object — quotes around strings, <code>nil</code> shown explicitly, and so on.</p>



<pre class="wp-block-code"><code>name = "Ruby"
puts name   # Ruby
p name      # "Ruby"

value = nil
puts value  # (prints nothing, blank line)
p value     # nil
</code></pre>



<p class="wp-block-paragraph">This difference matters a lot in practice. If you&#8217;re debugging why a string has trailing whitespace, <code>puts</code> will hide it from you — <code>p</code> won&#8217;t.</p>



<pre class="wp-block-code"><code>mystery = "hello   "
puts mystery   # hello    (you can't see the trailing spaces)
p mystery      # "hello   " (now you can)
</code></pre>



<p class="wp-block-paragraph">There&#8217;s also <code>pp</code> (pretty print), useful for deeply nested hashes and arrays, and <code>print</code> combined with <code>$stdout.flush</code> when you need output to appear immediately without buffering delays — important in long-running scripts with progress indicators.</p>



<h2 class="wp-block-heading">Reading Input: gets</h2>



<p class="wp-block-paragraph"><code>gets</code> reads a line of text from standard input, including the trailing newline character, which is why you&#8217;ll almost always see it chained with <code>.chomp</code>:</p>



<pre class="wp-block-code"><code>print "What's your name? "
name = gets.chomp
puts "Nice to meet you, #{name}!"
</code></pre>



<p class="wp-block-paragraph">Running this interactively:</p>



<pre class="wp-block-code"><code>What's your name? Ada
Nice to meet you, Ada!
</code></pre>



<p class="wp-block-paragraph">Without <code>.chomp</code>, <code>name</code> would actually contain <code>"Ada\n"</code>, and any string comparison or concatenation downstream would behave unexpectedly — this is one of the most common beginner bugs in Ruby CLI scripts.</p>



<p class="wp-block-paragraph">If you need a number instead of a string, <code>gets</code> still returns a <code>String</code>, so you have to convert it explicitly:</p>



<pre class="wp-block-code"><code>print "Enter your age: "
age = gets.chomp.to_i
puts "In 10 years you'll be #{age + 10}."
</code></pre>



<p class="wp-block-paragraph">One quirk worth knowing: <code>to_i</code> silently returns <code>0</code> if it can&#8217;t parse a number, rather than raising an error. So <code>"abc".to_i</code> is <code>0</code>, not an exception. If you need strict validation, use <code>Integer("abc")</code> instead, which raises <code>ArgumentError</code> on bad input — genuinely useful when you want to catch malformed user input rather than silently treating it as zero.</p>



<pre class="wp-block-code"><code>begin
  age = Integer(gets.chomp)
rescue ArgumentError
  puts "That's not a valid number."
end
</code></pre>



<h2 class="wp-block-heading">STDIN, STDOUT, and STDERR</h2>



<p class="wp-block-paragraph">Under the hood, <code>gets</code> and <code>puts</code> are just convenience methods that operate on the global <code>$stdin</code> and <code>$stdout</code> streams (technically they&#8217;re defined on <code>Kernel</code>, and delegate to these streams). You can address them directly:</p>



<pre class="wp-block-code"><code>STDOUT.puts "This goes to standard output"
STDERR.puts "This goes to standard error"
line = STDIN.gets
</code></pre>



<p class="wp-block-paragraph">This distinction matters the moment you write a script meant to be piped or redirected in a shell. Errors and diagnostic messages belong on <code>STDERR</code> so they don&#8217;t pollute output that might be piped into another program:</p>



<pre class="wp-block-code"><code>def process(data)
  raise "empty input" if data.nil?
  data.upcase
end

begin
  result = process(nil)
rescue =&gt; e
  STDERR.puts "Error: #{e.message}"
  exit 1
end
</code></pre>



<p class="wp-block-paragraph">Running <code>ruby script.rb &gt; output.txt</code> will send the error to your terminal while <code>output.txt</code> stays clean, because <code>STDERR</code> was never redirected.</p>



<h2 class="wp-block-heading">File I/O: Reading and Writing Files</h2>



<p class="wp-block-paragraph">Once you move beyond talking to a human at a terminal, you&#8217;ll spend most of your I/O time reading and writing files. Ruby&#8217;s <code>File</code> class (a subclass of <code>IO</code>) covers this comprehensively.</p>



<h3 class="wp-block-heading">Writing to a File</h3>



<pre class="wp-block-code"><code>File.open("notes.txt", "w") do |file|
  file.puts "First line"
  file.puts "Second line"
end
</code></pre>



<p class="wp-block-paragraph">The <code>"w"</code> mode truncates the file if it exists, or creates it if it doesn&#8217;t. Using the block form is important — Ruby automatically closes the file handle when the block ends, even if an exception is raised inside it. This is the single most important habit to build with file I/O in Ruby.</p>



<h3 class="wp-block-heading">Appending to a File</h3>



<pre class="wp-block-code"><code>File.open("notes.txt", "a") do |file|
  file.puts "Third line, appended later"
end
</code></pre>



<h3 class="wp-block-heading">Reading an Entire File</h3>



<pre class="wp-block-code"><code>content = File.read("notes.txt")
puts content
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>First line
Second line
Third line, appended later
</code></pre>



<h3 class="wp-block-heading">Reading Line by Line</h3>



<p class="wp-block-paragraph">For large files, reading the whole thing into memory with <code>File.read</code> is wasteful. Use <code>each_line</code> or <code>File.foreach</code> to stream through it:</p>



<pre class="wp-block-code"><code>File.foreach("notes.txt") do |line|
  puts "Line: #{line.chomp}"
end
</code></pre>



<p class="wp-block-paragraph">Or, using an open file handle:</p>



<pre class="wp-block-code"><code>File.open("notes.txt", "r") do |file|
  file.each_line do |line|
    puts line.chomp.upcase
  end
end
</code></pre>



<h3 class="wp-block-heading">readlines</h3>



<p class="wp-block-paragraph">If you genuinely need every line as an array (say, to process it out of order), <code>readlines</code> gives you that, at the cost of loading the whole file into memory:</p>



<pre class="wp-block-code"><code>lines = File.readlines("notes.txt")
puts lines.length
puts lines.first
</code></pre>



<h3 class="wp-block-heading">Checking Existence and Metadata</h3>



<pre class="wp-block-code"><code>if File.exist?("notes.txt")
  puts "Size: #{File.size("notes.txt")} bytes"
  puts "Last modified: #{File.mtime("notes.txt")}"
else
  puts "File not found"
end
</code></pre>



<h2 class="wp-block-heading">Internal Working: How Ruby&#8217;s IO Actually Behaves</h2>



<p class="wp-block-paragraph"><code>File</code> inherits from <code>IO</code>, and understanding <code>IO</code> explains a lot of behavior you&#8217;ll bump into. Ruby&#8217;s <code>IO</code> objects wrap a file descriptor provided by the operating system, and reads/writes are buffered in userspace by default — this is why you sometimes need <code>$stdout.sync = true</code> or explicit <code>.flush</code> calls in long-running scripts that print progress: without flushing, Ruby may hold output in a buffer rather than sending it to the terminal immediately, especially when output is redirected to a file or pipe rather than an interactive terminal (which uses line-buffering by default, while piped output uses full buffering).</p>



<p class="wp-block-paragraph">File modes matter for how Ruby opens the underlying OS file descriptor: <code>"r"</code> (read-only, error if the file doesn&#8217;t exist), <code>"w"</code> (write, truncate or create), <code>"a"</code> (append, create if missing), <code>"r+"</code> (read/write, must exist), <code>"w+"</code> (read/write, truncate or create), and <code>"a+"</code> (read/append). Adding <code>"b"</code> to any of these (e.g. <code>"rb"</code>) opens the file in binary mode, important on Windows where text mode does newline translation that can corrupt binary data like images.</p>



<p class="wp-block-paragraph">Encoding is another subtlety. Ruby strings carry an encoding tag, and <code>File.read</code> uses the default external encoding (usually UTF-8) unless told otherwise:</p>



<pre class="wp-block-code"><code>File.open("data.txt", "r:UTF-8") do |file|
  puts file.read.encoding
end
</code></pre>



<h2 class="wp-block-heading">Real-World Applications</h2>



<p class="wp-block-paragraph">I reach for these patterns constantly:</p>



<ul class="wp-block-list">
<li><strong>CLI tools</strong> that prompt the user for input and validate it before proceeding.</li>



<li><strong>Log file parsers</strong> that stream through gigabyte-sized log files line by line rather than loading them entirely into memory.</li>



<li><strong>Configuration readers</strong> that load a YAML or JSON file at startup (<code>File.read</code> combined with <code>JSON.parse</code> or <code>YAML.load</code>).</li>



<li><strong>Report generators</strong> that write structured output to disk for later use, using <code>File.open(path, "w")</code> blocks.</li>



<li><strong>Interactive scripts</strong> for onboarding or setup wizards that combine <code>gets</code>, validation loops, and file writes.</li>
</ul>



<h2 class="wp-block-heading">Best Practices</h2>



<ol class="wp-block-list">
<li><strong>Always use block form</strong> (<code>File.open(path) do |f| ... end</code>) so files close automatically.</li>



<li><strong>Stream large files</strong> with <code>each_line</code> or <code>foreach</code> instead of <code>read</code> or <code>readlines</code>.</li>



<li><strong>Chomp your gets calls</strong> — nearly every <code>gets</code> should be followed by <code>.chomp</code>.</li>



<li><strong>Send errors to STDERR</strong>, not STDOUT, especially in scripts meant to be composed with other command-line tools.</li>



<li><strong>Validate numeric input</strong> with <code>Integer()</code>/<code>Float()</code> rather than trusting <code>.to_i</code>/<code>.to_f</code>, which silently default to zero on bad input.</li>



<li><strong>Set explicit encodings</strong> when reading files that might not be UTF-8, to avoid <code>Encoding::UndefinedConversionError</code> surprises later.</li>
</ol>



<h2 class="wp-block-heading">Common Mistakes</h2>



<ul class="wp-block-list">
<li>Forgetting <code>.chomp</code> and being confused why string comparisons fail.</li>



<li>Opening a file without the block form and forgetting to call <code>.close</code>, leaking file handles in long-running processes.</li>



<li>Using <code>"w"</code> mode when you meant <code>"a"</code>, silently wiping out an existing file&#8217;s contents.</li>



<li>Reading massive files fully into memory with <code>File.read</code> when the task only needed to scan line by line.</li>



<li>Assuming <code>gets</code> returns <code>nil</code> gracefully on EOF in all contexts — in some environments (like piped input) <code>gets</code> returns <code>nil</code> at end-of-file, and calling <code>.chomp</code> on <code>nil</code> raises a <code>NoMethodError</code>. Always guard with <code>gets&amp;.chomp</code> or check for <code>nil</code> explicitly in scripts that might read piped input.</li>
</ul>



<h2 class="wp-block-heading">Debugging Tips</h2>



<p class="wp-block-paragraph">When output isn&#8217;t showing up when you expect it to, check buffering first — try <code>$stdout.sync = true</code> at the top of your script to force immediate flushing. When file content looks wrong, use <code>p</code> instead of <code>puts</code> to reveal hidden whitespace or encoding artifacts. And when a script behaves differently in a pipeline than it does interactively, remember that <code>STDIN.tty?</code> tells you whether input is coming from an actual terminal or being redirected — useful for scripts that need to behave differently in both cases.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby&#8217;s I/O methods look simple on the surface — <code>puts</code>, <code>print</code>, <code>gets</code> — but each has real behavioral differences worth knowing precisely, and the <code>File</code>/<code>IO</code> class hierarchy underneath gives you fine control once you need it: buffering, encoding, binary vs. text mode, and streaming large files efficiently. Building the habit of using block-form file handling, chomping your input, and sending errors to <code>STDERR</code> will save you from the vast majority of I/O-related bugs you&#8217;ll otherwise hit as your scripts grow from toy examples into real tools.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>Ruby&#8217;s official <code>IO</code> documentation: https://docs.ruby-lang.org/en/master/IO.html</li>



<li>Ruby&#8217;s official <code>File</code> documentation: https://docs.ruby-lang.org/en/master/File.html</li>



<li>Ruby&#8217;s <code>Kernel#gets</code>, <code>#puts</code>, <code>#print</code>, <code>#p</code> documentation: https://docs.ruby-lang.org/en/master/Kernel.html</li>



<li>Ruby style guide on I/O practices: https://rubystyle.guide/</li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ruby/basic-input-and-output-in-ruby-gets-puts-print-and-file-i-o-operations-explained/">Basic Input and Output in Ruby: gets, puts, print, and File I/O Operations Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/basic-input-and-output-in-ruby-gets-puts-print-and-file-i-o-operations-explained/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4499</post-id>	</item>
		<item>
		<title>Iterators and the Enumerable Module in Ruby: each, map, select, reduce, and Collection Methods Guide</title>
		<link>https://awjunaid.com/ruby/iterators-and-the-enumerable-module-in-ruby-each-map-select-reduce-and-collection-methods-guide/</link>
					<comments>https://awjunaid.com/ruby/iterators-and-the-enumerable-module-in-ruby-each-map-select-reduce-and-collection-methods-guide/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Fri, 01 Sep 2023 19:36:32 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4496</guid>

					<description><![CDATA[<p>If there&#8217;s one thing that made me fall in love with Ruby early on, it was the moment&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/iterators-and-the-enumerable-module-in-ruby-each-map-select-reduce-and-collection-methods-guide/">Iterators and the Enumerable Module in Ruby: each, map, select, reduce, and Collection Methods Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If there&#8217;s one thing that made me fall in love with Ruby early on, it was the moment I understood the <code>Enumerable</code> module properly. Before that, I was writing <code>for</code> loops out of habit from other languages. After it clicked, I realized Ruby had quietly given me a whole vocabulary for expressing <em>what</em> I wanted done with a collection, instead of manually writing <em>how</em> to loop through it. This article is my attempt to explain iterators and <code>Enumerable</code> the way I wish someone had explained them to me — from the basics of <code>each</code> all the way to writing your own enumerable classes and understanding what&#8217;s happening internally.</p>



<h2 class="wp-block-heading">What Is an Iterator, Really?</h2>



<p class="wp-block-paragraph">In Ruby, an iterator is just a method that yields control back to a block, one element at a time. The classic example is <code>each</code>:</p>



<pre class="wp-block-code"><code>fruits = &#91;"apple", "banana", "cherry"]

fruits.each do |fruit|
  puts fruit
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>apple
banana
cherry
</code></pre>



<p class="wp-block-paragraph"><code>each</code> doesn&#8217;t return anything meaningful for chaining — it returns the original array. Its whole job is running the block once per element, for side effects like printing. This is the foundation everything else in <code>Enumerable</code> builds on top of.</p>



<h2 class="wp-block-heading">The Enumerable Module</h2>



<p class="wp-block-paragraph">Here&#8217;s the part that took me a while to fully appreciate: <code>Array</code>, <code>Hash</code>, <code>Range</code>, and many other classes don&#8217;t each implement <code>map</code>, <code>select</code>, <code>reduce</code>, and dozens of other methods separately. They implement <strong>one</strong> method — <code>each</code> — and then <code>include Enumerable</code>, which gives them around 50 additional methods <strong>for free</strong>, all built on top of that single <code>each</code>.</p>



<pre class="wp-block-code"><code>puts Array.ancestors.include?(Enumerable)  # true
puts Hash.ancestors.include?(Enumerable)   # true
puts Range.ancestors.include?(Enumerable)  # true
</code></pre>



<p class="wp-block-paragraph">This is one of the cleanest examples of Ruby&#8217;s design philosophy: define one primitive operation, mix in a module, and inherit a rich, expressive API.</p>



<h2 class="wp-block-heading">map: Transforming Collections</h2>



<p class="wp-block-paragraph"><code>map</code> (aliased as <code>collect</code>) runs the block on every element and returns a <strong>new array</strong> built from the block&#8217;s return values:</p>



<pre class="wp-block-code"><code>numbers = &#91;1, 2, 3, 4, 5]
squared = numbers.map { |n| n ** 2 }
puts squared.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;1, 4, 9, 16, 25]
</code></pre>



<p class="wp-block-paragraph">Notice <code>numbers</code> itself is untouched — <code>map</code> doesn&#8217;t mutate the original array unless you use the bang version, <code>map!</code>, which replaces the array&#8217;s contents in place:</p>



<pre class="wp-block-code"><code>numbers.map! { |n| n * 10 }
puts numbers.inspect  # &#91;10, 20, 30, 40, 50]
</code></pre>



<p class="wp-block-paragraph">I generally avoid bang methods unless I have a specific reason (like avoiding an allocation in a hot loop), because mutating shared state quietly is a common source of bugs.</p>



<h2 class="wp-block-heading">select and reject: Filtering Collections</h2>



<p class="wp-block-paragraph"><code>select</code> (aliased <code>filter</code>) keeps elements where the block returns truthy; <code>reject</code> keeps elements where it returns falsy — the exact inverse:</p>



<pre class="wp-block-code"><code>numbers = (1..20).to_a

evens = numbers.select { |n| n.even? }
odds  = numbers.reject { |n| n.even? }

puts evens.inspect
puts odds.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
&#91;1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
</code></pre>



<p class="wp-block-paragraph">There&#8217;s also <code>find</code> (aliased <code>detect</code>), which returns the <strong>first</strong> matching element instead of all of them:</p>



<pre class="wp-block-code"><code>first_multiple_of_seven = numbers.find { |n| n % 7 == 0 }
puts first_multiple_of_seven  # 7
</code></pre>



<h2 class="wp-block-heading">reduce / inject: Folding a Collection into One Value</h2>



<p class="wp-block-paragraph"><code>reduce</code> (aliased <code>inject</code>) is the one that confuses people longest, but it&#8217;s the most powerful of the bunch — it folds a whole collection down into a single accumulated value.</p>



<pre class="wp-block-code"><code>numbers = &#91;1, 2, 3, 4, 5]

sum = numbers.reduce(0) { |accumulator, n| accumulator + n }
puts sum  # 15
</code></pre>



<p class="wp-block-paragraph">The first argument (<code>0</code>) is the starting value of the accumulator. Each iteration, the block&#8217;s return value becomes the new accumulator for the next iteration. You can also pass a symbol directly for simple operations, skipping the explicit block:</p>



<pre class="wp-block-code"><code>sum = numbers.reduce(:+)
product = numbers.reduce(1, :*)
puts sum      # 15
puts product  # 120
</code></pre>



<p class="wp-block-paragraph"><code>reduce</code> isn&#8217;t limited to numbers — it&#8217;s genuinely general-purpose. Here&#8217;s building a word-frequency hash:</p>



<pre class="wp-block-code"><code>words = %w&#91;ruby is fun ruby is powerful ruby is elegant]

frequency = words.reduce(Hash.new(0)) do |counts, word|
  counts&#91;word] += 1
  counts
end

puts frequency.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>{"ruby"=&gt;3, "is"=&gt;3, "fun"=&gt;1, "powerful"=&gt;1, "elegant"=&gt;1}
</code></pre>



<h2 class="wp-block-heading">Other Enumerable Methods Worth Knowing</h2>



<p class="wp-block-paragraph">A handful of others I use constantly:</p>



<pre class="wp-block-code"><code>numbers = &#91;5, 3, 8, 1, 9, 2]

puts numbers.sort.inspect          # &#91;1, 2, 3, 5, 8, 9]
puts numbers.sort { |a, b| b &lt;=&gt; a }.inspect  # descending
puts numbers.min                   # 1
puts numbers.max                   # 9
puts numbers.sum                   # 28
puts numbers.count { |n| n &gt; 3 }   # 3
puts numbers.any? { |n| n &gt; 8 }    # true
puts numbers.all? { |n| n &gt; 0 }    # true
puts numbers.none? { |n| n &gt; 100 } # true
puts numbers.group_by { |n| n.even? ? :even : :odd }.inspect
puts numbers.each_with_index.to_a.inspect
puts numbers.each_with_object(&#91;]) { |n, arr| arr &lt;&lt; n * 2 }.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;1, 2, 3, 5, 8, 9]
&#91;9, 8, 5, 3, 2, 1]
1
9
28
3
true
true
true
{:odd=&gt;&#91;5, 3, 1, 9], :even=&gt;&#91;8, 2]}
&#91;&#91;5, 0], &#91;3, 1], &#91;8, 2], &#91;1, 3], &#91;9, 4], &#91;2, 5]]
&#91;10, 6, 16, 2, 18, 4]
</code></pre>



<p class="wp-block-paragraph"><code>each_with_object</code> is my preferred alternative to <code>reduce</code> when the accumulator is a mutable object like an array or hash, since you don&#8217;t have to remember to return it explicitly at the end of the block.</p>



<h2 class="wp-block-heading">Writing Your Own Enumerable Class</h2>



<p class="wp-block-paragraph">This is where <code>Enumerable</code> really shows its design. If you define <code>each</code> on your own class and mix in <code>Enumerable</code>, you get <code>map</code>, <code>select</code>, <code>reduce</code>, <code>sort</code>, and everything else automatically.</p>



<pre class="wp-block-code"><code>class Playlist
  include Enumerable

  def initialize
    @songs = &#91;]
  end

  def add(song)
    @songs &lt;&lt; song
    self
  end

  def each
    return enum_for(:each) unless block_given?
    @songs.each { |song| yield song }
  end
end

playlist = Playlist.new
playlist.add("Bohemian Rhapsody").add("Imagine").add("Hotel California")

puts playlist.map(&amp;:upcase).inspect
puts playlist.select { |s| s.include?("H") }.inspect
puts playlist.sort.inspect
puts playlist.count
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;"BOHEMIAN RHAPSODY", "IMAGINE", "HOTEL CALIFORNIA"]
&#91;"Bohemian Rhapsody", "Hotel California"]
&#91;"Bohemian Rhapsody", "Hotel California", "Imagine"]
3
</code></pre>



<p class="wp-block-paragraph">I only had to write <code>each</code>. Every other method — <code>map</code>, <code>select</code>, <code>sort</code>, <code>count</code>, dozens more — came free from <code>Enumerable</code>, because internally they&#8217;re all implemented in terms of repeatedly calling <code>each</code> and collecting results.</p>



<h2 class="wp-block-heading">Internal Working: Enumerator Objects and Lazy Evaluation</h2>



<p class="wp-block-paragraph">When you call an iterator method <strong>without a block</strong>, Ruby doesn&#8217;t run it immediately — it returns an <code>Enumerator</code> object instead:</p>



<pre class="wp-block-code"><code>enum = &#91;1, 2, 3].map
puts enum.class  # Enumerator

result = enum.each { |n| n * 2 }
puts result.inspect  # &#91;2, 4, 6]
</code></pre>



<p class="wp-block-paragraph">This is what powers the <code>return enum_for(:each) unless block_given?</code> line in the <code>Playlist</code> example above — it lets <code>each</code> work correctly whether or not a block is passed, which <code>Enumerable</code>&#8216;s other methods rely on internally.</p>



<p class="wp-block-paragraph">Enumerators also support <strong>external iteration</strong> using <code>next</code>, which under the hood is implemented using Ruby <code>Fiber</code>s — lightweight, cooperatively-scheduled coroutines that let the enumerator pause mid-iteration and resume later:</p>



<pre class="wp-block-code"><code>enum = &#91;10, 20, 30].each
puts enum.next  # 10
puts enum.next  # 20
puts enum.next  # 30
</code></pre>



<p class="wp-block-paragraph">For working with very large or infinite sequences, <code>lazy</code> enumerators avoid computing the entire chain eagerly:</p>



<pre class="wp-block-code"><code>lazy_result = (1..Float::INFINITY).lazy
                                   .select { |n| n % 3 == 0 }
                                   .map { |n| n * 2 }
                                   .first(5)

puts lazy_result.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;6, 12, 18, 24, 30]
</code></pre>



<p class="wp-block-paragraph">Without <code>.lazy</code>, calling <code>select</code> on an infinite range would hang forever trying to build the full filtered array before <code>map</code> even starts. <code>.lazy</code> chains the operations so each value flows through the whole pipeline one at a time, stopping once <code>first(5)</code> has what it needs.</p>



<h2 class="wp-block-heading">Real-World Applications</h2>



<p class="wp-block-paragraph">I use <code>Enumerable</code> methods constantly for:</p>



<ul class="wp-block-list">
<li><strong>Data transformation pipelines</strong> — parsing CSV rows, mapping them into objects, filtering by business rules, and reducing into summary statistics.</li>



<li><strong>API response processing</strong> — <code>map</code> and <code>select</code> on JSON arrays returned from external services.</li>



<li><strong>Report generation</strong> — <code>group_by</code> and <code>reduce</code> for aggregating totals by category.</li>



<li><strong>Custom domain collections</strong> — wrapping a database result set or a queue in a class that includes <code>Enumerable</code>, so consumers get the whole familiar collection API without needing to know the underlying storage.</li>
</ul>



<h2 class="wp-block-heading">Best Practices</h2>



<ol class="wp-block-list">
<li><strong>Prefer <code>map</code>/<code>select</code>/<code>reduce</code> over manual loops</strong> when you&#8217;re transforming data — it communicates intent and avoids off-by-one bugs.</li>



<li><strong>Use <code>each</code> when you genuinely only need side effects</strong> (printing, logging) — don&#8217;t use <code>map</code> and discard its return value just out of habit.</li>



<li><strong>Use <code>each_with_object</code> instead of <code>reduce</code></strong> when accumulating into a mutable collection, for cleaner code.</li>



<li><strong>Reach for <code>.lazy</code></strong> when working with large or infinite sequences, or when you only need the first few results.</li>



<li><strong>Include <code>Enumerable</code> in custom classes</strong> that represent collections, rather than reinventing <code>map</code>/<code>select</code>/<code>sort</code> yourself.</li>
</ol>



<h2 class="wp-block-heading">Common Mistakes</h2>



<ul class="wp-block-list">
<li>Using <code>map</code> when you meant <code>each</code>, and being surprised by an unused array of <code>nil</code>s being returned.</li>



<li>Mutating the collection you&#8217;re iterating over inside the block (e.g. calling <code>array.delete</code> inside <code>array.each</code>), which produces unpredictable skipped elements.</li>



<li>Forgetting that <code>reduce</code> without an initial value uses the first element as the seed, which can misbehave on empty arrays or produce a different type than expected.</li>



<li>Building a giant array with <code>select</code>/<code>map</code> on data that could have been streamed lazily, causing unnecessary memory pressure.</li>



<li>Implementing <code>each</code> on a custom class without handling the no-block case (<code>enum_for</code>), which breaks every other <code>Enumerable</code> method that expects to be able to get an <code>Enumerator</code> back.</li>
</ul>



<h2 class="wp-block-heading">Debugging Tips</h2>



<p class="wp-block-paragraph">When a chain of <code>Enumerable</code> calls isn&#8217;t producing what you expect, break it apart and inspect intermediate results with <code>p</code> after each step rather than debugging the whole chain at once. For custom <code>Enumerable</code> classes, test <code>each</code> in isolation first — if <code>each</code> is wrong, everything built on top of it (<code>map</code>, <code>select</code>, <code>sort</code>, <code>reduce</code>) will be wrong too, since they all delegate to it internally.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby&#8217;s iterators and the <code>Enumerable</code> module are, in my experience, one of the best examples of good API design in any mainstream language: implement <code>each</code> once, mix in a module, and get dozens of expressive, well-tested collection methods for free. Learning to reach for <code>map</code>, <code>select</code>, and <code>reduce</code> instead of manual loops doesn&#8217;t just make code shorter — it makes intent clearer, and once you understand how <code>Enumerable</code> is built on <code>each</code> and <code>Enumerator</code>, you can extend that same power to your own custom classes.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>Ruby&#8217;s official <code>Enumerable</code> module documentation: https://docs.ruby-lang.org/en/master/Enumerable.html</li>



<li>Ruby&#8217;s official <code>Enumerator</code> class documentation: https://docs.ruby-lang.org/en/master/Enumerator.html</li>



<li>Ruby&#8217;s official <code>Array</code> documentation: https://docs.ruby-lang.org/en/master/Array.html</li>



<li>Ruby style guide on collections: https://rubystyle.guide/</li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ruby/iterators-and-the-enumerable-module-in-ruby-each-map-select-reduce-and-collection-methods-guide/">Iterators and the Enumerable Module in Ruby: each, map, select, reduce, and Collection Methods Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/iterators-and-the-enumerable-module-in-ruby-each-map-select-reduce-and-collection-methods-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4496</post-id>	</item>
		<item>
		<title>The Exception Class Catch and Throw in Ruby: Error Handling and Control Flow Explained</title>
		<link>https://awjunaid.com/ruby/the-exception-class-catch-and-throw-in-ruby-error-handling-and-control-flow-explained/</link>
					<comments>https://awjunaid.com/ruby/the-exception-class-catch-and-throw-in-ruby-error-handling-and-control-flow-explained/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Fri, 01 Sep 2023 19:32:03 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4493</guid>

					<description><![CDATA[<p>When I first started writing Ruby, I treated error handling like an afterthought. I&#8217;d write my happy-path code,&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/the-exception-class-catch-and-throw-in-ruby-error-handling-and-control-flow-explained/">The Exception Class Catch and Throw in Ruby: Error Handling and Control Flow Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">When I first started writing Ruby, I treated error handling like an afterthought. I&#8217;d write my happy-path code, ship it, and only think about exceptions when something blew up in production at 2 AM. Over the years I&#8217;ve completely flipped that mindset. Good error handling isn&#8217;t defensive paranoia — it&#8217;s part of the design of the program. In this article, I want to walk you through everything I&#8217;ve learned about Ruby&#8217;s exception system, the often-misunderstood <code>catch</code> and <code>throw</code> keywords, and how Ruby&#8217;s control flow really works under the hood.</p>



<p class="wp-block-paragraph">This is a long one, so grab a coffee. I&#8217;ll go from the absolute basics to the internals of how Ruby represents exceptions as objects, and I&#8217;ll show you the patterns I actually use in real codebases.</p>



<h2 class="wp-block-heading">Why Error Handling Deserves Its Own Mental Model</h2>



<p class="wp-block-paragraph">In a lot of languages, errors are treated as return codes or flags you have to check manually. Ruby, like Python and Java, treats errors as <strong>objects</strong> that get <strong>raised</strong> and <strong>rescued</strong>. This is a huge shift in mindset if you&#8217;re coming from C or older-style JavaScript. Instead of checking <code>if result == nil</code> after every call, you write code assuming things will work, and you handle the exceptional cases separately, where they belong.</p>



<p class="wp-block-paragraph">I like this approach because it keeps my &#8220;main&#8221; logic readable. I don&#8217;t have to litter every third line with error checks. But it does mean I need to understand exactly how Ruby&#8217;s exception machinery works, because sloppy rescue blocks can hide real bugs.</p>



<h2 class="wp-block-heading">The Exception Class Hierarchy</h2>



<p class="wp-block-paragraph">Everything in Ruby&#8217;s error system starts with the <code>Exception</code> class. Here&#8217;s the hierarchy I keep in my head:</p>



<pre class="wp-block-code"><code>Exception
  NoMemoryError
  ScriptError
    LoadError
    NotImplementedError
    SyntaxError
  SecurityError
  SignalException
    Interrupt
  StandardError
    ArgumentError
    EncodingError
    FiberError
    IOError
      EOFError
    IndexError
      KeyError
      StopIteration
    LocalJumpError
    NameError
      NoMethodError
    RangeError
      FloatDomainError
    RegexpError
    RuntimeError (default for raise)
    ThreadError
    TypeError
    ZeroDivisionError
  SystemExit
  SystemStackError
</code></pre>



<p class="wp-block-paragraph">The most important thing to understand here is that <code>rescue</code> <strong>without an explicit class</strong> only catches <code>StandardError</code> and its subclasses. It does <em>not</em> catch <code>Exception</code> itself. This is intentional. Things like <code>SystemExit</code> (raised when you call <code>exit</code>) or <code>NoMemoryError</code> are not meant to be casually swallowed by your <code>rescue</code> blocks. I&#8217;ve seen junior developers write <code>rescue Exception =&gt; e</code> thinking it&#8217;s &#8220;more thorough,&#8221; and it actually breaks things like <code>Ctrl+C</code> interrupts and clean process exits. I never do this, and I&#8217;d recommend you avoid it too unless you have a very specific reason (like a top-level crash logger that re-raises afterward).</p>



<h2 class="wp-block-heading">Basic Syntax: begin, rescue, else, ensure</h2>



<p class="wp-block-paragraph">Let me start with the core building block:</p>



<pre class="wp-block-code"><code>begin
  result = 10 / 0
rescue ZeroDivisionError =&gt; e
  puts "Caught an error: #{e.message}"
ensure
  puts "This always runs, error or not"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Caught an error: divided by 0
This always runs, error or not
</code></pre>



<p class="wp-block-paragraph">A few things I want to point out here:</p>



<ul class="wp-block-list">
<li><code>rescue ZeroDivisionError => e</code> catches the specific exception class and binds it to the local variable <code>e</code>.</li>



<li><code>ensure</code> runs no matter what — whether an exception was raised, rescued, or not raised at all. I use <code>ensure</code> constantly for cleanup: closing files, releasing database connections, unlocking mutexes.</li>



<li>There&#8217;s also an <code>else</code> clause that runs only if <strong>no</strong> exception was raised:</li>
</ul>



<pre class="wp-block-code"><code>begin
  result = 10 / 2
rescue ZeroDivisionError =&gt; e
  puts "Error: #{e.message}"
else
  puts "Success! Result is #{result}"
ensure
  puts "Cleanup happens here"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Success! Result is 5
Cleanup happens here
</code></pre>



<p class="wp-block-paragraph">I don&#8217;t use <code>else</code> as often as <code>ensure</code>, but it&#8217;s genuinely useful when you want to separate &#8220;code that might fail&#8221; from &#8220;code that should only run after success&#8221; — it keeps the rescue block focused purely on error recovery.</p>



<h2 class="wp-block-heading">Method-Level Rescue (No begin Needed)</h2>



<p class="wp-block-paragraph">Something I really appreciate about Ruby is that you don&#8217;t need an explicit <code>begin</code> block inside a method — the method definition itself acts as an implicit begin/end:</p>



<pre class="wp-block-code"><code>def divide(a, b)
  a / b
rescue ZeroDivisionError =&gt; e
  puts "Can't divide by zero: #{e.message}"
  nil
end

divide(10, 0)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Can't divide by zero: divided by 0
</code></pre>



<p class="wp-block-paragraph">I use this style all the time because it reduces indentation and keeps methods shorter. It&#8217;s genuinely idiomatic Ruby.</p>



<h2 class="wp-block-heading">Rescuing Multiple Exception Types</h2>



<p class="wp-block-paragraph">You can rescue multiple classes in one clause, or stack multiple <code>rescue</code> clauses for different handling logic:</p>



<pre class="wp-block-code"><code>def parse_input(value)
  Integer(value) / 0
rescue ArgumentError, TypeError =&gt; e
  puts "Bad input: #{e.message}"
rescue ZeroDivisionError =&gt; e
  puts "Math error: #{e.message}"
rescue =&gt; e
  puts "Something else went wrong: #{e.class} - #{e.message}"
end

parse_input("abc")
parse_input("10")
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Bad input: invalid value for Integer(): "abc"
Math error: divided by 0
</code></pre>



<p class="wp-block-paragraph">Notice the order matters — Ruby checks rescue clauses top to bottom and uses the first one that matches, similar to a case statement. I always put the most specific exception classes first and the generic <code>rescue =&gt; e</code> catch-all last.</p>



<h2 class="wp-block-heading">Raising Exceptions</h2>



<p class="wp-block-paragraph">I raise exceptions constantly to enforce invariants in my code. The <code>raise</code> keyword has a few forms:</p>



<pre class="wp-block-code"><code>raise "Something went wrong"                     # RuntimeError with message
raise ArgumentError, "age must be positive"       # specific class + message
raise ArgumentError.new("age must be positive")   # equivalent, using .new
</code></pre>



<p class="wp-block-paragraph">Here&#8217;s a real pattern I use for validating method arguments:</p>



<pre class="wp-block-code"><code>def set_age(age)
  raise ArgumentError, "age must be a positive integer" unless age.is_a?(Integer) &amp;&amp; age.positive?
  @age = age
end

set_age(-5)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>ArgumentError (age must be a positive integer)
</code></pre>



<h2 class="wp-block-heading">Building Custom Exception Classes</h2>



<p class="wp-block-paragraph">This is where error handling starts to feel like real application design. Instead of raising generic <code>RuntimeError</code>s everywhere, I define my own exception hierarchy that mirrors my domain.</p>



<pre class="wp-block-code"><code>class ApplicationError &lt; StandardError; end

class InsufficientFundsError &lt; ApplicationError
  attr_reader :balance, :requested_amount

  def initialize(balance:, requested_amount:)
    @balance = balance
    @requested_amount = requested_amount
    super("Insufficient funds: tried to withdraw #{requested_amount}, but balance is #{balance}")
  end
end

class Account
  attr_reader :balance

  def initialize(balance)
    @balance = balance
  end

  def withdraw(amount)
    if amount &gt; balance
      raise InsufficientFundsError.new(balance: balance, requested_amount: amount)
    end
    @balance -= amount
  end
end

account = Account.new(100)
begin
  account.withdraw(500)
rescue InsufficientFundsError =&gt; e
  puts e.message
  puts "Shortfall: #{e.requested_amount - e.balance}"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Insufficient funds: tried to withdraw 500, but balance is 100
Shortfall: 400
</code></pre>



<p class="wp-block-paragraph">I always create a base error class (<code>ApplicationError</code> here) for my application or gem, then subclass it for specific error conditions. This lets consumers of my code choose how granular they want to be — they can rescue the base class to catch anything from my app, or a specific subclass for fine-grained handling.</p>



<h2 class="wp-block-heading">The retry Keyword</h2>



<p class="wp-block-paragraph"><code>retry</code> is one of those features I didn&#8217;t appreciate until I started writing code that talks to flaky external services (APIs, databases with connection hiccups, etc.). It jumps back to the beginning of the <code>begin</code> block:</p>



<pre class="wp-block-code"><code>attempts = 0

begin
  attempts += 1
  puts "Attempt #{attempts}"
  raise "Connection failed" if attempts &lt; 3
  puts "Connected successfully!"
rescue =&gt; e
  if attempts &lt; 3
    puts "Retrying after: #{e.message}"
    retry
  else
    puts "Giving up after #{attempts} attempts"
  end
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Attempt 1
Retrying after: Connection failed
Attempt 2
Retrying after: Connection failed
Attempt 3
Connected successfully!
</code></pre>



<p class="wp-block-paragraph">I always cap my retries with a counter like this. An unconditional <code>retry</code> is a great way to write an infinite loop by accident, and I&#8217;ve done that at least once early in my career.</p>



<h2 class="wp-block-heading">catch and throw: Ruby&#8217;s Other Control Flow Tool</h2>



<p class="wp-block-paragraph">This is the part people confuse with exception handling, and I want to be very clear: <strong><code>catch</code>/<code>throw</code> is not for error handling.</strong> It&#8217;s a general-purpose, non-local jump mechanism — a way to break out of deeply nested loops or blocks without raising an actual exception object.</p>



<pre class="wp-block-code"><code>result = catch(:found) do
  (1..100).each do |i|
    (1..100).each do |j|
      if i * j == 50
        throw :found, &#91;i, j]
      end
    end
  end
  nil
end

puts result.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;1, 50]
</code></pre>



<p class="wp-block-paragraph">Here&#8217;s how I think about the difference:</p>



<ul class="wp-block-list">
<li><code>raise</code>/<code>rescue</code> is for signaling that something went <strong>wrong</strong> — an exceptional, often error-like condition.</li>



<li><code>throw</code>/<code>catch</code> is for jumping out of a normal, non-error control flow — like escaping nested loops early once you&#8217;ve found what you wanted.</li>
</ul>



<p class="wp-block-paragraph"><code>throw</code> and <code>catch</code> are matched by a <strong>symbol tag</strong> (<code>:found</code> in my example), not by class, and there&#8217;s no concept of a hierarchy like there is with exceptions. If you <code>throw</code> a tag that has no matching <code>catch</code> anywhere up the call stack, Ruby raises an <code>UncaughtThrowError</code>, which <em>is</em> a real exception:</p>



<pre class="wp-block-code"><code>throw :nonexistent_tag
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>UncaughtThrowError (uncaught throw :nonexistent_tag)
</code></pre>



<p class="wp-block-paragraph">I use <code>catch</code>/<code>throw</code> rarely — mostly for early-exit scenarios in nested iterations where <code>break</code> alone isn&#8217;t enough because I&#8217;m several loop levels deep. Honestly, in most real code I write, I refactor the nested loops into a method and use <code>return</code> instead, which is usually cleaner. But it&#8217;s good to know <code>catch</code>/<code>throw</code> exists for the cases where extraction into a method isn&#8217;t convenient.</p>



<h2 class="wp-block-heading">Internal Working: How Exceptions Actually Propagate</h2>



<p class="wp-block-paragraph">Under the hood, when you call <code>raise</code>, Ruby creates (or reuses) an exception object and unwinds the call stack, looking frame by frame for a matching <code>rescue</code> clause. This unwinding is not free — it&#8217;s more expensive than a normal method return because the Ruby VM (YARV) has to walk back through the stack frames, check for <code>ensure</code> blocks that need to run, and match exception classes against active rescue clauses.</p>



<p class="wp-block-paragraph">This is why exceptions in Ruby, like in most languages, should be reserved for truly <strong>exceptional</strong> situations — not for routine control flow. I&#8217;ve seen code that uses <code>raise</code>/<code>rescue</code> to break out of loops or handle &#8220;user not found&#8221; as if it were catastrophic. It works, but it&#8217;s slower than it needs to be and it makes the code harder to reason about, because now <code>NoUserFoundError</code> looks the same, structurally, as <code>DatabaseConnectionLost</code>.</p>



<p class="wp-block-paragraph">A concrete illustration of the performance cost:</p>



<pre class="wp-block-code"><code>require 'benchmark'

Benchmark.bm do |x|
  x.report("with exceptions:") do
    100_000.times do
      begin
        raise "test"
      rescue
        nil
      end
    end
  end

  x.report("with return values:") do
    100_000.times do
      result = begin
        :error
      end
    end
  end
end
</code></pre>



<p class="wp-block-paragraph">On my machine, the exception-based loop runs several times slower than the plain conditional version. That gap grows if the exceptions carry a full backtrace (which they do by default). If you&#8217;re in a hot path and need to signal &#8220;not found&#8221; or similar frequent, expected conditions, returning <code>nil</code>, a sentinel value, or a Result-style object is usually the better idea. Save real exceptions for genuinely unexpected failures.</p>



<h2 class="wp-block-heading">Exception Objects: message, backtrace, and cause</h2>



<p class="wp-block-paragraph">Every exception instance carries useful introspection data:</p>



<pre class="wp-block-code"><code>begin
  begin
    raise ArgumentError, "bad input"
  rescue ArgumentError =&gt; inner
    raise TypeError, "wrapping error"
  end
rescue TypeError =&gt; outer
  puts outer.message
  puts outer.cause.class
  puts outer.cause.message
  puts outer.backtrace.first
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>wrapping error
ArgumentError
bad input
(the file and line number where TypeError was raised)
</code></pre>



<p class="wp-block-paragraph">The <code>cause</code> chain is something I lean on heavily when wrapping low-level errors into higher-level, domain-specific ones. It preserves the original exception so I don&#8217;t lose debugging context, while still presenting a clean, meaningful error type to the caller.</p>



<h2 class="wp-block-heading">Common Mistakes I See (and Have Made Myself)</h2>



<p class="wp-block-paragraph"><strong>Rescuing too broadly.</strong> <code>rescue =&gt; e</code> inside a tight loop, silently swallowing everything, is a classic way to hide real bugs. I always log or re-raise unless I have a genuinely good reason to suppress an error.</p>



<p class="wp-block-paragraph"><strong>Using exceptions for expected conditions.</strong> If &#8220;user not found&#8221; happens on every third request, that&#8217;s not exceptional — model it with a return value.</p>



<p class="wp-block-paragraph"><strong>Forgetting that <code>ensure</code> can swallow return values.</strong> If your <code>ensure</code> block has an explicit <code>return</code>, it silently overrides whatever the <code>begin</code> block returned. I avoid <code>return</code> inside <code>ensure</code> for this exact reason.</p>



<p class="wp-block-paragraph"><strong>Not re-raising after logging.</strong> If you catch an error just to log it, but the caller still needs to know something failed, re-raise it (<code>raise</code> with no arguments inside a rescue block re-raises the current exception).</p>



<pre class="wp-block-code"><code>def risky_operation
  do_something
rescue =&gt; e
  logger.error("Failed: #{e.message}")
  raise
end
</code></pre>



<h2 class="wp-block-heading">Best Practices I Actually Follow</h2>



<ul class="wp-block-list">
<li>Rescue the most specific exception class you can, not the broadest one.</li>



<li>Build a small hierarchy of custom exceptions per application/gem, rooted in a single base class.</li>



<li>Use <code>ensure</code> for cleanup, not <code>rescue</code>.</li>



<li>Never use <code>rescue Exception</code> unless you&#8217;re writing top-level process supervision code that re-raises afterward.</li>



<li>Reserve exceptions for actually exceptional situations; use return values for expected, frequent conditions.</li>



<li>Always preserve the <code>cause</code> chain when wrapping exceptions.</li>



<li>Use <code>catch</code>/<code>throw</code> sparingly, and only for non-error control flow like early exits from deep nesting.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby&#8217;s exception system is more thoughtfully designed than it first appears. The <code>Exception</code> class hierarchy gives you fine control over what gets rescued and what doesn&#8217;t, <code>begin</code>/<code>rescue</code>/<code>else</code>/<code>ensure</code> gives you a clean structure for handling and cleaning up after failures, and custom exception classes let you model your application&#8217;s error conditions as first-class citizens instead of stringly-typed messages. <code>catch</code>/<code>throw</code>, meanwhile, is a completely separate tool for non-local jumps that has nothing to do with error handling, despite superficially looking similar.</p>



<p class="wp-block-paragraph">The biggest shift for me, going from &#8220;just make errors go away&#8221; to actually good error handling, was learning to treat exceptions as part of my domain model rather than a nuisance to suppress. Once you start designing your exception hierarchy the same way you design your classes, your error handling code stops being an afterthought and starts being one of the more elegant parts of your codebase.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/exception_md.html">Exception Handling</a></li>



<li>Ruby Core API — <a href="https://docs.ruby-lang.org/en/master/Exception.html">Exception class</a></li>



<li>Ruby Core API — <a href="https://docs.ruby-lang.org/en/master/Kernel.html#method-i-catch">Kernel#catch and Kernel#throw</a></li>



<li>Ruby Core API — <a href="https://docs.ruby-lang.org/en/master/StandardError.html">StandardError</a></li>



<li>RubyGems Guides — <a href="https://guides.rubygems.org/">Publishing your gem and versioning practices</a></li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ruby/the-exception-class-catch-and-throw-in-ruby-error-handling-and-control-flow-explained/">The Exception Class Catch and Throw in Ruby: Error Handling and Control Flow Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/the-exception-class-catch-and-throw-in-ruby-error-handling-and-control-flow-explained/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4493</post-id>	</item>
		<item>
		<title>Standard Data Types in Ruby: Numbers, Strings, Symbols, Booleans, and Nil Explained</title>
		<link>https://awjunaid.com/ruby/standard-data-types-in-ruby-numbers-strings-symbols-booleans-and-nil-explained/</link>
					<comments>https://awjunaid.com/ruby/standard-data-types-in-ruby-numbers-strings-symbols-booleans-and-nil-explained/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Tue, 15 Aug 2023 13:26:10 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4226</guid>

					<description><![CDATA[<p>I remember the moment Ruby&#8217;s object model finally clicked for me. I was debugging why 1.class returned Integer&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/standard-data-types-in-ruby-numbers-strings-symbols-booleans-and-nil-explained/">Standard Data Types in Ruby: Numbers, Strings, Symbols, Booleans, and Nil Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I remember the moment Ruby&#8217;s object model finally clicked for me. I was debugging why <code>1.class</code> returned <code>Integer</code> and not some primitive type, and I realized: in Ruby, <strong>everything is an object</strong>. Numbers, strings, even <code>true</code>, <code>false</code>, and <code>nil</code> — they all respond to methods, they all have a class, and they all live in the same object hierarchy as your custom classes. Coming from languages with primitive types bolted onto an object system, this was a genuine &#8220;oh, that&#8217;s elegant&#8221; moment for me.</p>



<p class="wp-block-paragraph">In this article, I&#8217;m going to walk through Ruby&#8217;s core data types — numbers, strings, symbols, booleans, and nil — the way I wish someone had explained them to me: not just the syntax, but what&#8217;s actually happening underneath, and how I use each type in real code.</p>



<h2 class="wp-block-heading">Everything Is an Object</h2>



<p class="wp-block-paragraph">Before diving into individual types, I want to plant this idea firmly: in Ruby, there is no such thing as a &#8220;primitive.&#8221; Even integers are instances of a class:</p>



<pre class="wp-block-code"><code>puts 42.class          # Integer
puts 42.is_a?(Object)  # true
puts 3.14.class         # Float
puts "hello".class      # String
puts :symbol.class      # Symbol
puts true.class         # TrueClass
puts false.class        # FalseClass
puts nil.class           # NilClass
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Integer
true
Float
String
Symbol
TrueClass
FalseClass
NilClass
</code></pre>



<p class="wp-block-paragraph">Notice something interesting: <code>true</code> and <code>false</code> aren&#8217;t both instances of some <code>Boolean</code> class — Ruby doesn&#8217;t even have a <code>Boolean</code> class. <code>true</code> is the sole instance of <code>TrueClass</code>, and <code>false</code> is the sole instance of <code>FalseClass</code>. Same story with <code>nil</code> — it&#8217;s the one and only instance of <code>NilClass</code>. I&#8217;ll come back to why this matters.</p>



<h2 class="wp-block-heading">Numbers: Integer, Float, Rational, and Complex</h2>



<h3 class="wp-block-heading">Integer</h3>



<p class="wp-block-paragraph">Ruby&#8217;s <code>Integer</code> class handles whole numbers, and unlike many languages, Ruby integers have <strong>arbitrary precision</strong> — they grow as large as memory allows, with no overflow:</p>



<pre class="wp-block-code"><code>big_number = 2**100
puts big_number
puts big_number.class
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>1267650600228229401496703205376
Integer
</code></pre>



<p class="wp-block-paragraph">Internally, small integers (that fit within a machine word) are stored as &#8220;Fixnum&#8221;-style immediate values that don&#8217;t require a heap allocation — Ruby literally encodes the integer value directly inside the object reference itself. Once a number grows beyond that range, Ruby transparently promotes it to a heap-allocated &#8220;Bignum&#8221; representation. As a developer, I never have to think about this distinction anymore (Ruby merged Fixnum/Bignum into a unified <code>Integer</code> class years ago), but understanding it helps explain why small integer arithmetic in Ruby is so fast — there&#8217;s no object allocation involved at all.</p>



<h3 class="wp-block-heading">Float</h3>



<p class="wp-block-paragraph">Floats are IEEE 754 double-precision numbers, and they come with the usual floating-point precision caveats:</p>



<pre class="wp-block-code"><code>puts 0.1 + 0.2
puts (0.1 + 0.2) == 0.3
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>0.30000000000000004
false
</code></pre>



<p class="wp-block-paragraph">I&#8217;ve been bitten by this exact issue when comparing floating point totals in financial calculations. My rule: never use floats for money. Which brings me to&#8230;</p>



<h3 class="wp-block-heading">Rational and Complex</h3>



<p class="wp-block-paragraph">For cases where precision actually matters, Ruby gives you <code>Rational</code> numbers:</p>



<pre class="wp-block-code"><code>require 'rational' # not required in modern Ruby, but explicit here for clarity

r = Rational(1, 3)
puts r
puts r + Rational(1, 6)
puts 0.1r + 0.2r  # rational literals
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>1/3
1/2
3/10
</code></pre>



<p class="wp-block-paragraph">I use <code>Rational</code> when I need exact fractional arithmetic — currency calculations, precise ratios, anything where floating-point drift is unacceptable. <code>Complex</code> numbers exist too, for mathematical/scientific applications:</p>



<pre class="wp-block-code"><code>c = Complex(3, 4)
puts c.abs  # 5.0 (magnitude of the complex number)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>5.0
</code></pre>



<h3 class="wp-block-heading">Common Numeric Operations</h3>



<pre class="wp-block-code"><code>puts 10.divmod(3).inspect  # &#91;3, 1] - quotient and remainder together
puts 7.fdiv(2)               # 3.5 - float division
puts(-5.abs)                  # 5
puts 10.gcd(15)              # 5
puts 3.14159.round(2)        # 3.14
puts 5.between?(1, 10)       # true
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;3, 1]
3.5
5
5
3.14
true
</code></pre>



<p class="wp-block-paragraph">I lean on <code>divmod</code>, <code>fdiv</code>, and <code>round</code> constantly in everyday scripting — they save me from writing manual arithmetic that Ruby already handles cleanly.</p>



<h2 class="wp-block-heading">Strings: Mutable, Encoded, and Method-Rich</h2>



<p class="wp-block-paragraph">Ruby strings are <strong>mutable</strong> by default, which surprises people coming from Python or Java where strings are immutable.</p>



<pre class="wp-block-code"><code>s = "hello"
s &lt;&lt; " world"
puts s
puts s.object_id  # same object_id before and after mutation
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>hello world
</code></pre>



<p class="wp-block-paragraph">Because strings are mutable, two variables can point to the same string object, and mutating through one affects the other:</p>



<pre class="wp-block-code"><code>a = "shared"
b = a
b &lt;&lt; "!"
puts a  # "shared!" - a changed too, because a and b reference the SAME object
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>shared!
</code></pre>



<p class="wp-block-paragraph">This trips people up constantly. If you want an independent copy, use <code>.dup</code> or <code>.clone</code>:</p>



<pre class="wp-block-code"><code>a = "original"
b = a.dup
b &lt;&lt; " modified"
puts a  # "original" - unaffected
puts b  # "original modified"
</code></pre>



<h3 class="wp-block-heading">Frozen Strings</h3>



<p class="wp-block-paragraph">Since Ruby 3.0, you can opt into frozen string literals — a performance and safety practice I now use in almost every file I write:</p>



<pre class="wp-block-code"><code># frozen_string_literal: true

s = "hello"
begin
  s &lt;&lt; " world"
rescue =&gt; e
  puts "#{e.class}: #{e.message}"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>FrozenError: can't modify frozen String: "hello"
</code></pre>



<p class="wp-block-paragraph">Freezing string literals means Ruby doesn&#8217;t have to allocate a new string object every time that literal is evaluated — it can reuse the same frozen instance. In hot loops with lots of string literals, this measurably reduces object allocation and garbage collector pressure. I add <code># frozen_string_literal: true</code> to the top of new Ruby files as a habit now.</p>



<h3 class="wp-block-heading">String Methods I Use Every Day</h3>



<pre class="wp-block-code"><code>name = "  Ruby Developer  "
puts name.strip
puts name.strip.downcase
puts name.strip.split(" ").inspect
puts "hello".center(11, "*")
puts "abc" * 3
puts "hello world".gsub("o", "0")
puts format("%.2f", 3.14159)
puts "%-10s|" % "left"
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Ruby Developer
ruby developer
&#91;"Ruby", "Developer"]
***hello***
abcabcabc
hell0 w0rld
3.14
left      |
</code></pre>



<h3 class="wp-block-heading">String Encoding</h3>



<p class="wp-block-paragraph">Every Ruby string carries an encoding, and this matters a lot when you&#8217;re dealing with multi-byte characters or interfacing with external systems:</p>



<pre class="wp-block-code"><code>s = "héllo"
puts s.encoding
puts s.bytesize
puts s.length
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>UTF-8
6
5
</code></pre>



<p class="wp-block-paragraph">Notice <code>bytesize</code> (6) differs from <code>length</code> (5) because <code>é</code> takes two bytes in UTF-8 but counts as a single character. I&#8217;ve debugged more than one bug where someone assumed <code>bytesize == length</code>, especially when truncating strings for database columns defined by byte length rather than character length.</p>



<h2 class="wp-block-heading">Symbols: Lightweight, Immutable Identifiers</h2>



<p class="wp-block-paragraph">Symbols look like strings with a colon (<code>:name</code>), but they behave very differently. A symbol is <strong>immutable</strong> and Ruby <strong>interns</strong> them — meaning every reference to <code>:name</code> anywhere in your program points to the exact same object in memory:</p>



<pre class="wp-block-code"><code>puts :name.object_id == :name.object_id  # true
puts "name".object_id == "name".object_id  # false (different objects each time)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>true
false
</code></pre>



<p class="wp-block-paragraph">This is why symbols are the idiomatic choice for hash keys, method names, and anything used as an identifier rather than as textual data. Since there&#8217;s only ever one copy of a given symbol in memory, comparing two symbols is a fast identity check rather than a character-by-character comparison, which is why symbol comparisons and hash lookups with symbol keys are noticeably faster than the string equivalent.</p>



<pre class="wp-block-code"><code>person = { name: "Alice", age: 30 }  # symbol keys, modern hash syntax
puts person&#91;:name]
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Alice
</code></pre>



<p class="wp-block-paragraph">One caution I always mention to newer Ruby developers: don&#8217;t dynamically generate symbols from unbounded, user-controlled input (like <code>params[:type].to_sym</code> on arbitrary user text). Before Ruby 2.2, symbols were never garbage collected at all, and even now, symbols created this way can still accumulate in ways strings wouldn&#8217;t, because they persist for the life of the process in certain cases. It&#8217;s a minor but real memory consideration in long-running server processes.</p>



<h2 class="wp-block-heading">Booleans: true, false, and Truthiness</h2>



<p class="wp-block-paragraph">As I mentioned earlier, Ruby has no <code>Boolean</code> class — just the singleton objects <code>true</code> (an instance of <code>TrueClass</code>) and <code>false</code> (an instance of <code>FalseClass</code>). What really matters in Ruby is <strong>truthiness</strong>: which values are treated as true or false in a conditional.</p>



<p class="wp-block-paragraph">Ruby&#8217;s rule is refreshingly simple: <strong>everything is truthy except <code>false</code> and <code>nil</code>.</strong></p>



<pre class="wp-block-code"><code>if 0
  puts "0 is truthy"
end

if ""
  puts "empty string is truthy"
end

if &#91;]
  puts "empty array is truthy"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>0 is truthy
empty string is truthy
empty array is truthy
</code></pre>



<p class="wp-block-paragraph">This surprises developers coming from JavaScript or Python, where <code>0</code>, <code>""</code>, and <code>[]</code> are all falsy. In Ruby, only <code>nil</code> and <code>false</code> are falsy — full stop. I had to consciously retrain my instincts here when I started writing Ruby, because habits from other languages led me to write buggy conditionals early on.</p>



<h2 class="wp-block-heading">Nil: The Absence of a Value</h2>



<p class="wp-block-paragraph"><code>nil</code> represents &#8220;nothing&#8221; — the absence of a value — and it&#8217;s the sole instance of <code>NilClass</code>:</p>



<pre class="wp-block-code"><code>puts nil.class
puts nil.nil?
puts nil.to_s.inspect
puts nil.to_a.inspect
puts nil.to_i
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>NilClass
true
""
&#91;]
0
</code></pre>



<p class="wp-block-paragraph">I really appreciate that <code>nil</code> responds sensibly to conversion methods like <code>to_s</code>, <code>to_a</code>, and <code>to_i</code> — it makes certain code paths safer without explicit nil checks, since <code>nil.to_s</code> gives you an empty string rather than raising an error.</p>



<h3 class="wp-block-heading">The Safe Navigation Operator</h3>



<p class="wp-block-paragraph">One of my favorite additions to modern Ruby is the safe navigation operator <code>&amp;.</code>, which lets you call a method on a possibly-nil object without blowing up:</p>



<pre class="wp-block-code"><code>user = nil
puts user&amp;.name.inspect     # nil, no NoMethodError raised

user = OpenStruct.new(name: "Priya")
puts user&amp;.name
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>nil
Priya
</code></pre>



<p class="wp-block-paragraph">Before this operator existed, I wrote a lot of <code>user &amp;&amp; user.name</code> or <code>user.nil? ? nil : user.name</code>. The <code>&amp;.</code> operator is cleaner and has become idiomatic in modern Ruby codebases.</p>



<h2 class="wp-block-heading">Type Checking and Conversion</h2>



<p class="wp-block-paragraph">I use these constantly when validating input or writing defensive code:</p>



<pre class="wp-block-code"><code>puts 5.is_a?(Numeric)
puts "5".is_a?(String)
puts 5.instance_of?(Integer)
puts "42".to_i
puts "3.14".to_f
puts 42.to_s
puts Integer("42")     # strict conversion, raises on invalid input
puts Integer("abc") rescue puts "conversion failed"
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>true
true
true
42
3.14
42
42
conversion failed
</code></pre>



<p class="wp-block-paragraph">I want to highlight the difference between <code>"abc".to_i</code> and <code>Integer("abc")</code>. <code>to_i</code> is forgiving — it silently returns <code>0</code> for unparseable input, which can hide real bugs. <code>Integer()</code> is strict — it raises <code>ArgumentError</code> on invalid input. I almost always prefer <code>Integer()</code> for user-facing input validation, precisely because I want it to fail loudly rather than silently coerce garbage into <code>0</code>.</p>



<h2 class="wp-block-heading">Real-World Application: Putting It All Together</h2>



<p class="wp-block-paragraph">Here&#8217;s a small, realistic example that uses all five types together — parsing a configuration hash from user input:</p>



<pre class="wp-block-code"><code># frozen_string_literal: true

def parse_config(raw)
  config = {}
  config&#91;:name] = raw&#91;:name]&amp;.to_s&amp;.strip || "unnamed"
  config&#91;:retries] = begin
    Integer(raw&#91;:retries])
  rescue ArgumentError, TypeError
    3
  end
  config&#91;:enabled] = raw&#91;:enabled] == true
  config&#91;:timeout] = raw&#91;:timeout].nil? ? 30.0 : raw&#91;:timeout].to_f
  config
end

result = parse_config(name: "  Worker  ", retries: "5", enabled: true)
puts result.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>{:name=&gt;"Worker", :retries=&gt;5, :enabled=&gt;true, :timeout=&gt;30.0}
</code></pre>



<p class="wp-block-paragraph">This little function uses symbols as hash keys, safe navigation for the string, strict integer parsing with a rescue fallback, boolean comparison, and nil-checking for the float default — a fairly typical slice of real Ruby code.</p>



<h2 class="wp-block-heading">Common Mistakes I See</h2>



<p class="wp-block-paragraph"><strong>Comparing floats for exact equality.</strong> Always use a tolerance (<code>(a - b).abs &lt; epsilon</code>) or <code>Rational</code>/<code>BigDecimal</code> for money.</p>



<p class="wp-block-paragraph"><strong>Assuming strings are immutable.</strong> Mutating a shared string reference is a classic source of &#8220;spooky action at a distance&#8221; bugs.</p>



<p class="wp-block-paragraph"><strong>Overusing dynamic symbol creation from user input.</strong> Stick to a known, bounded set of symbols.</p>



<p class="wp-block-paragraph"><strong>Forgetting that <code>0</code> and <code>""</code> are truthy in Ruby.</strong> This bites developers coming from other languages more than almost anything else on this list.</p>



<p class="wp-block-paragraph"><strong>Using <code>to_i</code>/<code>to_f</code> for validation instead of <code>Integer()</code>/<code>Float()</code>.</strong> Silent coercion to zero can hide bad input.</p>



<h2 class="wp-block-heading">Best Practices I Follow</h2>



<ul class="wp-block-list">
<li>Freeze string literals in new files with the magic comment, and <code>.dup</code> when you genuinely need a mutable copy.</li>



<li>Use symbols for identifiers (hash keys, method names) and strings for actual textual data.</li>



<li>Use <code>Rational</code> or <code>BigDecimal</code> for money and anything requiring exact decimal precision.</li>



<li>Prefer <code>Integer()</code>/<code>Float()</code> over <code>to_i</code>/<code>to_f</code> when validating external input.</li>



<li>Lean on the safe navigation operator (<code>&amp;.</code>) instead of manual nil checks where it improves readability.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby&#8217;s approach to data types reflects its broader design philosophy: consistency and elegance over special-casing. Numbers, strings, symbols, booleans, and even <code>nil</code> are all full-fledged objects that respond to methods, and understanding the subtle differences between them — mutability, identity, truthiness, encoding — pays off constantly in day-to-day Ruby development. Once these fundamentals are second nature, a huge category of subtle bugs simply stops happening in your code.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/Integer.html">Integer</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/String.html">String</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/Symbol.html">Symbol</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/NilClass.html">NilClass</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/syntax/control_expressions_md.html">Truthiness and control flow expressions</a></li>



<li>RubyGems Guides — <a href="https://guides.rubygems.org/">Gem specification basics and dependency types</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/ruby/standard-data-types-in-ruby-numbers-strings-symbols-booleans-and-nil-explained/">Standard Data Types in Ruby: Numbers, Strings, Symbols, Booleans, and Nil Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/standard-data-types-in-ruby-numbers-strings-symbols-booleans-and-nil-explained/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4226</post-id>	</item>
		<item>
		<title>Containers, Blocks, and Iterations in Ruby: Arrays, Hashes, Blocks, and Looping Constructs Guide</title>
		<link>https://awjunaid.com/ruby/containers-blocks-and-iterations-in-ruby-arrays-hashes-blocks-and-looping-constructs-guide/</link>
					<comments>https://awjunaid.com/ruby/containers-blocks-and-iterations-in-ruby-arrays-hashes-blocks-and-looping-constructs-guide/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Tue, 15 Aug 2023 13:16:08 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4223</guid>

					<description><![CDATA[<p>If there&#8217;s one thing that made me fall in love with Ruby early on, it&#8217;s how naturally I&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/containers-blocks-and-iterations-in-ruby-arrays-hashes-blocks-and-looping-constructs-guide/">Containers, Blocks, and Iterations in Ruby: Arrays, Hashes, Blocks, and Looping Constructs Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">If there&#8217;s one thing that made me fall in love with Ruby early on, it&#8217;s how naturally I can express &#8220;do this for every item&#8221; without wading through boilerplate. Coming from languages where iteration meant hand-rolled index variables and <code>for (int i = 0; ...)</code> loops, Ruby&#8217;s blocks and Enumerable methods felt like a different way of thinking entirely. In this article, I want to cover Ruby&#8217;s core containers — arrays and hashes — along with blocks, procs, lambdas, and the various looping constructs, and explain not just how to use them but why they&#8217;re built the way they are.</p>



<h2 class="wp-block-heading">Arrays: Ordered, Mixed-Type Collections</h2>



<p class="wp-block-paragraph">A Ruby <code>Array</code> is an ordered, integer-indexed collection that can hold objects of any type, mixed together in the same array:</p>



<pre class="wp-block-code"><code>mixed = &#91;1, "two", :three, 4.0, &#91;5, 6], { seven: 7 }]
puts mixed.inspect
puts mixed.length
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;1, "two", :three, 4.0, &#91;5, 6], {:seven=&gt;7}]
6
</code></pre>



<h3 class="wp-block-heading">Creating and Accessing Arrays</h3>



<pre class="wp-block-code"><code>numbers = &#91;10, 20, 30, 40, 50]

puts numbers&#91;0]        # 10
puts numbers&#91;-1]        # 50, negative indexing from the end
puts numbers&#91;1..3].inspect   # &#91;20, 30, 40], inclusive range
puts numbers&#91;1...3].inspect  # &#91;20, 30], exclusive range
puts numbers.first(2).inspect
puts numbers.last(2).inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>10
50
&#91;20, 30, 40]
&#91;20, 30]
&#91;10, 20]
&#91;40, 50]
</code></pre>



<p class="wp-block-paragraph">I use negative indexing and range slicing constantly — it eliminates a lot of the manual index math I used to write in other languages.</p>



<h3 class="wp-block-heading">Modifying Arrays</h3>



<pre class="wp-block-code"><code>arr = &#91;1, 2, 3]
arr.push(4)         # same as arr &lt;&lt; 4
arr &lt;&lt; 5
arr.unshift(0)
puts arr.inspect

arr.pop
arr.shift
puts arr.inspect

arr.insert(2, 99)
puts arr.inspect

arr.delete(99)
puts arr.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;1, 2, 3, 4, 5]
&#91;0, 1, 2, 3, 4]
&#91;0, 1, 99, 2, 3, 4]
&#91;0, 1, 2, 3, 4]
</code></pre>



<h3 class="wp-block-heading">Internal Working: How Arrays Store Data</h3>



<p class="wp-block-paragraph">Ruby&#8217;s <code>Array</code> is backed by a C-level dynamic array (similar in spirit to a <code>Vector</code> in C++ or <code>ArrayList</code> in Java), not a linked list. This means index-based access (<code>arr[5]</code>) is O(1), while inserting or removing from the front (<code>unshift</code>/<code>shift</code>) is O(n) because every subsequent element has to shift position in memory. I keep this in mind when choosing data structures for performance-sensitive code — if I&#8217;m doing a lot of front-insertion, I reconsider whether an array is really the right structure, or whether I should reverse my approach and append/pop from the end instead, which is O(1) amortized.</p>



<p class="wp-block-paragraph">Ruby also over-allocates capacity behind the scenes (similar to how many dynamic array implementations work), so that repeated <code>push</code> calls don&#8217;t require a full reallocation every single time — the array&#8217;s backing store grows in chunks, amortizing the cost of growth across many operations.</p>



<h2 class="wp-block-heading">Hashes: Key-Value Containers</h2>



<p class="wp-block-paragraph">A <code>Hash</code> maps keys to values, and in modern Ruby, hashes <strong>maintain insertion order</strong> — a guarantee that wasn&#8217;t always true in older Ruby versions, and one I rely on more than I probably should.</p>



<pre class="wp-block-code"><code>person = { name: "Aisha", age: 28, city: "Lahore" }
puts person.inspect
puts person&#91;:name]

person.each do |key, value|
  puts "#{key}: #{value}"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>{:name=&gt;"Aisha", :age=&gt;28, :city=&gt;"Lahore"}
Aisha
name: Aisha
age: 28
city: Lahore
</code></pre>



<h3 class="wp-block-heading">Hash Operations I Use Regularly</h3>



<pre class="wp-block-code"><code>h = { a: 1, b: 2 }
h&#91;:c] = 3
puts h.inspect

puts h.key?(:a)
puts h.fetch(:z, "default value")
puts h.merge(d: 4).inspect
puts h.select { |k, v| v &gt; 1 }.inspect
puts h.transform_values { |v| v * 10 }.inspect
puts h.to_a.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>{:a=&gt;1, :b=&gt;2, :c=&gt;3}
true
default value
{:a=&gt;1, :b=&gt;2, :c=&gt;3, :d=&gt;4}
{:b=&gt;2, :c=&gt;3}
{:a=&gt;10, :b=&gt;20, :c=&gt;30}
&#91;&#91;:a, 1], &#91;:b, 2], &#91;:c, 3]]
</code></pre>



<p class="wp-block-paragraph">I specifically want to call out <code>fetch</code> with a default — it&#8217;s a much safer habit than <code>h[:missing_key]</code>, which silently returns <code>nil</code> and can propagate <code>nil</code>-related bugs downstream. <code>fetch</code> without a default raises <code>KeyError</code>, which I actually prefer for catching typos in key names early.</p>



<h3 class="wp-block-heading">Internal Working: Hashes Are Hash Tables</h3>



<p class="wp-block-paragraph">Under the hood, a Ruby <code>Hash</code> is a genuine hash table: keys are run through a hash function to compute a bucket, giving average O(1) lookup, insertion, and deletion. The insertion-order guarantee is maintained separately, alongside the hash table structure, so you get both fast lookups and predictable iteration order — a combination that isn&#8217;t trivial to implement efficiently, and one of the reasons Ruby&#8217;s Hash implementation has been rewritten more than once over the years for performance.</p>



<p class="wp-block-paragraph">One practical consequence: mutable objects (like a plain <code>String</code>) make risky hash keys, because if you mutate the key object after inserting it, the hash&#8217;s internal bucket placement can become inconsistent with the object&#8217;s current hash value. This is part of why symbols — immutable and pre-hashed — are the idiomatic default for hash keys in Ruby.</p>



<h2 class="wp-block-heading">Blocks: Ruby&#8217;s Signature Feature</h2>



<p class="wp-block-paragraph">A block is a chunk of code you pass to a method, delimited either by <code>do...end</code> or curly braces <code>{ }</code>. This is the feature that makes Ruby&#8217;s iteration style so expressive.</p>



<pre class="wp-block-code"><code>&#91;1, 2, 3].each do |n|
  puts n * 2
end

&#91;1, 2, 3].each { |n| puts n * 2 }
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>2
4
6
2
4
6
</code></pre>



<p class="wp-block-paragraph">My personal convention: <code>{ }</code> for single-line blocks, <code>do...end</code> for multi-line blocks. It&#8217;s not enforced by the language, but it&#8217;s a widely followed community convention that makes code more scannable.</p>



<h3 class="wp-block-heading">yield: How Methods Receive Blocks</h3>



<p class="wp-block-paragraph">Any Ruby method can accept a block implicitly, and inside the method, <code>yield</code> hands control (and optional values) to that block:</p>



<pre class="wp-block-code"><code>def repeat_three_times
  yield 1
  yield 2
  yield 3
end

repeat_three_times { |n| puts "Iteration #{n}" }
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Iteration 1
Iteration 2
Iteration 3
</code></pre>



<p class="wp-block-paragraph">I can check whether a block was even given, and branch accordingly:</p>



<pre class="wp-block-code"><code>def greet
  if block_given?
    yield "Hello"
  else
    puts "No block given"
  end
end

greet { |msg| puts "#{msg}, friend!" }
greet
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Hello, friend!
No block given
</code></pre>



<p class="wp-block-paragraph">This is exactly how methods like <code>each</code>, <code>map</code>, and <code>select</code> are implemented internally within Ruby&#8217;s own C source — they call <code>yield</code> on each element and let the caller&#8217;s block decide what to do with it.</p>



<h2 class="wp-block-heading">Procs and Lambdas: Blocks as First-Class Objects</h2>



<p class="wp-block-paragraph">Blocks are convenient, but sometimes I want to store a chunk of code in a variable, pass it around, or call it later. That&#8217;s where <code>Proc</code> and <code>lambda</code> come in.</p>



<pre class="wp-block-code"><code>square = Proc.new { |n| n * n }
puts square.call(5)
puts square.(5)     # alternate call syntax
puts square&#91;5]        # yet another alternate call syntax

cube = lambda { |n| n ** 3 }
puts cube.call(3)

triple = -&gt;(n) { n * 3 }   # "stabby lambda" syntax
puts triple.call(4)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>25
25
25
27
12
</code></pre>



<h3 class="wp-block-heading">Procs vs Lambdas: The Real Differences</h3>



<p class="wp-block-paragraph">This distinction confused me for a long time, so let me be precise about it, because it genuinely matters in practice.</p>



<p class="wp-block-paragraph"><strong>Argument strictness.</strong> Lambdas enforce arity strictly; procs are forgiving:</p>



<pre class="wp-block-code"><code>lax_proc = Proc.new { |a, b| puts "a=#{a}, b=#{b}" }
lax_proc.call(1)   # doesn't raise, b is just nil

strict_lambda = lambda { |a, b| puts "a=#{a}, b=#{b}" }
begin
  strict_lambda.call(1)
rescue ArgumentError =&gt; e
  puts "Error: #{e.message}"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>a=1, b=
Error: wrong number of arguments (given 1, expected 2)
</code></pre>



<p class="wp-block-paragraph"><strong><code>return</code> behavior.</strong> This is the one that actually causes bugs. A <code>return</code> inside a lambda just exits the lambda, like a normal method. A <code>return</code> inside a proc tries to return from the <strong>enclosing method</strong>, which can raise <code>LocalJumpError</code> if that method has already finished executing.</p>



<pre class="wp-block-code"><code>def test_lambda_return
  l = lambda { return 10 }
  l.call
  puts "This line runs, because lambda's return only exits the lambda"
  20
end

def test_proc_return
  p = Proc.new { return 10 }
  p.call
  puts "This line never runs"
  20
end

puts test_lambda_return
puts test_proc_return
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>This line runs, because lambda's return only exits the lambda
20
10
</code></pre>



<p class="wp-block-paragraph">Because of this difference, I default to lambdas whenever I&#8217;m storing reusable logic in a variable, and I only reach for <code>Proc.new</code> when I specifically want the more permissive, block-like behavior.</p>



<h2 class="wp-block-heading">Enumerable: The Module That Powers Iteration</h2>



<p class="wp-block-paragraph">Almost every collection method you use in Ruby beyond basic <code>each</code> — <code>map</code>, <code>select</code>, <code>reject</code>, <code>reduce</code>, <code>sort_by</code>, <code>group_by</code>, and dozens more — comes from the <code>Enumerable</code> module, which is mixed into <code>Array</code>, <code>Hash</code>, <code>Range</code>, and any custom class that defines <code>each</code> and includes <code>Enumerable</code>.</p>



<pre class="wp-block-code"><code>numbers = &#91;1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

puts numbers.map { |n| n * n }.inspect
puts numbers.select { |n| n.even? }.inspect
puts numbers.reject { |n| n.even? }.inspect
puts numbers.reduce(:+)
puts numbers.reduce(0) { |sum, n| sum + n }
puts numbers.group_by { |n| n % 3 }.inspect
puts numbers.sort_by { |n| -n }.first(3).inspect
puts numbers.partition { |n| n &gt; 5 }.inspect
puts numbers.each_slice(3).to_a.inspect
puts numbers.each_cons(2).to_a.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
&#91;2, 4, 6, 8, 10]
&#91;1, 3, 5, 7, 9]
55
55
{1=&gt;&#91;1, 4, 7, 10], 2=&gt;&#91;2, 5, 8], 0=&gt;&#91;3, 6, 9]}
&#91;10, 9, 8]
&#91;&#91;6, 7, 8, 9, 10], &#91;1, 2, 3, 4, 5]]
&#91;&#91;1, 2, 3], &#91;4, 5, 6], &#91;7, 8, 9], &#91;10]]
&#91;&#91;1, 2], &#91;2, 3], &#91;3, 4], &#91;4, 5], &#91;5, 6], &#91;6, 7], &#91;7, 8], &#91;8, 9], &#91;9, 10]]
</code></pre>



<p class="wp-block-paragraph">I genuinely reach for <code>Enumerable</code> methods before I write a manual loop in almost every situation. <code>reduce</code>/<code>inject</code> in particular replaced a huge amount of manual accumulator-variable code I used to write.</p>



<h3 class="wp-block-heading">Building a Custom Enumerable Class</h3>



<p class="wp-block-paragraph">Here&#8217;s something I find genuinely elegant about Ruby: I can make my own class fully iterable just by defining <code>each</code> and including <code>Enumerable</code>.</p>



<pre class="wp-block-code"><code>class TeamRoster
  include Enumerable

  def initialize
    @players = &#91;]
  end

  def add(player)
    @players &lt;&lt; player
    self
  end

  def each
    @players.each { |p| yield p }
  end
end

roster = TeamRoster.new
roster.add("Zara").add("Bilal").add("Omar")

puts roster.map(&amp;:upcase).inspect
puts roster.select { |p| p.length &gt; 4 }.inspect
puts roster.sort.inspect
puts roster.count
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;"ZARA", "BILAL", "OMAR"]
&#91;"Zara", "Bilal"]
&#91;"Bilal", "Omar", "Zara"]
3
</code></pre>



<p class="wp-block-paragraph">I only had to write <code>each</code> — <code>map</code>, <code>select</code>, <code>sort</code>, and <code>count</code> all came for free from <code>Enumerable</code>. This is a good example of Ruby&#8217;s mixin-based design philosophy: define one primitive method, and inherit a whole vocabulary of behavior built on top of it.</p>



<h2 class="wp-block-heading">Looping Constructs</h2>



<p class="wp-block-paragraph">Beyond <code>each</code> and friends, Ruby has traditional loop constructs, though I use them less often than block-based iteration.</p>



<pre class="wp-block-code"><code>i = 0
while i &lt; 3
  puts "while: #{i}"
  i += 1
end

i = 0
until i &gt;= 3
  puts "until: #{i}"
  i += 1
end

3.times { |i| puts "times: #{i}" }

for i in 0..2
  puts "for: #{i}"
end

loop do
  i += 1
  break if i &gt; 5
  next if i.even?
  puts "loop: #{i}"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>while: 0
while: 1
while: 2
until: 0
until: 1
until: 2
times: 0
times: 1
times: 2
for: 0
for: 1
for: 2
loop: 3
loop: 5
</code></pre>



<p class="wp-block-paragraph">A subtlety worth knowing: <code>for...in</code> does <strong>not</strong> create a new scope for its loop variable — <code>i</code> leaks into the surrounding scope after the loop ends. <code>each</code> with a block, by contrast, keeps the block variable scoped to the block itself. This is one of several reasons the Ruby community strongly favors <code>each</code>/<code>times</code>/<code>map</code> over <code>for</code> loops — I basically never use <code>for</code> in real code anymore, and I&#8217;d recommend you don&#8217;t either.</p>



<pre class="wp-block-code"><code>for i in 1..3; end
puts i   # 3, i still exists here - leaked from the loop

&#91;1, 2, 3].each { |j| }
puts defined?(j)  # nil, j does not exist outside the block
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>3

</code></pre>



<h2 class="wp-block-heading">Practical, Real-World Example</h2>



<p class="wp-block-paragraph">Here&#8217;s a small realistic script that ties containers, blocks, and iteration together — grouping a list of orders by status and computing totals:</p>



<pre class="wp-block-code"><code>orders = &#91;
  { id: 1, status: :shipped, total: 49.99 },
  { id: 2, status: :pending, total: 19.50 },
  { id: 3, status: :shipped, total: 89.00 },
  { id: 4, status: :cancelled, total: 15.00 },
  { id: 5, status: :pending, total: 32.25 }
]

summary = orders.group_by { |order| order&#91;:status] }.transform_values do |group|
  { count: group.size, total: group.sum { |o| o&#91;:total] }.round(2) }
end

summary.each do |status, data|
  puts "#{status}: #{data&#91;:count]} orders, $#{data&#91;:total]}"
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>shipped: 2 orders, $138.99
pending: 2 orders, $51.75
cancelled: 1 orders, $15.0
</code></pre>



<p class="wp-block-paragraph">This is the kind of code I write daily in real applications — no manual loop counters, no mutable accumulator variables scattered around, just composed, declarative transformations.</p>



<h2 class="wp-block-heading">Common Mistakes I See</h2>



<p class="wp-block-paragraph"><strong>Mutating a collection while iterating over it.</strong> This produces unpredictable results (skipped elements, <code>IndexError</code>s). Use <code>select</code>/<code>reject</code> to build a new collection, or <code>each.to_a.each</code> style patterns, rather than deleting elements mid-<code>each</code>.</p>



<p class="wp-block-paragraph"><strong>Using <code>for</code> loops out of old habit.</strong> As shown above, it leaks scope and offers no real benefit over <code>each</code>.</p>



<p class="wp-block-paragraph"><strong>Confusing <code>map</code> with <code>each</code>.</strong> <code>each</code> returns the original collection unchanged and is for side effects; <code>map</code> returns a new, transformed collection. Using <code>each</code> when you meant <code>map</code> is a very common beginner mistake.</p>



<p class="wp-block-paragraph"><strong>Using mutable objects as hash keys</strong> and then mutating them after insertion, which can silently break lookups.</p>



<p class="wp-block-paragraph"><strong>Reaching for <code>Proc.new</code> when a lambda is what&#8217;s actually needed</strong>, especially when strict argument checking matters.</p>



<h2 class="wp-block-heading">Best Practices I Follow</h2>



<ul class="wp-block-list">
<li>Prefer <code>Enumerable</code> methods (<code>map</code>, <code>select</code>, <code>reduce</code>, <code>group_by</code>) over manual loops for anything beyond the most trivial iteration.</li>



<li>Use lambdas over procs by default, and reserve <code>Proc.new</code> for cases where the loose arity and <code>return</code> behavior are actually wanted.</li>



<li>Use symbols as hash keys unless you have a specific reason to use strings.</li>



<li>Build custom classes on top of <code>Enumerable</code> by defining <code>each</code> — it&#8217;s a small investment for a large payoff in expressiveness.</li>



<li>Avoid <code>for...in</code>; use <code>each</code>, <code>times</code>, or <code>map</code> instead, for proper variable scoping.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby&#8217;s containers and iteration tools reflect the language&#8217;s core philosophy: express intent, not mechanics. Arrays and hashes give you fast, well-understood data structures backed by dynamic arrays and hash tables respectively. Blocks, procs, and lambdas let you treat chunks of behavior as first-class values, with lambdas offering the stricter, more predictable semantics I reach for by default. And the <code>Enumerable</code> module ties it all together, turning a single <code>each</code> method into an entire vocabulary of <code>map</code>, <code>select</code>, <code>reduce</code>, and more — both for built-in collections and for your own custom classes. Once you get comfortable thinking in terms of blocks and enumerable transformations rather than manual loops, your Ruby code naturally becomes shorter, safer, and more expressive.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/Array.html">Array</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/Hash.html">Hash</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/Enumerable.html">Enumerable module</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/Proc.html">Proc class</a></li>



<li>Ruby Official Documentation — <a href="https://docs.ruby-lang.org/en/master/syntax/control_expressions_md.html">Control expressions and looping constructs</a></li>



<li>RubyGems Guides — <a href="https://guides.rubygems.org/make-your-own-gem/">Make your own gem</a></li>
</ul>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://awjunaid.com/ruby/containers-blocks-and-iterations-in-ruby-arrays-hashes-blocks-and-looping-constructs-guide/">Containers, Blocks, and Iterations in Ruby: Arrays, Hashes, Blocks, and Looping Constructs Guide</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/containers-blocks-and-iterations-in-ruby-arrays-hashes-blocks-and-looping-constructs-guide/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4223</post-id>	</item>
		<item>
		<title>Classes, Objects, and Variables in Ruby: Object-Oriented Programming Foundations Explained</title>
		<link>https://awjunaid.com/ruby/classes-objects-and-variables-in-ruby-object-oriented-programming-foundations-explained/</link>
					<comments>https://awjunaid.com/ruby/classes-objects-and-variables-in-ruby-object-oriented-programming-foundations-explained/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Tue, 15 Aug 2023 13:11:38 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4220</guid>

					<description><![CDATA[<p>When I first started learning Ruby, I remember being confused by how effortlessly everything seemed to &#8220;just work.&#8221;&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/classes-objects-and-variables-in-ruby-object-oriented-programming-foundations-explained/">Classes, Objects, and Variables in Ruby: Object-Oriented Programming Foundations Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">When I first started learning Ruby, I remember being confused by how effortlessly everything seemed to &#8220;just work.&#8221; I&#8217;d write a class, create an object, call a method, and get a sensible result without fighting the language. It took me a while to realize that this smoothness isn&#8217;t an accident — it&#8217;s a direct result of how deliberately Ruby was designed around object-oriented principles. Every single thing you touch in Ruby, from a simple integer to a full-blown class definition, is an object with behavior and state.</p>



<p class="wp-block-paragraph">In this article, I want to walk you through classes, objects, and variables in Ruby the way I wish someone had explained them to me — starting from the absolute basics and working up to the internal mechanics that make Ruby&#8217;s object model so elegant. By the end, you&#8217;ll not only know how to write classes, but you&#8217;ll understand <em>why</em> they behave the way they do.</p>



<h2 class="wp-block-heading">Why Object-Oriented Programming Matters in Ruby</h2>



<p class="wp-block-paragraph">Object-oriented programming (OOP) is a paradigm that organizes code around &#8220;objects&#8221; — bundles of data (state) and behavior (methods) that model real-world or logical entities. Instead of writing a pile of loose functions that operate on raw data, you group related data and the operations on that data into a single unit: a class.</p>



<p class="wp-block-paragraph">Ruby takes OOP further than most mainstream languages. In Python, JavaScript, or even Java, there are primitive types that sit outside the object system to some degree. In Ruby, there are no primitives. <code>42</code> is an object. <code>true</code> is an object. <code>nil</code> is an object. Even classes themselves are objects (instances of the class <code>Class</code>). This consistency is what gives Ruby its reputation for being intuitive once it clicks.</p>



<h2 class="wp-block-heading">What Is a Class in Ruby?</h2>



<p class="wp-block-paragraph">A class is a blueprint. It defines what data an object of that type will hold and what behavior it will expose. Think of a class like an architectural drawing for a house — the drawing itself isn&#8217;t a house you can live in, but it tells you exactly how to build one.</p>



<p class="wp-block-paragraph">Here&#8217;s the simplest class I can show you:</p>



<pre class="wp-block-code"><code>class Dog
end

my_pet = Dog.new
puts my_pet.class
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Dog
</code></pre>



<p class="wp-block-paragraph">That&#8217;s it. <code>Dog.new</code> creates a new object — an <em>instance</em> — of the <code>Dog</code> class. Right now this dog doesn&#8217;t do anything interesting, so let&#8217;s give it some data and behavior.</p>



<h2 class="wp-block-heading">Creating Objects with <code>initialize</code></h2>



<p class="wp-block-paragraph">Every Ruby class can define a special method called <code>initialize</code>, which runs automatically whenever you call <code>.new</code>. This is Ruby&#8217;s constructor.</p>



<pre class="wp-block-code"><code>class Dog
  def initialize(name, breed)
    @name = name
    @breed = breed
  end

  def bark
    "#{@name} says: Woof!"
  end
end

rex = Dog.new("Rex", "German Shepherd")
puts rex.bark
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Rex says: Woof!
</code></pre>



<p class="wp-block-paragraph">Notice the <code>@name</code> and <code>@breed</code> variables. These are instance variables, and they&#8217;re the primary way an object stores its own private state. I&#8217;ll explain them in more depth in a moment, but the key idea is this: each object you create from a class gets its own independent copy of these variables.</p>



<pre class="wp-block-code"><code>milo = Dog.new("Milo", "Beagle")
puts milo.bark
puts rex.bark
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Milo says: Woof!
Rex says: Woof!
</code></pre>



<p class="wp-block-paragraph"><code>rex</code> and <code>milo</code> are separate objects with separate state, even though they were built from the same class.</p>



<h2 class="wp-block-heading">Understanding Variables in Ruby</h2>



<p class="wp-block-paragraph">Ruby has several types of variables, and knowing when to use each one is a big part of writing clean object-oriented code.</p>



<h3 class="wp-block-heading">Local Variables</h3>



<p class="wp-block-paragraph">Local variables live inside the scope where they&#8217;re defined — a method, a block, or the top level of a script. They start with a lowercase letter or underscore.</p>



<pre class="wp-block-code"><code>def greet
  message = "Hello there"
  puts message
end

greet
</code></pre>



<p class="wp-block-paragraph">Once <code>greet</code> finishes executing, <code>message</code> no longer exists. Local variables can&#8217;t be accessed outside their scope, which keeps your code predictable and free of accidental interference between unrelated parts of a program.</p>



<h3 class="wp-block-heading">Instance Variables</h3>



<p class="wp-block-paragraph">Instance variables start with an <code>@</code> symbol and belong to a specific object. They hold the state of that object and are accessible from any instance method within the class.</p>



<pre class="wp-block-code"><code>class BankAccount
  def initialize(owner, balance)
    @owner = owner
    @balance = balance
  end

  def deposit(amount)
    @balance += amount
  end

  def summary
    "#{@owner}'s balance is $#{@balance}"
  end
end

account = BankAccount.new("Sara", 100)
account.deposit(50)
puts account.summary
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Sara's balance is $150
</code></pre>



<p class="wp-block-paragraph">Notice that <code>@balance</code> isn&#8217;t visible outside the class unless you explicitly expose it. This is encapsulation in action — the object controls how its internal state can be changed.</p>



<h3 class="wp-block-heading">Class Variables</h3>



<p class="wp-block-paragraph">Class variables start with <code>@@</code> and are shared across <em>all</em> instances of a class, as well as any subclasses. I use these sparingly because they can create subtle bugs if you&#8217;re not careful, especially in inheritance hierarchies.</p>



<pre class="wp-block-code"><code>class Car
  @@total_cars = 0

  def initialize(model)
    @model = model
    @@total_cars += 1
  end

  def self.total
    @@total_cars
  end
end

Car.new("Civic")
Car.new("Corolla")
puts Car.total
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>2
</code></pre>



<p class="wp-block-paragraph">Here, <code>@@total_cars</code> tracks how many <code>Car</code> objects have been created, no matter which instance triggered the increment.</p>



<h3 class="wp-block-heading">Global Variables</h3>



<p class="wp-block-paragraph">Global variables start with <code>$</code> and are accessible from anywhere in your program. I avoid these almost entirely in real projects because they break encapsulation and make code harder to reason about, but it&#8217;s worth knowing they exist.</p>



<pre class="wp-block-code"><code>$app_name = "InventoryTracker"

def show_app_name
  puts $app_name
end

show_app_name
</code></pre>



<h3 class="wp-block-heading">Constants</h3>



<p class="wp-block-paragraph">Constants start with an uppercase letter and are meant to hold values that shouldn&#8217;t change. Ruby won&#8217;t stop you from reassigning a constant, but it will warn you.</p>



<pre class="wp-block-code"><code>class Circle
  PI = 3.14159

  def initialize(radius)
    @radius = radius
  end

  def area
    PI * @radius ** 2
  end
end

puts Circle.new(4).area
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>50.26544
</code></pre>



<h2 class="wp-block-heading">Accessing Instance Variables: Getters and Setters</h2>



<p class="wp-block-paragraph">By default, instance variables are private to the object. If you try to read <code>@balance</code> from outside the <code>BankAccount</code> class, Ruby will complain. To expose data safely, you write accessor methods — or let Ruby generate them for you.</p>



<pre class="wp-block-code"><code>class Person
  def name
    @name
  end

  def name=(new_name)
    @name = new_name
  end

  def initialize(name)
    @name = name
  end
end

person = Person.new("Ahmed")
puts person.name
person.name = "Ahmed Khan"
puts person.name
</code></pre>



<p class="wp-block-paragraph">Writing getters and setters manually gets repetitive fast, so Ruby gives you a shortcut: <code>attr_accessor</code>, <code>attr_reader</code>, and <code>attr_writer</code>.</p>



<pre class="wp-block-code"><code>class Person
  attr_accessor :name
  attr_reader :id

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

p = Person.new("Ayesha", 101)
puts p.name
p.name = "Ayesha Malik"
puts p.name
puts p.id
</code></pre>



<p class="wp-block-paragraph"><code>attr_accessor</code> generates both a getter and setter, <code>attr_reader</code> generates only a getter, and <code>attr_writer</code> generates only a setter. I use <code>attr_reader</code> for things like IDs that shouldn&#8217;t change after creation, and <code>attr_accessor</code> for anything meant to be freely readable and writable.</p>



<h2 class="wp-block-heading">The Internal Object Model: How Ruby Actually Stores This</h2>



<p class="wp-block-paragraph">This is the part that made everything click for me. Internally, every Ruby object has:</p>



<ol class="wp-block-list">
<li>A pointer to its class (which determines what methods it can respond to).</li>



<li>A hash-like table of instance variables, created lazily the first time they&#8217;re assigned.</li>
</ol>



<p class="wp-block-paragraph">When you call <code>rex.bark</code>, Ruby doesn&#8217;t search the object itself for a <code>bark</code> method — objects don&#8217;t store methods directly. Instead, Ruby looks up <code>rex</code>&#8216;s class (<code>Dog</code>), and if <code>Dog</code> doesn&#8217;t define <code>bark</code>, Ruby walks up what&#8217;s called the <strong>method lookup chain</strong> (or ancestor chain): from the object&#8217;s class, to any included modules, to the superclass, all the way up to <code>BasicObject</code>.</p>



<p class="wp-block-paragraph">You can inspect this chain yourself:</p>



<pre class="wp-block-code"><code>puts Dog.ancestors.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;Dog, Object, Kernel, BasicObject]
</code></pre>



<p class="wp-block-paragraph">This lookup mechanism is why methods defined in a superclass are automatically available to subclasses, and it&#8217;s the backbone of Ruby&#8217;s inheritance and mixin system.</p>



<p class="wp-block-paragraph">Instance variables, on the other hand, are <em>not</em> looked up through this chain. They belong strictly to the object instance, stored in that object&#8217;s own variable table. This is why two objects of the same class never accidentally share instance variable values — each object&#8217;s <code>@name</code> lives in a completely separate slot in memory.</p>



<h2 class="wp-block-heading">Memory Management and Object Lifecycle</h2>



<p class="wp-block-paragraph">Ruby uses automatic memory management through garbage collection, so you rarely need to think about freeing memory manually. When you create an object with <code>.new</code>, Ruby allocates memory for it on the heap. As long as something references that object — a variable, an array, another object&#8217;s instance variable — it stays alive.</p>



<pre class="wp-block-code"><code>def create_temp_object
  temp = Dog.new("Ghost", "Unknown")
  temp.bark
end

create_temp_object
</code></pre>



<p class="wp-block-paragraph">Once <code>create_temp_object</code> returns, nothing references <code>temp</code> anymore, and Ruby&#8217;s garbage collector (which uses a mark-and-sweep algorithm, generational since Ruby 2.1+) will reclaim that memory during its next collection cycle. You can observe object counts and force garbage collection for debugging purposes:</p>



<pre class="wp-block-code"><code>GC.start
puts ObjectSpace.count_objects&#91;:T_OBJECT]
</code></pre>



<p class="wp-block-paragraph">I rarely need to call <code>GC.start</code> manually in production code, but understanding that it exists helps when you&#8217;re debugging memory bloat in a long-running Ruby process, like a Rails server handling thousands of requests.</p>



<h2 class="wp-block-heading">Object Identity vs Object Equality</h2>



<p class="wp-block-paragraph">A subtlety that trips up a lot of newcomers is the difference between two objects being <em>equal</em> and two objects being the <em>same object in memory</em>.</p>



<pre class="wp-block-code"><code>a = "hello"
b = "hello"

puts a == b
puts a.equal?(b)
puts a.object_id
puts b.object_id
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>true
false
123456789
987654321
</code></pre>



<p class="wp-block-paragraph"><code>==</code> checks value equality, while <code>.equal?</code> checks object identity — whether both variables point to the exact same object in memory. Every object has a unique <code>object_id</code>, and understanding this distinction matters a lot when you&#8217;re debugging why mutating one variable seems to (or doesn&#8217;t) affect another.</p>



<pre class="wp-block-code"><code>c = a
c &lt;&lt; " world"
puts a
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>hello world
</code></pre>



<p class="wp-block-paragraph">Here, <code>c = a</code> doesn&#8217;t copy the string — it copies the <em>reference</em>. Both <code>a</code> and <code>c</code> point to the same object, so mutating <code>c</code> also changes what <code>a</code> sees. This is a common source of bugs for people coming from languages with different assignment semantics, so I&#8217;d genuinely recommend spending real time experimenting with <code>object_id</code> and <code>.dup</code> / <code>.clone</code> until this feels natural.</p>



<h2 class="wp-block-heading">Practical Real-World Example: A Task Manager</h2>



<p class="wp-block-paragraph">Let&#8217;s put everything together in something closer to real code you might actually write.</p>



<pre class="wp-block-code"><code>class Task
  attr_accessor :title, :done
  attr_reader :created_at

  def initialize(title)
    @title = title
    @done = false
    @created_at = Time.now
  end

  def complete!
    @done = true
  end

  def status
    @done ? "✅ Done" : "🕒 Pending"
  end

  def to_s
    "#{title} - #{status}"
  end
end

class TaskList
  def initialize
    @tasks = &#91;]
  end

  def add(title)
    @tasks &lt;&lt; Task.new(title)
  end

  def complete(index)
    @tasks&#91;index].complete! if @tasks&#91;index]
  end

  def show_all
    @tasks.each_with_index do |task, i|
      puts "#{i}: #{task}"
    end
  end
end

list = TaskList.new
list.add("Write blog post")
list.add("Review pull request")
list.complete(0)
list.show_all
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>0: Write blog post - ✅ Done
1: Review pull request - 🕒 Pending
</code></pre>



<p class="wp-block-paragraph">This small example demonstrates encapsulation (each <code>Task</code> manages its own state), composition (<code>TaskList</code> holds an array of <code>Task</code> objects), and clean accessor usage — patterns you&#8217;ll use constantly in real Ruby applications, from Rails models to command-line tools.</p>



<h2 class="wp-block-heading">Best Practices I&#8217;ve Learned the Hard Way</h2>



<ul class="wp-block-list">
<li><strong>Prefer <code>attr_accessor</code>/<code>attr_reader</code> over manual getters</strong> unless you need custom logic in the setter — it keeps classes shorter and more readable.</li>



<li><strong>Avoid class variables (<code>@@</code>) in inheritance hierarchies.</strong> They&#8217;re shared across subclasses in ways that often surprise people; class instance variables (a class-level <code>@variable</code> combined with <code>self.</code> methods) are usually a safer choice.</li>



<li><strong>Keep instance variables private by default.</strong> Only expose what callers actually need. Encapsulation isn&#8217;t bureaucracy — it&#8217;s what lets you change internal implementation later without breaking everyone who uses your class.</li>



<li><strong>Use <code>to_s</code> and <code>inspect</code> deliberately.</strong> Overriding <code>to_s</code> makes <code>puts</code> and string interpolation produce readable output, which pays off enormously during debugging.</li>



<li><strong>Watch out for shared mutable state</strong>, especially with arrays and hashes assigned as default values in <code>initialize</code>. Assigning <code>@items = []</code> inside <code>initialize</code> (not as a class-level default) avoids one array being accidentally shared across every instance.</li>
</ul>



<h2 class="wp-block-heading">Common Mistakes to Avoid</h2>



<p class="wp-block-paragraph">One mistake I made early on was defining default values for instance variables at the class level instead of inside <code>initialize</code>, which led to every instance sharing the same array:</p>



<pre class="wp-block-code"><code># Problematic pattern
class ShoppingCart
  @@items = &#91;]  # shared across all carts!

  def add(item)
    @@items &lt;&lt; item
  end
end
</code></pre>



<p class="wp-block-paragraph">The fix is to always initialize per-instance state inside <code>initialize</code> using <code>@</code>, not <code>@@</code>.</p>



<p class="wp-block-paragraph">Another common mistake is forgetting that instance variables default to <code>nil</code> if never assigned, which can cause silent bugs rather than loud errors:</p>



<pre class="wp-block-code"><code>class Product
  def initialize(name)
    @name = name
  end

  def price
    @price * 1.1
  end
end

Product.new("Pen").price
</code></pre>



<p class="wp-block-paragraph">This raises a <code>NoMethodError</code> because <code>@price</code> is <code>nil</code> and <code>nil</code> doesn&#8217;t understand <code>*</code>. Always initialize every instance variable your object depends on, even if just to a sensible default like <code>0</code>.</p>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Classes give you a blueprint for creating objects, and objects are the living instances that carry their own independent state through instance variables. Ruby&#8217;s variable system — local, instance, class, global, and constants — gives you precise control over scope and visibility, while accessor methods let you decide exactly what parts of an object&#8217;s internal state are exposed to the outside world. Underneath all of this, Ruby&#8217;s object model treats everything as an object with a class pointer and its own variable table, using method lookup chains for behavior and independent storage for state. Understanding this foundation makes everything else in Ruby — inheritance, modules, metaprogramming — dramatically easier to reason about.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li><a href="https://www.ruby-lang.org/en/documentation/">Ruby Official Documentation</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Class.html">Ruby Core: Class</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Object.html">Ruby Core: Object</a></li>



<li><a href="https://guides.rubygems.org/">RubyGems Guides</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/GC.html">Ruby Core: GC Module</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/ruby/classes-objects-and-variables-in-ruby-object-oriented-programming-foundations-explained/">Classes, Objects, and Variables in Ruby: Object-Oriented Programming Foundations Explained</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/classes-objects-and-variables-in-ruby-object-oriented-programming-foundations-explained/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4220</post-id>	</item>
		<item>
		<title>Ruby Is an Object-Oriented Language: Understanding Objects, Methods, and Inheritance in Ruby</title>
		<link>https://awjunaid.com/ruby/ruby-is-an-object-oriented-language-understanding-objects-methods-and-inheritance-in-ruby/</link>
					<comments>https://awjunaid.com/ruby/ruby-is-an-object-oriented-language-understanding-objects-methods-and-inheritance-in-ruby/?noamp=mobile#respond</comments>
		
		<dc:creator><![CDATA[Abdul Wahab Junaid]]></dc:creator>
		<pubDate>Tue, 15 Aug 2023 13:01:23 +0000</pubDate>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ruby]]></category>
		<guid isPermaLink="false">https://awjunaid.com/?p=4217</guid>

					<description><![CDATA[<p>I still remember the exact moment Ruby&#8217;s philosophy clicked for me. I typed 3.times { puts "hi" }&#8230;</p>
<p>The post <a href="https://awjunaid.com/ruby/ruby-is-an-object-oriented-language-understanding-objects-methods-and-inheritance-in-ruby/">Ruby Is an Object-Oriented Language: Understanding Objects, Methods, and Inheritance in Ruby</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">I still remember the exact moment Ruby&#8217;s philosophy clicked for me. I typed <code>3.times { puts "hi" }</code> into an <code>irb</code> session, half expecting an error, because in every other language I&#8217;d used up to that point, <code>3</code> was just a dumb number — not something you could call methods on. But it worked. <code>3</code> was an object. It had methods. That&#8217;s when I understood the phrase people kept repeating: &#8220;In Ruby, everything is an object.&#8221;</p>



<p class="wp-block-paragraph">In this article, I want to dig into what that actually means in practice, how methods work under the hood, and how inheritance and modules let you build flexible, reusable object hierarchies. This isn&#8217;t just theory — I&#8217;ll walk through real code, real output, and the mistakes I made before this stuff felt natural.</p>



<h2 class="wp-block-heading">Everything Really Is an Object</h2>



<p class="wp-block-paragraph">In many languages, there&#8217;s a hard split between &#8220;primitive types&#8221; (integers, booleans) and &#8220;objects&#8221; (things with methods). Ruby refuses to make that split. Numbers, strings, <code>true</code>, <code>false</code>, <code>nil</code>, arrays, even classes themselves — all objects, all instances of some class, all capable of responding to methods.</p>



<pre class="wp-block-code"><code>puts 5.class
puts true.class
puts nil.class
puts "hello".class
puts &#91;1, 2, 3].class
puts Integer.class
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Integer
TrueClass
NilClass
String
Array
Class
</code></pre>



<p class="wp-block-paragraph">Notice that last line: <code>Integer.class</code> returns <code>Class</code>. Even a class is an object — an instance of the class <code>Class</code>. This is what people mean when they say Ruby&#8217;s object model goes &#8220;all the way down.&#8221; There&#8217;s no escape hatch to some non-object primitive layer.</p>



<p class="wp-block-paragraph">This matters practically, not just philosophically. Because everything is an object, everything can have methods called on it, be passed around, be reopened and extended, and participate fully in the object-oriented features I&#8217;ll cover below.</p>



<pre class="wp-block-code"><code>puts 5.even?
puts (-5).abs
puts nil.to_a.inspect
puts "ruby".upcase
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>false
5
&#91;]
RUBY
</code></pre>



<h2 class="wp-block-heading">What Exactly Is a Method?</h2>



<p class="wp-block-paragraph">A method is a named, reusable block of behavior attached to a class. When you call <code>obj.method_name</code>, you&#8217;re sending a message to <code>obj</code>, asking it to execute the behavior defined by <code>method_name</code> in its class (or an ancestor of its class).</p>



<pre class="wp-block-code"><code>class Greeter
  def hello(name)
    "Hello, #{name}!"
  end
end

g = Greeter.new
puts g.hello("World")
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Hello, World!
</code></pre>



<h3 class="wp-block-heading">Method Visibility: Public, Private, and Protected</h3>



<p class="wp-block-paragraph">Ruby lets you control which methods can be called from outside an object, using three visibility levels.</p>



<pre class="wp-block-code"><code>class Account
  def initialize(balance)
    @balance = balance
  end

  def display_balance
    "Balance: #{formatted_balance}"
  end

  private

  def formatted_balance
    "$#{@balance}"
  end
end

acc = Account.new(500)
puts acc.display_balance
puts acc.formatted_balance
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Balance: $500
</code></pre>



<p class="wp-block-paragraph">The second call raises a <code>NoMethodError</code> because <code>formatted_balance</code> is private — it can only be called from within the object itself, without an explicit receiver. I use <code>private</code> for internal helper methods that support public behavior but shouldn&#8217;t be part of the object&#8217;s external contract. <code>protected</code> is similar but allows calling the method on other instances of the same class, which is useful for comparison methods:</p>



<pre class="wp-block-code"><code>class Money
  def initialize(amount)
    @amount = amount
  end

  def &gt;(other)
    amount &gt; other.amount
  end

  protected

  attr_reader :amount
end

puts Money.new(100) &gt; Money.new(50)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>true
</code></pre>



<h3 class="wp-block-heading">Class Methods vs Instance Methods</h3>



<p class="wp-block-paragraph">Instance methods operate on individual objects. Class methods operate on the class itself and are defined with <code>self.</code> or inside <code>class &lt;&lt; self</code>.</p>



<pre class="wp-block-code"><code>class Product
  @@catalog = &#91;]

  def initialize(name, price)
    @name = name
    @price = price
    @@catalog &lt;&lt; self
  end

  def self.total_products
    @@catalog.size
  end

  def self.most_expensive
    @@catalog.max_by { |p| p.instance_variable_get(:@price) }
  end
end

Product.new("Laptop", 1200)
Product.new("Mouse", 25)
puts Product.total_products
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>2
</code></pre>



<p class="wp-block-paragraph">I reach for class methods when the behavior conceptually belongs to the class as a whole rather than to a single instance — things like factory methods, counters, or finder methods.</p>



<h2 class="wp-block-heading">How Method Lookup Actually Works</h2>



<p class="wp-block-paragraph">This is where Ruby&#8217;s object-oriented design becomes genuinely elegant. When you call a method on an object, Ruby doesn&#8217;t search the object — it searches the object&#8217;s <strong>ancestor chain</strong>, a linear sequence of classes and modules that Ruby walks through in order until it finds a matching method.</p>



<pre class="wp-block-code"><code>class Animal
  def speak
    "Some generic sound"
  end
end

class Dog &lt; Animal
end

puts Dog.ancestors.inspect
puts Dog.new.speak
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;Dog, Animal, Object, Kernel, BasicObject]
</code></pre>



<pre class="wp-block-code"><code>Some generic sound
</code></pre>



<p class="wp-block-paragraph"><code>Dog</code> doesn&#8217;t define <code>speak</code>, so Ruby walks up the chain to <code>Animal</code>, finds it there, and executes it. This lookup process is deterministic and inspectable, which makes debugging &#8220;where did this method come from?&#8221; questions much easier than in languages with less transparent dispatch mechanisms.</p>



<h2 class="wp-block-heading">Inheritance: Building on What Already Exists</h2>



<p class="wp-block-paragraph">Inheritance lets you define a general class and then create more specific classes that automatically get all its behavior, while being free to override or extend it.</p>



<pre class="wp-block-code"><code>class Animal
  attr_reader :name

  def initialize(name)
    @name = name
  end

  def speak
    "#{name} makes a sound"
  end
end

class Dog &lt; Animal
  def speak
    "#{name} barks: Woof!"
  end
end

class Cat &lt; Animal
  def speak
    "#{name} meows: Meow!"
  end
end

&#91;Dog.new("Rex"), Cat.new("Whiskers")].each do |animal|
  puts animal.speak
end
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Rex barks: Woof!
Whiskers meows: Meow!
</code></pre>



<p class="wp-block-paragraph">This is <strong>polymorphism</strong> — different classes responding to the same method call (<code>speak</code>) in ways appropriate to their own type. The calling code doesn&#8217;t need to know or care whether it&#8217;s dealing with a <code>Dog</code> or a <code>Cat</code>; it just trusts that <code>speak</code> will do the right thing.</p>



<h3 class="wp-block-heading">Calling the Parent&#8217;s Implementation with <code>super</code></h3>



<p class="wp-block-paragraph">Sometimes you don&#8217;t want to fully replace a parent method — you want to extend it. <code>super</code> calls the same-named method in the superclass.</p>



<pre class="wp-block-code"><code>class Animal
  def initialize(name)
    @name = name
  end
end

class Dog &lt; Animal
  def initialize(name, breed)
    super(name)
    @breed = breed
  end

  def info
    "#{@name} is a #{@breed}"
  end
end

puts Dog.new("Rex", "Labrador").info
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Rex is a Labrador
</code></pre>



<p class="wp-block-paragraph">Calling <code>super</code> without parentheses (just <code>super</code>) automatically forwards all the arguments the current method received. Calling <code>super()</code> with empty parentheses calls the parent method with no arguments at all. This distinction has bitten me more than once, so I always write it explicitly when I mean &#8220;no arguments.&#8221;</p>



<h2 class="wp-block-heading">Modules and Mixins: Ruby&#8217;s Answer to Multiple Inheritance</h2>



<p class="wp-block-paragraph">Ruby classes can only inherit from one superclass — but Ruby gives you a powerful alternative for sharing behavior across unrelated classes: <strong>modules</strong>, mixed in using <code>include</code> or <code>extend</code>.</p>



<pre class="wp-block-code"><code>module Swimmable
  def swim
    "#{name} is swimming"
  end
end

module Flyable
  def fly
    "#{name} is flying"
  end
end

class Duck
  include Swimmable
  include Flyable

  attr_reader :name

  def initialize(name)
    @name = name
  end
end

duck = Duck.new("Donald")
puts duck.swim
puts duck.fly
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Donald is swimming
Donald is flying
</code></pre>



<p class="wp-block-paragraph"><code>Duck</code> isn&#8217;t a subclass of <code>Swimmable</code> or <code>Flyable</code> — it simply mixes their behavior in. This is how Ruby avoids the complexity of true multiple inheritance while still letting you compose behavior from multiple sources. When you <code>include</code> a module, it gets inserted into the ancestor chain right above the class that included it:</p>



<pre class="wp-block-code"><code>puts Duck.ancestors.inspect
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>&#91;Duck, Flyable, Swimmable, Object, Kernel, BasicObject]
</code></pre>



<p class="wp-block-paragraph">Notice modules are included in reverse order of declaration — the most recently included module sits closest to the class in the lookup chain. This matters when two mixed-in modules define the same method name, since it determines which one wins.</p>



<h3 class="wp-block-heading"><code>extend</code> vs <code>include</code></h3>



<p class="wp-block-paragraph">While <code>include</code> adds module methods as instance methods, <code>extend</code> adds them as methods on the object (or class) itself.</p>



<pre class="wp-block-code"><code>module Describable
  def describe
    "I am #{self}"
  end
end

class Robot
  extend Describable
end

puts Robot.describe
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>I am Robot
</code></pre>



<p class="wp-block-paragraph">I use <code>include</code> constantly for shared instance behavior (comparable logic, enumerable behavior, formatting helpers) and <code>extend</code> less often, typically for adding class-level utility methods to a class.</p>



<h2 class="wp-block-heading">Abstract Base Classes and Duck Typing</h2>



<p class="wp-block-paragraph">Ruby doesn&#8217;t have formal <code>abstract class</code> or <code>interface</code> keywords like Java or C#. Instead, Ruby relies on a philosophy called <strong>duck typing</strong>: &#8220;If it walks like a duck and quacks like a duck, treat it like a duck.&#8221; What matters is whether an object responds to the methods you need, not what class it officially belongs to.</p>



<pre class="wp-block-code"><code>class PDFExporter
  def export
    "Exporting as PDF"
  end
end

class CSVExporter
  def export
    "Exporting as CSV"
  end
end

def run_export(exporter)
  puts exporter.export
end

run_export(PDFExporter.new)
run_export(CSVExporter.new)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Exporting as PDF
Exporting as CSV
</code></pre>



<p class="wp-block-paragraph"><code>run_export</code> doesn&#8217;t care what class it receives — only that the object responds to <code>.export</code>. You can enforce this loosely with <code>respond_to?</code>:</p>



<pre class="wp-block-code"><code>def run_export(exporter)
  raise ArgumentError, "must respond to #export" unless exporter.respond_to?(:export)
  puts exporter.export
end
</code></pre>



<p class="wp-block-paragraph">If you do want something closer to a formal abstract class, a common convention is to raise <code>NotImplementedError</code> in the base class:</p>



<pre class="wp-block-code"><code>class Exporter
  def export
    raise NotImplementedError, "#{self.class} must implement export"
  end
end

class JSONExporter &lt; Exporter
  def export
    "Exporting as JSON"
  end
end

puts JSONExporter.new.export
Exporter.new.export
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Exporting as JSON
</code></pre>



<p class="wp-block-paragraph">followed by a raised <code>NotImplementedError</code> on the last line, since <code>Exporter</code> itself never provides a real implementation.</p>



<h2 class="wp-block-heading">Internal Working: Message Passing and <code>send</code></h2>



<p class="wp-block-paragraph">Under the hood, calling <code>object.method_name(args)</code> is really Ruby sending a message called <code>method_name</code> with <code>args</code> to <code>object</code>. You can do this explicitly with <code>send</code>, which even bypasses private method restrictions — useful for testing or metaprogramming, dangerous if overused.</p>



<pre class="wp-block-code"><code>class Wallet
  def initialize(amount)
    @amount = amount
  end

  private

  def secret_amount
    @amount
  end
end

w = Wallet.new(200)
puts w.send(:secret_amount)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>200
</code></pre>



<p class="wp-block-paragraph">This message-passing model is also why <code>method_missing</code> works the way it does — when Ruby can&#8217;t find a matching method anywhere in the ancestor chain, it sends a <code>method_missing</code> message instead of immediately failing, giving you a hook to intercept undefined calls dynamically (this is how many Ruby DSLs and ORMs, including parts of Rails, implement dynamic attribute access).</p>



<pre class="wp-block-code"><code>class DynamicResponder
  def method_missing(name, *args)
    "You called #{name} with #{args.inspect}"
  end
end

puts DynamicResponder.new.anything_goes(1, 2, 3)
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>You called anything_goes with &#91;1, 2, 3]
</code></pre>



<h2 class="wp-block-heading">Performance Considerations</h2>



<p class="wp-block-paragraph">Method lookup in Ruby involves walking the ancestor chain, which sounds slow but is heavily optimized internally through method caching (Ruby&#8217;s MRI implementation caches lookups so repeated calls to the same method on the same class don&#8217;t re-walk the chain every time). Still, a few practical performance notes I&#8217;ve picked up:</p>



<ul class="wp-block-list">
<li>Deep inheritance hierarchies and heavy module chains add lookup overhead; keep hierarchies as shallow as reasonably possible.</li>



<li><code>method_missing</code> is convenient but slower than defined methods, since it&#8217;s only reached after the full ancestor chain lookup fails. Use <code>define_method</code> to generate real methods dynamically when performance matters.</li>



<li><code>send</code> and <code>public_send</code> have a small overhead compared to direct calls; avoid them in hot loops.</li>
</ul>



<pre class="wp-block-code"><code>class Config
  &#91;:host, :port, :timeout].each do |attr|
    define_method(attr) { instance_variable_get("@#{attr}") }
  end

  def initialize
    @host = "localhost"
    @port = 8080
    @timeout = 30
  end
end

c = Config.new
puts c.host
puts c.port
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>localhost
8080
</code></pre>



<p class="wp-block-paragraph">This <code>define_method</code> pattern generates real, cacheable methods instead of relying on <code>method_missing</code>, giving you dynamic behavior without the performance penalty.</p>



<h2 class="wp-block-heading">Real-World Application: A Notification System</h2>



<p class="wp-block-paragraph">Here&#8217;s a practical example pulling together inheritance, modules, and duck typing the way you&#8217;d actually structure this in a production Ruby application.</p>



<pre class="wp-block-code"><code>module Loggable
  def log(message)
    puts "&#91;LOG] #{Time.now.strftime('%H:%M:%S')} - #{message}"
  end
end

class Notifier
  include Loggable

  def send_notification(message)
    raise NotImplementedError
  end

  def notify(message)
    send_notification(message)
    log("Notification sent via #{self.class}")
  end
end

class EmailNotifier &lt; Notifier
  def send_notification(message)
    puts "Emailing: #{message}"
  end
end

class SMSNotifier &lt; Notifier
  def send_notification(message)
    puts "Texting: #{message}"
  end
end

notifiers = &#91;EmailNotifier.new, SMSNotifier.new]
notifiers.each { |n| n.notify("Server restarted successfully") }
</code></pre>



<p class="wp-block-paragraph">Output:</p>



<pre class="wp-block-code"><code>Emailing: Server restarted successfully
&#91;LOG] 14:02:31 - Notification sent via EmailNotifier
Texting: Server restarted successfully
&#91;LOG] 14:02:31 - Notification sent via SMSNotifier
</code></pre>



<p class="wp-block-paragraph">This is a template method pattern: the base class defines the overall workflow (<code>notify</code>), while subclasses fill in the specific step (<code>send_notification</code>). It&#8217;s a pattern I use constantly in real Ruby codebases, and it only works because of the inheritance and polymorphism fundamentals covered above.</p>



<h2 class="wp-block-heading">Best Practices and Common Mistakes</h2>



<ul class="wp-block-list">
<li><strong>Favor composition (modules) over deep inheritance</strong> when behavior doesn&#8217;t represent a true &#8220;is-a&#8221; relationship. A <code>Car</code> is a <code>Vehicle</code> (inheritance); a <code>Car</code> is <code>Trackable</code> (mixin).</li>



<li><strong>Don&#8217;t overuse <code>method_missing</code>.</strong> It&#8217;s powerful but makes code harder to trace and debug; prefer <code>define_method</code> for dynamic-but-known method sets.</li>



<li><strong>Be explicit with <code>super</code> vs <code>super()</code></strong> — forgetting the difference is a classic source of &#8220;why is this argument nil?&#8221; bugs.</li>



<li><strong>Avoid deep module chains that shadow each other&#8217;s methods</strong> unexpectedly; always check <code>SomeClass.ancestors</code> when you&#8217;re unsure which implementation wins.</li>



<li><strong>Don&#8217;t reach for <code>send</code> to bypass private methods</strong> as a routine practice — if you need to call something from outside the object often, it probably shouldn&#8217;t be private.</li>
</ul>



<h2 class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">Ruby earns its reputation as a purely object-oriented language because there is genuinely no escape hatch from the object model — numbers, strings, booleans, and even classes are all objects that respond to methods. Method calls are message sends resolved through an inspectable, predictable ancestor chain, which is what makes inheritance, <code>super</code>, and mixins behave consistently. Modules give you a clean way to share behavior across unrelated classes without the complexity of true multiple inheritance, and duck typing lets you write flexible code that cares about behavior rather than rigid type hierarchies. Once these pieces click together, you start writing Ruby that feels less like following syntax rules and more like designing a small society of cooperating objects.</p>



<h2 class="wp-block-heading">References</h2>



<ul class="wp-block-list">
<li><a href="https://www.ruby-lang.org/en/documentation/">Ruby Official Documentation</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Module.html">Ruby Core: Module</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/Method.html">Ruby Core: Method</a></li>



<li><a href="https://docs.ruby-lang.org/en/master/BasicObject.html">Ruby Core: BasicObject</a></li>



<li><a href="https://guides.rubygems.org/">RubyGems Guides</a></li>
</ul>
<p>The post <a href="https://awjunaid.com/ruby/ruby-is-an-object-oriented-language-understanding-objects-methods-and-inheritance-in-ruby/">Ruby Is an Object-Oriented Language: Understanding Objects, Methods, and Inheritance in Ruby</a> appeared first on <a href="https://awjunaid.com">Abdul Wahab Junaid</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://awjunaid.com/ruby/ruby-is-an-object-oriented-language-understanding-objects-methods-and-inheritance-in-ruby/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4217</post-id>	</item>
	</channel>
</rss>
