<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shrouk Abozeid</title>
    <description>The latest articles on DEV Community by Shrouk Abozeid (@shroukabozeid).</description>
    <link>https://dev.to/shroukabozeid</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4008684%2Fddf07757-4921-49f6-8aa8-bd77aeda61b0.jpg</url>
      <title>DEV Community: Shrouk Abozeid</title>
      <link>https://dev.to/shroukabozeid</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shroukabozeid"/>
    <language>en</language>
    <item>
      <title>Learning Go as a Ruby Developer # 1: How Go Programs Actually Run</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Tue, 14 Jul 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-part-1-understanding-how-go-programs-actually-run-3eh0</link>
      <guid>https://dev.to/shroukabozeid/learning-go-as-a-ruby-developer-part-1-understanding-how-go-programs-actually-run-3eh0</guid>
      <description>&lt;p&gt;Recently I started learning Go, and one of the first things I noticed was how much it reminded me of C++.&lt;br&gt;
I haven't touched C++ since college, so Go gives me a weird sense of nostalgia :D&lt;/p&gt;

&lt;p&gt;As a Ruby developer, I'm used to writing code and simply executing it.&lt;br&gt;
Go, however, has a much stronger notion of what a program actually is and how it starts running.&lt;/p&gt;

&lt;p&gt;In this article, I want to explore how a Go program is structured and compare it with how we typically think about programs in Ruby&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Felt Strange Coming from Ruby
&lt;/h2&gt;

&lt;p&gt;In Ruby, writing a program is straightforward:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;puts "Hello World"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save it as &lt;em&gt;hello.rb&lt;/em&gt; and run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ruby hello.rb&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There's no special package declaration, no imports required for basic programs, and no designated entry point function.&lt;/p&gt;

&lt;p&gt;Go takes a very different approach.&lt;/p&gt;

&lt;p&gt;Every executable Go program follows a specific structure, and understanding this structure is one of the first steps to becoming comfortable with the language.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Go Programs Are Structured
&lt;/h2&gt;

&lt;p&gt;A typical Go file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="s"&gt;"fmt"&lt;/span&gt; 
&lt;span class="p"&gt;)&lt;/span&gt; 

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three important pieces here:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Package Declaration
&lt;/h3&gt;

&lt;p&gt;Every Go file begins with a package declaration:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;package main&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Packages are Go's mechanism for organizing code.&lt;/p&gt;

&lt;p&gt;If you want to build an executable application, the package must be named main.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Imports
&lt;/h3&gt;

&lt;p&gt;Go requires explicit imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The compiler will actually complain if you import something you don't use.&lt;/p&gt;

&lt;p&gt;As a Ruby developer, this felt unusual because Ruby happily allows unused &lt;br&gt;
requires:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'csv'&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go prefers keeping dependencies explicit and clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The main Function
&lt;/h3&gt;

&lt;p&gt;Every executable Go program starts execution in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;main&lt;/code&gt;function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;accepts no arguments&lt;/li&gt;
&lt;li&gt;returns no values&lt;/li&gt;
&lt;li&gt;acts as the application's entry point&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When &lt;code&gt;main()&lt;/code&gt; finishes, the program exits.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Program Execution Works
&lt;/h2&gt;

&lt;p&gt;According to the Go specification, a complete program consists of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one package named main&lt;/li&gt;
&lt;li&gt;all packages imported by main&lt;/li&gt;
&lt;li&gt;all transitive dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Program execution happens in two stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Initialize packages&lt;/li&gt;
&lt;li&gt;Execute main()&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once &lt;code&gt;main()&lt;/code&gt;returns, the program terminates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running vs Building Programs
&lt;/h2&gt;

&lt;p&gt;Go provides two common ways to execute code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run directly
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;go run hello.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This compiles and runs the program immediately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build an executable
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;go build hello.go
./hello
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a standalone binary.&lt;/p&gt;

&lt;p&gt;In Ruby: applications are distributed as source code and interpreted at runtime.&lt;/p&gt;

&lt;p&gt;Coming from Rails, where so much setup happens automatically, Go feels so explicit.&lt;/p&gt;

&lt;p&gt;At the same time, that explicitness means you have to think about things that Ruby usually hides from you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;while Ruby optimizes for developer happiness and speed of iteration, Go forces me to understand what's actually happening.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What about you? do you use Ruby or Go, or both ? and how was the transition for you ?&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #3: Decorator Pattern</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Mon, 13 Jul 2026 15:11:23 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-3-decorator-pattern-12an</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-3-decorator-pattern-12an</guid>
      <description>&lt;p&gt;&lt;strong&gt;Inheritance&lt;/strong&gt; is powerful but doesn’t always lead to flexible designs and Decorator Pattern is one of the solutions to balance between inheritance and flexibility &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decorators&lt;/strong&gt; work like object wrappers that add functionality/behavior to the object during run time instead of compile time.&lt;/p&gt;

&lt;p&gt;we said wrapper*&lt;em&gt;S&lt;/em&gt;* with an S because you can wrap as many as your object need, adding layers to your Main object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure of the Decorator Pattern
&lt;/h2&gt;

&lt;p&gt;The Decorator Pattern consists of four main parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Component&lt;/strong&gt; – the main abstraction that can be used directly or wrapped by decorators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Component&lt;/strong&gt; – the actual object whose behavior we want to extend dynamically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decorator&lt;/strong&gt; – implements the same interface as the component and &lt;strong&gt;has a&lt;/strong&gt; component object that it wraps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Decorators&lt;/strong&gt; – extend the decorator and add new behavior before or after delegating to the wrapped object.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At first, this may sound a bit abstract, so let's look at a practical example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Rack Middleware
&lt;/h2&gt;

&lt;p&gt;If you've worked with Ruby on Rails, you've already used one of the best real-world examples of the Decorator Pattern: &lt;strong&gt;Rack middleware&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each middleware wraps another application object, adds its own behavior, and then delegates the request to the wrapped object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Component&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Concrete Component&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;App&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing request: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Decorator&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Middleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;App&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Concrete Decorators&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggingMiddleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Middleware&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[LOG] Received request for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:path&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[LOG] Response status: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthenticationMiddleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Middleware&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[AUTH] Authenticating user"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:authenticated&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Unauthorized"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TimingMiddleware&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Middleware&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"[TIMING] Request took &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;elapsed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms"&lt;/span&gt;

    &lt;span class="n"&gt;response&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Usage&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;LoggingMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;AuthenticationMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TimingMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;env&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="s2"&gt;"/articles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;authenticated: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[AUTH] Authenticating user
[LOG] Received request for /articles
Processing request: /articles
[LOG] Response status: 200
[TIMING] Request took 0.12ms

[200, {}, ["OK"]]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Application&lt;/code&gt; is our &lt;strong&gt;Concrete Component&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Middleware&lt;/code&gt; is the &lt;strong&gt;Decorator&lt;/strong&gt; that wraps another component.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LoggingMiddleware&lt;/code&gt;, &lt;code&gt;AuthenticationMiddleware&lt;/code&gt;, and &lt;code&gt;TimingMiddleware&lt;/code&gt; are &lt;strong&gt;Concrete Decorators&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Each middleware adds behavior before, after, or around the original &lt;code&gt;call&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;We can add, remove, or reorder middleware without modifying the original &lt;code&gt;Application&lt;/code&gt; class.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's particularly interesting is that this is almost exactly how Rack itself builds a web application stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MethodOverride&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each middleware wraps the previous object, creating a chain of decorators that process requests and responses.&lt;/p&gt;

&lt;p&gt;In real Rack applications there isn't a common &lt;code&gt;App&lt;/code&gt; base class because Ruby relies on duck typing. As long as an object responds to &lt;code&gt;call&lt;/code&gt;, it can participate in the middleware stack. &lt;/p&gt;

&lt;p&gt;The example above introduces an explicit &lt;code&gt;App&lt;/code&gt; class only to make the Decorator Pattern structure easier to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Decorators use inheritance mainly for &lt;strong&gt;type compatibility&lt;/strong&gt;, not for behavior reuse.&lt;/li&gt;
&lt;li&gt;New behavior is acquired through &lt;strong&gt;composition&lt;/strong&gt; rather than deep inheritance hierarchies.&lt;/li&gt;
&lt;li&gt;The Decorator Pattern involves a family of decorator classes that wrap concrete components.&lt;/li&gt;
&lt;li&gt;A component can be wrapped by any number of decorators.&lt;/li&gt;
&lt;li&gt;Decorators share the same interface as the objects they decorate.&lt;/li&gt;
&lt;li&gt;The pattern follows the principle of &lt;strong&gt;favoring composition over inheritance&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why favoring composition ?
&lt;/h2&gt;

&lt;p&gt;inheritance becomes difficult to manage when you're trying to mix and match behaviors.&lt;/p&gt;

&lt;p&gt;The number of subclasses grows quickly because every new feature creates more combinations.&lt;/p&gt;

&lt;p&gt;With the Decorator Pattern, each behavior becomes its own object that can be composed dynamically.&lt;/p&gt;

&lt;p&gt;The next time you find yourself creating subclasses for every possible combination of features, it may be worth asking whether a decorator would provide a more flexible solution.&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #2: Observer Pattern</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Wed, 08 Jul 2026 16:17:55 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-2-observer-pattern-3g2</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-2-observer-pattern-3g2</guid>
      <description>&lt;p&gt;Applications often need to react when something changes.&lt;/p&gt;

&lt;p&gt;When a user signs up, you might want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send a welcome email&lt;/li&gt;
&lt;li&gt;Create a user profile&lt;/li&gt;
&lt;li&gt;Log the activity&lt;/li&gt;
&lt;li&gt;Notify an analytics service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One approach is to put all of this logic inside the signup code. While it works initially, the code quickly becomes difficult to maintain as more responsibilities are added.&lt;/p&gt;

&lt;p&gt;This is exactly the kind of problem the &lt;strong&gt;Observer Pattern&lt;/strong&gt; solves.&lt;/p&gt;

&lt;p&gt;The Observer Pattern is one of the most commonly used &lt;strong&gt;behavioral design patterns&lt;/strong&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It defines a &lt;strong&gt;one-to-many relationship&lt;/strong&gt; between objects so that when one object (the &lt;strong&gt;Subject&lt;/strong&gt;) changes state, all of its dependent objects (the &lt;strong&gt;Observers&lt;/strong&gt;) are notified automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of tightly coupling objects together, the subject simply announces that "something happened," and any interested observers can react.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The pattern consists of two main participants.&lt;/p&gt;

&lt;h4&gt;
  
  
  Subject (Publisher)
&lt;/h4&gt;

&lt;p&gt;The subject owns the state and keeps track of all registered observers.&lt;/p&gt;

&lt;p&gt;Whenever its state changes, it notifies every observer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Observer (Subscriber)
&lt;/h4&gt;

&lt;p&gt;Observers register themselves with the subject.&lt;/p&gt;

&lt;p&gt;When they receive a notification, they perform whatever action they're responsible for.&lt;/p&gt;

&lt;p&gt;A classic real-world example is a UI button.&lt;/p&gt;

&lt;p&gt;The button is the &lt;strong&gt;Subject&lt;/strong&gt;, while event listeners are the &lt;strong&gt;Observers&lt;/strong&gt;. When the button is clicked, every registered listener is notified.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Use the Observer Pattern?
&lt;/h2&gt;

&lt;p&gt;Without the Observer Pattern, your code often grows into something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;signup&lt;/span&gt;
    &lt;span class="n"&gt;save&lt;/span&gt;

    &lt;span class="no"&gt;WelcomeMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;track_signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;ActivityLogger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_signup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;UserProfile&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every new action requires modifying the &lt;code&gt;signup&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;This makes the class responsible for many unrelated tasks and violates the &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With the Observer Pattern, the signup process only needs to announce that a user has signed up. Each observer decides how to respond.&lt;/p&gt;




&lt;h2&gt;
  
  
  Loose Coupling
&lt;/h2&gt;

&lt;p&gt;One of the biggest benefits of the Observer Pattern is &lt;strong&gt;loose coupling&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The subject only knows that its observers respond to a common interface (for example, an &lt;code&gt;update&lt;/code&gt; method).&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New observers can be added without changing the subject.&lt;/li&gt;
&lt;li&gt;Observers can be removed at runtime.&lt;/li&gt;
&lt;li&gt;The subject doesn't know or care what each observer does.&lt;/li&gt;
&lt;li&gt;Subjects and observers can evolve independently.&lt;/li&gt;
&lt;li&gt;Each observer has a single, focused responsibility.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Ruby Example
&lt;/h2&gt;

&lt;p&gt;Let's build a simple weather station.&lt;/p&gt;

&lt;p&gt;Whenever the temperature changes, every registered display should update automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherStation&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;observer&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;remove_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
    &lt;span class="n"&gt;notify_observers&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;notify_observers&lt;/span&gt;
    &lt;span class="vi"&gt;@observers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PhoneDisplay&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Phone Display: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardDisplay&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Dashboard Display: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;°C"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;station&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;WeatherStation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;

&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PhoneDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_observer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;DashboardDisplay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;station&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Phone Display: 25°C
Dashboard Display: 25°C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the temperature changes, the weather station automatically notifies every registered display.&lt;/p&gt;

&lt;p&gt;Notice that &lt;code&gt;WeatherStation&lt;/code&gt; doesn't know anything about phones or dashboards. It only knows that each observer responds to &lt;code&gt;update&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Observer Pattern in Rails
&lt;/h2&gt;

&lt;p&gt;Even if you've never implemented the Observer Pattern yourself, you've probably used it in Rails.&lt;/p&gt;

&lt;p&gt;Some common examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Active Record callbacks (&lt;code&gt;after_create&lt;/code&gt;, &lt;code&gt;after_commit&lt;/code&gt;, &lt;code&gt;before_save&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ActiveSupport::Notifications&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Action Cable broadcasting events to connected clients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;after_create&lt;/span&gt; &lt;span class="ss"&gt;:send_welcome_email&lt;/span&gt;

  &lt;span class="kp"&gt;private&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;send_welcome_email&lt;/span&gt;
    &lt;span class="no"&gt;WelcomeMailer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;deliver_later&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a &lt;code&gt;User&lt;/code&gt; is created, Rails automatically invokes the callback.&lt;/p&gt;

&lt;p&gt;Although callbacks aren't a textbook implementation of the Observer Pattern, they follow the same fundamental idea: responding automatically when an object's state changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  When Should You Use the Observer Pattern?
&lt;/h2&gt;

&lt;p&gt;The Observer Pattern is a good choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple objects need to react to the same event.&lt;/li&gt;
&lt;li&gt;You want to avoid tightly coupling classes together.&lt;/li&gt;
&lt;li&gt;New behaviors should be be added without modifying existing code.&lt;/li&gt;
&lt;li&gt;Different parts of the application should respond independently to state changes.&lt;/li&gt;
&lt;li&gt;You want to follow the &lt;strong&gt;Open/Closed Principle&lt;/strong&gt; and the &lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The Observer Pattern is all about communication without tight coupling.&lt;/p&gt;

&lt;p&gt;Instead of asking every object to perform additional work, the subject simply announces that something has changed.&lt;/p&gt;

&lt;p&gt;Any interested observer can react in its own way.&lt;/p&gt;

&lt;p&gt;In Ruby, where objects communicate through simple interfaces and duck typing, the Observer Pattern is straightforward to implement and can significantly improve the flexibility and maintainability of your applications.&lt;/p&gt;

&lt;p&gt;As your applications grow, you'll find this pattern everywhere—from GUI frameworks to Rails callbacks to event-driven architectures.&lt;/p&gt;

&lt;p&gt;for a full example in ruby check this &lt;a href="https://github.com/ShroukAbozeid/design-pattern/tree/main/observer" rel="noopener noreferrer"&gt;https://github.com/ShroukAbozeid/design-pattern/tree/main/observer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>programming</category>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>Design Patterns in Ruby #1: Strategy Pattern</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Mon, 06 Jul 2026 14:21:52 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/design-patterns-in-ruby-1-strategy-pattern-5h78</link>
      <guid>https://dev.to/shroukabozeid/design-patterns-in-ruby-1-strategy-pattern-5h78</guid>
      <description>&lt;p&gt;When building applications, one of the most common challenges is managing behaviors that can vary over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Behavioral Design Patterns&lt;/strong&gt; helps us design how objects interact with each other in an effective way&lt;br&gt;
One of the most useful behavioral patterns is the &lt;strong&gt;Strategy Pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Strategy pattern defines a family of algorithms encapsulate each one and make them interchangeable&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;it provides a way to change the behavior of a class without extending it&lt;/p&gt;

&lt;p&gt;Instead of hardcoding behavior inside a class, the behavior is delegated to a separate object called a &lt;strong&gt;strategy&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Imagine you're building an e-commerce application.&lt;/p&gt;

&lt;p&gt;Customers can pay using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PayPal&lt;/li&gt;
&lt;li&gt;Credit Card&lt;/li&gt;
&lt;li&gt;Bank Transfer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An initial implementation might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Checkout&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:paypal&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing PayPal payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:credit_card&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Credit Card payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:bank_transfer&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Bank Transfer payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Usage&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:paypal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Problems
&lt;/h3&gt;

&lt;p&gt;Every time you add a new payment method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You modify &lt;code&gt;Checkout&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The class becomes larger&lt;/li&gt;
&lt;li&gt;Testing becomes harder&lt;/li&gt;
&lt;li&gt;You violate the Open/Closed Principle (open for extension, closed for modification)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Applying the Strategy Pattern
&lt;/h2&gt;

&lt;p&gt;Instead of putting all payment logic inside &lt;code&gt;Checkout&lt;/code&gt;, we'll create separate strategy classes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Strategies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="c1"&gt;# or make as module and use include instead of &amp;lt;&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NotImplementedError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PayPalStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing PayPal payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VisaStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Visa payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BankTransferStrategy&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;PaymentStrategy&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Processing Bank Transfer payment of $&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Create the Context
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Context&lt;/strong&gt; is the class that uses a strategy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Checkout&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment_strategy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@payment_strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment_strategy&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@payment_strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Use Different Strategies
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PayPalStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;VisaStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Runtime Strategy Switching
&lt;/h2&gt;

&lt;p&gt;You can even change strategies while the application is running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;checkout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;PayPalStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;payment_strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;BankTransferStrategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When Should You Use the Strategy Pattern?
&lt;/h2&gt;

&lt;p&gt;The Strategy Pattern is a good choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have multiple implementations of the same behavior.&lt;/li&gt;
&lt;li&gt;You find yourself writing large case or if/else statements.&lt;/li&gt;
&lt;li&gt;You want to follow the Open/Closed Principle.&lt;/li&gt;
&lt;li&gt;You need to switch behavior dynamically at runtime.&lt;/li&gt;
&lt;li&gt;You want to isolate and test algorithms independently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Ruby, where objects are lightweight and composition is encouraged, the Strategy Pattern often feels natural and can significantly improve the design of your applications.&lt;/p&gt;

&lt;p&gt;for a full example in ruby check this &lt;a href="https://github.com/ShroukAbozeid/design-pattern/tree/main/strategy" rel="noopener noreferrer"&gt;https://github.com/ShroukAbozeid/design-pattern/tree/main/strategy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>designpatterns</category>
      <category>ruby</category>
      <category>rails</category>
      <category>oop</category>
    </item>
    <item>
      <title>Understanding Rack #2 : Notes from Rebuilding Rails by Noah Gibbs</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Thu, 02 Jul 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/understanding-rack-2-notes-from-rebuilding-rails-by-noah-gibbs-1p2b</link>
      <guid>https://dev.to/shroukabozeid/understanding-rack-2-notes-from-rebuilding-rails-by-noah-gibbs-1p2b</guid>
      <description>&lt;p&gt;A Rack application is typically configured through a &lt;code&gt;config.ru&lt;/code&gt; (RackUp) file. This file defines the stack of middleware that will handle incoming requests before they reach the application itself.&lt;/p&gt;

&lt;p&gt;One of Rack's core ideas is that applications are built from multiple layers. Each layer, called middleware, can inspect, modify, or respond to a request before passing it to the next layer in the stack.&lt;/p&gt;

&lt;p&gt;When Rack builds the middleware stack, it passes each middleware instance the next layer through its &lt;code&gt;initialize&lt;/code&gt; method. The last layer in the chain is the actual application.&lt;/p&gt;

&lt;p&gt;Here's a simple example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config.ru&lt;/span&gt;
&lt;span class="n"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Rack&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Auth&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Basic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pass&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;pass&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"secret"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="nb"&gt;proc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"text/html"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;use&lt;/code&gt; keyword tells Rack which middleware class to instantiate and what arguments to pass to its constructor. &lt;br&gt;
The &lt;code&gt;run&lt;/code&gt; keyword specifies the final application that will handle the request.&lt;/p&gt;

&lt;p&gt;Rack includes several built-in middleware components, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Rack::Auth::Basic&lt;/code&gt; — HTTP Basic Authentication&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Rack::ContentType&lt;/code&gt; — Automatically sets the response content type&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Rack::ShowExceptions&lt;/code&gt; — Displays a helpful error page when an exception occurs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also many third-party middleware libraries available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Rack::GoogleAnalytics&lt;/code&gt; — Injects Google Analytics tracking code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Rack::Throttle&lt;/code&gt; — Adds request rate limiting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Warden&lt;/code&gt; — A flexible authentication framework used by libraries such as Devise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of Rack's strengths is that you can easily create your own custom middleware and insert it into the stack, allowing you to add application-specific behavior in a clean and reusable way.&lt;/p&gt;

&lt;p&gt;Since Rails is built on top of Rack, every Rails application includes a &lt;code&gt;config.ru&lt;/code&gt; file and uses Rack middleware internally.&lt;/p&gt;

&lt;p&gt;For a deeper look at how Rails integrates with Rack, see the "&lt;a href="https://guides.rubyonrails.org/rails_on_rack.html" rel="noopener noreferrer"&gt;Rails on Rack&lt;/a&gt;" guide in the Rails documentation.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>backend</category>
      <category>rack</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Understanding Rack #1 : Notes from Rebuilding Rails by Noah Gibbs</title>
      <dc:creator>Shrouk Abozeid</dc:creator>
      <pubDate>Tue, 30 Jun 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/shroukabozeid/understanding-rack-1-notes-from-rebuilding-rails-by-noah-gibbs-ma8</link>
      <guid>https://dev.to/shroukabozeid/understanding-rack-1-notes-from-rebuilding-rails-by-noah-gibbs-ma8</guid>
      <description>&lt;h3&gt;
  
  
  What is Rack?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rack&lt;/strong&gt; is a Ruby gem that acts as a &lt;strong&gt;middleman&lt;/strong&gt; between your Ruby framework (like Rails or Sinatra) and the web server/application server that runs your code.&lt;/p&gt;

&lt;p&gt;Think of it like a translator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser &amp;lt;--&amp;gt; Web Server/App Server &amp;lt;--&amp;gt; Rack &amp;lt;--&amp;gt; Rails App
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a browser sends a request:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The server receives it.&lt;/li&gt;
&lt;li&gt;Rack converts the request into a format Rails understands.&lt;/li&gt;
&lt;li&gt;Rails processes the request and generates a response.&lt;/li&gt;
&lt;li&gt;Rack converts the response back into a format the server can send to the browser.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  What is an application server?
&lt;/h3&gt;

&lt;p&gt;An application server is a program that actually &lt;strong&gt;runs your Ruby application&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Puma&lt;/li&gt;
&lt;li&gt;Thin&lt;/li&gt;
&lt;li&gt;Passenger&lt;/li&gt;
&lt;li&gt;WEBrick&lt;/li&gt;
&lt;li&gt;Unicorn&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These servers execute your Rails code and return the result to users.&lt;/p&gt;




&lt;h3&gt;
  
  
  Development vs Production
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Development (your local machine)
&lt;/h3&gt;

&lt;p&gt;Usually you run only one application server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rails starts Puma by default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser &amp;lt;--&amp;gt; Puma &amp;lt;--&amp;gt; Rails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is simple and works well for development.&lt;/p&gt;




&lt;h3&gt;
  
  
  Production (real website)
&lt;/h3&gt;

&lt;p&gt;In production, there is often a dedicated web server in front of the application server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser &amp;lt;--&amp;gt; Nginx/Apache &amp;lt;--&amp;gt; Puma &amp;lt;--&amp;gt; Rails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nginx/Apache can serve static files efficiently.&lt;/li&gt;
&lt;li&gt;They can handle SSL/HTTPS.&lt;/li&gt;
&lt;li&gt;They can distribute traffic to multiple Puma processes.&lt;/li&gt;
&lt;li&gt;They provide better performance and security.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Real-world analogy
&lt;/h3&gt;

&lt;p&gt;Imagine a restaurant:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser&lt;/strong&gt; = customer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx/Apache&lt;/strong&gt; = receptionist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rack&lt;/strong&gt; = waiter translating orders&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rails app&lt;/strong&gt; = chef&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Puma&lt;/strong&gt; = kitchen where the chef works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The customer doesn't talk directly to the chef. The request passes through several layers, and Rack helps them communicate using a common language.&lt;/p&gt;

&lt;h3&gt;
  
  
  So in one sentence we can say
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Rack is the standard interface that allows Ruby web servers (Puma, Unicorn, etc.) and Ruby web frameworks (Rails, Sinatra, etc.) to communicate with each other.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>backend</category>
      <category>ruby</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
