<?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: Wilbur Suero</title>
    <description>The latest articles on DEV Community by Wilbur Suero (@travelingwilbur).</description>
    <link>https://dev.to/travelingwilbur</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F38352%2Fb3f7db58-dbe2-42d2-a48e-fbaa9768b36e.jpg</url>
      <title>DEV Community: Wilbur Suero</title>
      <link>https://dev.to/travelingwilbur</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/travelingwilbur"/>
    <language>en</language>
    <item>
      <title>Writing Maintainable AI Prompts in Rails with Promptly</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Mon, 18 Aug 2025 22:03:48 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/writing-maintainable-ai-prompts-in-rails-with-promptly-1dnf</link>
      <guid>https://dev.to/travelingwilbur/writing-maintainable-ai-prompts-in-rails-with-promptly-1dnf</guid>
      <description>&lt;p&gt;A few months ago, I was helping a Rails team add AI-generated onboarding emails to their app. It seemed simple at first: drop an &lt;code&gt;OpenAI.chat(...)&lt;/code&gt; call inside a mailer, pass in the user’s name, and let the model draft a warm welcome.&lt;/p&gt;

&lt;p&gt;By the second week, things got messy.&lt;/p&gt;

&lt;p&gt;Different controllers and jobs had their own inline prompts.&lt;/p&gt;

&lt;p&gt;Some prompts were copy-pasted with slight tweaks (“friendly tone”, “professional tone”, etc.).&lt;/p&gt;

&lt;p&gt;Marketing wanted localized versions for Spanish and Portuguese.&lt;/p&gt;

&lt;p&gt;QA asked, “How do we know the prompts didn’t change by accident?”&lt;/p&gt;

&lt;p&gt;We ended up with prompt spaghetti—hard to test, impossible to translate cleanly, and brittle whenever we tried to refactor.&lt;/p&gt;

&lt;p&gt;That experience sparked the idea for &lt;a href="https://github.com/wilburhimself/promptly" rel="noopener noreferrer"&gt;Promptly&lt;/a&gt;: a small gem that brings Rails conventions to AI prompt management.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Problem: Prompts Don’t Belong Scattered in Code
&lt;/h3&gt;

&lt;p&gt;Rails developers already know the pain of hard-coded strings—why we use views, partials, and I18n instead of littering messages across controllers. Yet many of us are now hardcoding AI prompts directly in service objects or background jobs.&lt;/p&gt;

&lt;p&gt;It doesn’t scale.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplication: The same wording lives in multiple places.&lt;/li&gt;
&lt;li&gt;Localization headaches: Inline strings don’t play well with I18n.&lt;/li&gt;
&lt;li&gt;No safety net: Refactors can silently change how the AI behaves.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  The Solution: Promptly
&lt;/h3&gt;

&lt;p&gt;Promptly lets you define AI prompts as ERB or Liquid templates, stored in a Rails-native directory structure. Just like you’d render a view, you render a prompt:&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;# app/prompts/welcome_email.erb&lt;/span&gt;
&lt;span class="no"&gt;Hello&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= @user.name %&amp;gt;, welcome to our service!
We’re excited to have you join.

# In your mailer or service:
render_prompt("welcome_email", user: @user)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This unlocks the same benefits Rails developers already rely on elsewhere:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt; → All prompts live in one place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Localization&lt;/strong&gt; → Templates can use I18n just like views.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testability&lt;/strong&gt; → You can write RSpec tests that assert on rendered prompt output.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Why Rails Conventions Matter
&lt;/h3&gt;

&lt;p&gt;Rails has always thrived on convention over configuration. Promptly doesn’t reinvent the wheel; it extends familiar concepts (views, templates, helpers) into the AI space.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of partials, you have prompt templates.&lt;/li&gt;
&lt;li&gt;Instead of locals, you have prompt variables.&lt;/li&gt;
&lt;li&gt;Instead of ad-hoc strings, you have structured, versionable files.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Add it to your Gemfile:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'promptly'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2.Create your first template in app/prompts.&lt;br&gt;
3.Render it anywhere with render_prompt.&lt;br&gt;
4.Add tests to verify the output.&lt;/p&gt;

&lt;p&gt;Full docs are in the &lt;a href="https://github.com/wilburhimself/promptly" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Looking Ahead
&lt;/h3&gt;

&lt;p&gt;Promptly is intentionally small. It’s not trying to be a full-blown AI orchestration platform. But by solving one narrow pain point—making prompts maintainable, testable, and Rails-friendly—it can help Rails apps adopt AI without chaos.&lt;/p&gt;

&lt;p&gt;The next steps may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompt versioning.&lt;/li&gt;
&lt;li&gt;Preview workflows in Rails consoles.&lt;/li&gt;
&lt;li&gt;Deeper integration with related gems like semantic search adapters.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you’re a Rails developer experimenting with AI, try &lt;a href="https://github.com/wilburhimself/promptly" rel="noopener noreferrer"&gt;Promptly&lt;/a&gt;. It may save you from prompt spaghetti before it starts.&lt;/p&gt;

&lt;p&gt;Feedback and contributions are welcome, the best ideas usually come from real-world use.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>promptengineering</category>
    </item>
    <item>
      <title>🚨 Introducing GemGuard: Automated Security for Ruby Gems (Scan, SBOM, Typosquat, Auto-Fix)</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Mon, 11 Aug 2025 02:05:38 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/introducing-gemguard-automated-security-for-ruby-gems-scan-sbom-typosquat-auto-fix-2p2g</link>
      <guid>https://dev.to/travelingwilbur/introducing-gemguard-automated-security-for-ruby-gems-scan-sbom-typosquat-auto-fix-2p2g</guid>
      <description>&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/wilburhimself/gem_guard" rel="noopener noreferrer"&gt;github.com/wilburhimself/gem_guard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;RubyGems: &lt;a href="https://rubygems.org/gems/gem_guard" rel="noopener noreferrer"&gt;rubygems.org/gems/gem_guard&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;✅ Scan dependencies for known vulnerabilities (OSV.dev + Ruby Advisory DB)
&lt;/li&gt;
&lt;li&gt;🕵️ Detect typosquat packages before they bite
&lt;/li&gt;
&lt;li&gt;📜 Generate SPDX / CycloneDX SBOMs
&lt;/li&gt;
&lt;li&gt;🛠 Auto-fix vulnerable gems safely
&lt;/li&gt;
&lt;li&gt;⚡ Clean CLI + CI-ready
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version:&lt;/strong&gt; 1.1.x&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why GemGuard?
&lt;/h2&gt;

&lt;p&gt;Because security shouldn’t be an afterthought. It should be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pragmatic&lt;/strong&gt; – only what matters, no noise&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast&lt;/strong&gt; – instant feedback in dev or CI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrated&lt;/strong&gt; – works with your normal Ruby workflow&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is GemGuard?
&lt;/h2&gt;

&lt;p&gt;GemGuard is a lightweight Ruby security tool that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scans your &lt;code&gt;Gemfile.lock&lt;/code&gt; for known vulnerabilities&lt;/li&gt;
&lt;li&gt;Detects typosquat risks via fuzzy matching&lt;/li&gt;
&lt;li&gt;Generates SBOMs (SPDX and CycloneDX)&lt;/li&gt;
&lt;li&gt;Auto-fixes vulnerable gems with safe version upgrades&lt;/li&gt;
&lt;li&gt;Plays nicely with CI/CD&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  Installation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add to your Gemfile (recommended for projects)&lt;/span&gt;
gem &lt;span class="s2"&gt;"gem_guard"&lt;/span&gt;, &lt;span class="s2"&gt;"~&amp;gt; 1.1"&lt;/span&gt;

&lt;span class="c"&gt;# Or install globally&lt;/span&gt;
gem &lt;span class="nb"&gt;install &lt;/span&gt;gem_guard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Verify:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard version
&lt;span class="c"&gt;# =&amp;gt; 1.1.x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Quick Start
&lt;/h4&gt;

&lt;p&gt;Scan your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard scan
&lt;span class="c"&gt;# ✅ No vulnerabilities found!&lt;/span&gt;
&lt;span class="c"&gt;# or exits non‑zero if issues are found&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Detect typosquats:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard typosquat
&lt;span class="c"&gt;# No potential typosquat dependencies found.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Generate an SBOM:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard sbom &lt;span class="nt"&gt;--format&lt;/span&gt; spdx &lt;span class="nt"&gt;--output&lt;/span&gt; sbom.spdx.json
gem_guard sbom &lt;span class="nt"&gt;--format&lt;/span&gt; cyclonedx &lt;span class="nt"&gt;--output&lt;/span&gt; bom.cdx.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Auto‑Fix Vulnerabilities
&lt;/h4&gt;

&lt;p&gt;Preview (dry run):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard fix &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply fixes (creates a Gemfile.lock backup by default):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard fix
&lt;span class="c"&gt;# 📦 Created backup: Gemfile.lock.backup.2025...&lt;/span&gt;
&lt;span class="c"&gt;# ✅ Updated nokogiri to 1.18.9&lt;/span&gt;
&lt;span class="c"&gt;# 🔄 Running bundle install to update lockfile...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--interactive&lt;/code&gt;: confirm each update&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--no-backup&lt;/code&gt;: skip lockfile backup&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--gemfile&lt;/code&gt;, --lockfile: custom paths&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tip: Re-scan after fixing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Clean CLI
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;span class="c"&gt;# config, scan, typosquat, sbom, fix, version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Exit codes:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;0: success / no vulns&lt;/li&gt;
&lt;li&gt;1: vulnerabilities found&lt;/li&gt;
&lt;li&gt;2: errors (e.g., missing files)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CI/CD Integration (GitHub Actions)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security-scan&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;gemguard&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ruby/setup-ruby@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ruby-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.3'&lt;/span&gt;
          &lt;span class="na"&gt;bundler-cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gem install gem_guard&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gem_guard scan --format json &amp;gt; gemguard-report.json&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gem_guard typosquat --format json &amp;gt; typosquat-report.json&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload reports&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/upload-artifact@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gemguard-reports&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;gemguard-report.json&lt;/span&gt;
            &lt;span class="s"&gt;typosquat-report.json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fail builds on vulnerabilities (default behavior). If you want non-blocking scans (e.g., on main), wrap with || true or use matrix strategies.&lt;/p&gt;

&lt;h4&gt;
  
  
  Configuration
&lt;/h4&gt;

&lt;p&gt;Create .gemguard.yml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;lockfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gemfile.lock&lt;/span&gt;
&lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;table&lt;/span&gt;   &lt;span class="c1"&gt;# table | json&lt;/span&gt;
&lt;span class="na"&gt;typosquat&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;similarity_threshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.82&lt;/span&gt;
  &lt;span class="na"&gt;risk_levels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;high&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.9&lt;/span&gt;
    &lt;span class="na"&gt;medium&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.85&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;View current config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem_guard config &lt;span class="nt"&gt;--show&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why GemGuard?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Minimal setup, zero noise&lt;/li&gt;
&lt;li&gt;Pragmatic defaults, sensible exit codes&lt;/li&gt;
&lt;li&gt;Works offline for typosquat via fallback popular gems&lt;/li&gt;
&lt;li&gt;Well-tested (RSpec), standardrb formatting&lt;/li&gt;
&lt;li&gt;Designed for CI from day 1&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How It Compares
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Bundler Audit: great for advisories; GemGuard adds typosquat + SBOM + auto-fix&lt;/li&gt;
&lt;li&gt;OSV-Scanner: broad ecosystem; GemGuard is Ruby-first with tighter UX and auto-fix&lt;/li&gt;
&lt;li&gt;Trivy/Grype: container focus; GemGuard slots into pure-Ruby pipelines easily&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use GemGuard standalone or alongside your existing stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Roadmap
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Enriched advisories (GHSA/CVE links, CVSS)&lt;/li&gt;
&lt;li&gt;Optional dependency graph visualizations&lt;/li&gt;
&lt;li&gt;Interactive TUI&lt;/li&gt;
&lt;li&gt;More fix strategies and guards&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Contribute / Feedback
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Issues/PRs welcome: add tests, keep it minimal and intention-revealing&lt;/li&gt;
&lt;li&gt;Prefer failing test → minimal fix → refactor&lt;/li&gt;
&lt;li&gt;Security disclosures: see SECURITY.md&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try It Now
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gem &lt;span class="nb"&gt;install &lt;/span&gt;gem_guard
gem_guard scan
gem_guard typosquat
gem_guard fix &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this helps you ship safer Ruby apps with less fuss, drop a ❤️ and share!&lt;/p&gt;

&lt;p&gt;— Built for Rubyists who like fast feedback, clean CLIs, and reliable automation.&lt;/p&gt;

&lt;p&gt;Issues and PRs welcome → &lt;a href="https://github.com/wilburhimself/gem_guard" rel="noopener noreferrer"&gt;github.com/wilburhimself/gem_guard&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>security</category>
      <category>devops</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How I Built a RAG System in Rails Using Nomic Embeddings and OpenAI</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Fri, 18 Jul 2025 19:48:41 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/how-i-built-a-rag-system-in-rails-using-nomic-embeddings-and-openai-154e</link>
      <guid>https://dev.to/travelingwilbur/how-i-built-a-rag-system-in-rails-using-nomic-embeddings-and-openai-154e</guid>
      <description>&lt;p&gt;Retrieval-Augmented Generation (RAG) lets you bring your own data to LLMs—and get real answers. I’ll show how I used the open-source nomic-embed-text-v2-moe model for semantic search in a Rails app, while still using OpenAI for generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 What is RAG?
&lt;/h3&gt;

&lt;p&gt;RAG (Retrieval-Augmented Generation) enhances LLMs by feeding them relevant chunks of your data before generating a response. Instead of fine-tuning, we give the model useful context.&lt;/p&gt;

&lt;p&gt;Here's the basic pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;User&lt;/span&gt; &lt;span class="nt"&gt;Question&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;Embed&lt;/span&gt; &lt;span class="nt"&gt;the&lt;/span&gt; &lt;span class="nt"&gt;Question&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nt"&gt;Nomic&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;Vector&lt;/span&gt; &lt;span class="nt"&gt;Search&lt;/span&gt; &lt;span class="nt"&gt;in&lt;/span&gt; &lt;span class="nt"&gt;PgVector&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;Retrieve&lt;/span&gt; &lt;span class="nt"&gt;Relevant&lt;/span&gt; &lt;span class="nt"&gt;Chunks&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;Assemble&lt;/span&gt; &lt;span class="nt"&gt;Prompt&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;Generate&lt;/span&gt; &lt;span class="nt"&gt;Answer&lt;/span&gt; &lt;span class="nt"&gt;with&lt;/span&gt; &lt;span class="nt"&gt;OpenAI&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧰 The Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rails&lt;/strong&gt; – Backend framework, routes, controllers, and persistence&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nomic&lt;/strong&gt; Embedding Model – For semantic understanding of data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; – Lightweight Python server to serve embeddings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PgVector&lt;/strong&gt; – PostgreSQL extension to store and query vector data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenAI GPT-4 / GPT-3.5&lt;/strong&gt; – For the final response generation&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🛠 Step 1: Run the Nomic Model Locally (Optional but Fast)
&lt;/h3&gt;

&lt;p&gt;You can run the &lt;a href="https://huggingface.co/nomic-ai/nomic-embed-text-v2-moe" rel="noopener noreferrer"&gt;nomic-embed-text-v2-moe&lt;/a&gt; model using &lt;a href="https://www.sbert.net/" rel="noopener noreferrer"&gt;sentence-transformers&lt;/a&gt; in a Python FastAPI app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentence_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SentenceTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nomic-ai/nomic-embed-text-v2-moe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/embed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;input_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_text&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;embedding&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes your internal embedding API, replacing OpenAI’s &lt;code&gt;/embeddings&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  📄 Step 2: Chunk and Store Your Data
&lt;/h3&gt;

&lt;p&gt;Split your content into short passages (~100–300 words), embed them via your FastAPI endpoint, and store the results in PostgreSQL with &lt;code&gt;pgvector&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add a vector column:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-d&lt;/span&gt; your_db &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"CREATE EXTENSION IF NOT EXISTS vector;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;AddEmbeddingToDocuments&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Migration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;7.1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&lt;/span&gt;
    &lt;span class="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:vector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;limit: &lt;/span&gt;&lt;span class="mi"&gt;768&lt;/span&gt; &lt;span class="c1"&gt;# Nomic v2-moe size&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: Embed User Queries via Nomic
&lt;/h3&gt;

&lt;p&gt;In your Rails controller:&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;def&lt;/span&gt; &lt;span class="nf"&gt;get_embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&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="no"&gt;Faraday&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8000/embed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;input: &lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&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;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="s2"&gt;"embedding"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the same model for both document and query embeddings.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔍 Step 4: Perform Vector Search with PgVector
&lt;/h3&gt;

&lt;p&gt;Search your documents for the closest matches using cosine distance:&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="no"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"embedding &amp;lt;-&amp;gt; cube(array[?])"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query_vector&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These top chunks become the context for the LLM.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧾 Step 5: Build a Smart Prompt for OpenAI
&lt;/h3&gt;

&lt;p&gt;Concatenate the top passages and feed them into OpenAI’s chat API:&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;parameters: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="s2"&gt;"gpt-4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;messages: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;role: &lt;/span&gt;&lt;span class="s2"&gt;"system"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="s2"&gt;"You are an assistant answering based on the provided context."&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;role: &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;content: &lt;/span&gt;&lt;span class="n"&gt;build_contextual_prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_chunks&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="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ✅ Why Use Nomic for Embeddings?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;High-quality, open-source, multilingual&lt;/li&gt;
&lt;li&gt;No token limits — runs locally or self-hosted&lt;/li&gt;
&lt;li&gt;Zero vendor lock-in at the embedding layer&lt;/li&gt;
&lt;li&gt;Great performance on MTEB and real-world retrieval&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💡 Why I Still Use OpenAI for the LLM
&lt;/h3&gt;

&lt;p&gt;The generation step is where OpenAI shines. Instead of replacing it prematurely, I decoupled the embedding stage. Now I can experiment, optimize, and even switch LLMs later if needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧠 Takeaways
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;RAG doesn’t need to be a heavyweight system.&lt;/li&gt;
&lt;li&gt;Open-source embeddings + OpenAI generation = powerful, flexible hybrid.&lt;/li&gt;
&lt;li&gt;PgVector + Rails makes vector search feel native and hackable.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rag</category>
      <category>openai</category>
      <category>ai</category>
      <category>rails</category>
    </item>
    <item>
      <title>The Art of Idiomatic Ruby: Principles and Practices for Elegant Code</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Mon, 17 Mar 2025 17:29:02 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/the-art-of-idiomatic-ruby-principles-and-practices-for-elegant-code-53ej</link>
      <guid>https://dev.to/travelingwilbur/the-art-of-idiomatic-ruby-principles-and-practices-for-elegant-code-53ej</guid>
      <description>&lt;p&gt;As developers, we're constantly seeking to improve our craft and develop a coding style that's both effective and elegant. Ruby stands out among programming languages for its expressiveness and focus on developer happiness. The philosophy behind Ruby and its most popular framework, Rails, has shaped how countless developers think about software design, readability, and the overall development experience.&lt;/p&gt;

&lt;p&gt;In this post, I'll explore the key principles behind idiomatic Ruby, analyze what makes Ruby code truly "Rubyesque," and share practical ways to incorporate these principles into your own work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Philosophy of Idiomatic Ruby
&lt;/h2&gt;

&lt;p&gt;Ruby's approach to programming is built on several foundational principles:&lt;/p&gt;

&lt;h3&gt;
  
  
  Convention over Configuration
&lt;/h3&gt;

&lt;p&gt;One of Ruby's most influential frameworks popularized the concept of sensible defaults and conventions. Rather than requiring developers to make countless trivial decisions, idiomatic Ruby emphasizes having established patterns that make assumptions about what developers need and provide streamlined pathways for common tasks.&lt;/p&gt;

&lt;p&gt;This philosophy extends beyond frameworks into coding style, where established patterns and clear conventions are favored over reinventing the wheel or introducing unnecessary complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beautiful Code
&lt;/h3&gt;

&lt;p&gt;In the Ruby community, code isn't just functional—it's a form of craft. There's a strong emphasis on the aesthetics of code, with the understanding that beautiful code is more maintainable, more enjoyable to work with, and ultimately more effective. This focus on beauty manifests in a preference for expressive, readable syntax that almost reads like natural language.&lt;/p&gt;

&lt;h3&gt;
  
  
  Programmer Happiness
&lt;/h3&gt;

&lt;p&gt;"Optimize for programmer happiness" is a consistent theme in the Ruby community. While some languages and frameworks optimize primarily for performance or flexibility, Ruby prioritizes the developer experience. This perspective views coding as a creative act that should be enjoyable rather than tedious.&lt;/p&gt;

&lt;h3&gt;
  
  
  Opinionated Software Design
&lt;/h3&gt;

&lt;p&gt;Idiomatic Ruby doesn't shy away from having strong opinions about how software should be built. Rather than trying to accommodate every possible approach, Ruby and its ecosystem often present "The Ruby Way" of doing things. Making strong choices about architecture and design patterns creates a more cohesive and understandable codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Elements of Idiomatic Ruby Style
&lt;/h2&gt;

&lt;p&gt;When examining truly elegant Ruby code, several distinctive characteristics emerge:&lt;/p&gt;

&lt;h3&gt;
  
  
  Expressive Naming
&lt;/h3&gt;

&lt;p&gt;Idiomatic Ruby places tremendous importance on choosing the right names for variables, methods, and classes. It favors descriptive, sometimes longer names that clearly communicate intent over terse abbreviations. The goal is code that can be read and understood without extensive comments or documentation.&lt;/p&gt;

&lt;p&gt;For example, instead of:&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;def&lt;/span&gt; &lt;span class="nf"&gt;calc_ttl_prc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# Calculate total price with discount&lt;/span&gt;
  &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Idiomatic Ruby prefers:&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;def&lt;/span&gt; &lt;span class="nf"&gt;total_price_with_discount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Embracing Ruby's Natural Expressiveness
&lt;/h3&gt;

&lt;p&gt;Truly Rubyesque code leans heavily into the language's syntax to create code that feels natural and reads almost like English prose. It makes full use of Ruby's blocks, optional parentheses, and symbol shortcuts to create concise yet readable code.&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;# Less idiomatic&lt;/span&gt;
&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribed?&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_newsletter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# More idiomatic &lt;/span&gt;
&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:subscribed?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:send_newsletter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Domain-Driven Design
&lt;/h3&gt;

&lt;p&gt;Idiomatic Ruby often designs code around domain concepts rather than technical implementation details. Classes and methods reflect the business domain, making the code not just functional but a representation of the problem space itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pragmatic Testing Approach
&lt;/h3&gt;

&lt;p&gt;The Ruby community has evolved a pragmatic approach to testing. While testing is valued, there's a focus on testing the outcomes that matter rather than implementation details. System tests that verify functionality from the user's perspective are often favored alongside focused unit tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strategic Metaprogramming
&lt;/h3&gt;

&lt;p&gt;Ruby's powerful metaprogramming capabilities are a double-edged sword. Idiomatic Ruby uses metaprogramming strategically to eliminate boilerplate and create more elegant APIs, not as a showcase of technical wizardry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Design Patterns in Ruby
&lt;/h2&gt;

&lt;p&gt;Several design patterns are central to idiomatic Ruby programming:&lt;/p&gt;

&lt;h3&gt;
  
  
  Active Record Pattern
&lt;/h3&gt;

&lt;p&gt;The Active Record pattern, which blends database access and business logic into a single object, is widely used in the Ruby ecosystem. While this approach breaks with strict separation of concerns, it creates an intuitive model that's easy to work with.&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;Product&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;has_many&lt;/span&gt; &lt;span class="ss"&gt;:reviews&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:category&lt;/span&gt;

  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;numericality: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;greater_than: &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;discounted_price&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.9&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;
  
  
  Modules and Concerns for Shared Behavior
&lt;/h3&gt;

&lt;p&gt;Instead of deep inheritance hierarchies, idiomatic Ruby favors using modules as "Concerns" to share behavior across multiple classes. This creates more flexible composition without the rigid structures that deep inheritance can create.&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;module&lt;/span&gt; &lt;span class="nn"&gt;Trackable&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:audit_logs&lt;/span&gt;
    &lt;span class="n"&gt;after_save&lt;/span&gt; &lt;span class="ss"&gt;:record_change&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;record_change&lt;/span&gt;
    &lt;span class="n"&gt;audit_logs&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="ss"&gt;action: &lt;/span&gt;&lt;span class="s2"&gt;"updated"&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;class&lt;/span&gt; &lt;span class="nc"&gt;Product&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="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Trackable&lt;/span&gt;
  &lt;span class="c1"&gt;# Product-specific code...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Convention-Based Routing
&lt;/h3&gt;

&lt;p&gt;RESTful routing establishes clear conventions for mapping HTTP verbs and URLs to controller actions, creating a predictable structure for web applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Objects for Complex Operations
&lt;/h3&gt;

&lt;p&gt;For operations that span multiple models or incorporate complex business logic, Ruby developers often employ service objects—dedicated classes that encapsulate a single operation or transaction.&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;OrderProcessor&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;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payment_details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;
    &lt;span class="vi"&gt;@payment_details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payment_details&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;process&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;valid?&lt;/span&gt;

    &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;process_payment&lt;/span&gt;
      &lt;span class="n"&gt;update_inventory&lt;/span&gt;
      &lt;span class="n"&gt;send_confirmation&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Private methods for each step...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to Write Idiomatic Ruby
&lt;/h2&gt;

&lt;p&gt;If you're inspired by Ruby's elegant approach and want to incorporate elements of idiomatic style into your own work, here are some practical steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Prioritize Readability Above All
&lt;/h3&gt;

&lt;p&gt;Write code for humans first, computers second. Invest time in creating clear, expressive code that future developers (including your future self) will easily understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Embrace Ruby's Unique Features
&lt;/h3&gt;

&lt;p&gt;Work with Ruby's strengths rather than fighting against them. Learn what makes Ruby special—blocks, procs, symbols, method_missing, etc.—and use those features to create more elegant code.&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;# Instead of:&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"apple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cherry"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;fruit&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Write:&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"apple"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"banana"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cherry"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:upcase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Design Around Your Domain
&lt;/h3&gt;

&lt;p&gt;Structure your code to reflect the business or problem domain rather than technical considerations. Your classes and methods should speak the language of your users and stakeholders.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Follow Conventions but Break Them When Necessary
&lt;/h3&gt;

&lt;p&gt;Establish and follow conventions in your codebase, but be willing to break them when they don't serve your needs. Ruby isn't dogmatic about rules—it's pragmatic about results.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Value Simplicity Over Complexity
&lt;/h3&gt;

&lt;p&gt;Resist the urge to over-engineer. The Ruby community often advocates for the simplest solution that works, even if it's not the most theoretically pure or technically impressive.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Consider the Whole System
&lt;/h3&gt;

&lt;p&gt;Think holistically about your application rather than optimizing individual components in isolation. An idiomatic approach considers how all parts of a system work together to create a cohesive whole.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Make Development Enjoyable
&lt;/h3&gt;

&lt;p&gt;Finally, remember that coding should be enjoyable. Create tools, processes, and code that make development a pleasure rather than a chore—this is perhaps the most Ruby-like approach of all.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Pay Attention to Code Smells
&lt;/h3&gt;

&lt;p&gt;Learn to recognize and refactor common code smells:&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;# Code smell: Long method&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;
  &lt;span class="c1"&gt;# 100 lines of code doing many different things&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Refactored: Extracted methods with clear purposes&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_order&lt;/span&gt;
  &lt;span class="n"&gt;validate_order&lt;/span&gt;
  &lt;span class="n"&gt;process_payment&lt;/span&gt;
  &lt;span class="n"&gt;update_inventory&lt;/span&gt;
  &lt;span class="n"&gt;send_confirmation&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9. Follow Community Style Guides
&lt;/h3&gt;

&lt;p&gt;Familiarize yourself with established Ruby style guides like the one from GitHub or Rubocop's defaults. These encapsulate years of community wisdom about what makes Ruby code clear and maintainable.&lt;/p&gt;




&lt;p&gt;Idiomatic Ruby represents a philosophy of software development that values human factors alongside technical considerations—code that's not just functional but beautiful, maintainable, and enjoyable to work with.&lt;/p&gt;

&lt;p&gt;By prioritizing readability, embracing Ruby's unique features, and focusing on developer happiness, you can create code that not only works but brings joy to those who interact with it. That's the true spirit of Ruby.&lt;/p&gt;

&lt;p&gt;What aspects of Ruby's style have influenced your own development approach? What patterns or practices do you find most valuable in your own Ruby projects? Share your thoughts and experiences in the comments below.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>designpatterns</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Understanding Form Objects in Ruby on Rails</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Thu, 13 Mar 2025 21:38:04 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/understanding-form-objects-in-ruby-on-rails-3bf3</link>
      <guid>https://dev.to/travelingwilbur/understanding-form-objects-in-ruby-on-rails-3bf3</guid>
      <description>&lt;p&gt;In Ruby on Rails applications, handling complex forms can become messy when too much logic is stuffed into models or controllers. This is where &lt;strong&gt;Form Objects&lt;/strong&gt; come in—a design pattern that helps separate form-related logic from Active Record models, making our applications more maintainable and testable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Traditional Forms
&lt;/h2&gt;

&lt;p&gt;By default, Rails encourages using Active Record models directly in forms. However, this approach has some downsides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fat Models&lt;/strong&gt;: Business logic and validation bloat the model, making it harder to maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fat Controllers&lt;/strong&gt;: Controllers become responsible for handling complex form submissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multiple Models in One Form&lt;/strong&gt;: Standard Rails forms work well with single models, but handling multiple related models can be cumbersome.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To address these issues, we use &lt;strong&gt;Form Objects&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Form Object?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Form Object&lt;/strong&gt; is a Plain Old Ruby Object (PORO) designed to handle form submissions. It encapsulates form-specific validations and persistence logic while keeping models and controllers clean.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Use a Form Object
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When a form involves multiple models.&lt;/li&gt;
&lt;li&gt;When you want to keep your controllers thin and models focused.&lt;/li&gt;
&lt;li&gt;When form validation differs from the database schema.&lt;/li&gt;
&lt;li&gt;When reusing form logic across multiple places in your application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementing a Form Object in Rails
&lt;/h2&gt;

&lt;p&gt;Let's walk through an example where we create a &lt;code&gt;UserRegistrationForm&lt;/code&gt; that handles user sign-ups along with profile information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Create the Form Object
&lt;/h3&gt;

&lt;p&gt;Create a new file in &lt;code&gt;app/forms/user_registration_form.rb&lt;/code&gt;:&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;UserRegistrationForm&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ActiveModel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;

  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bio&lt;/span&gt;

  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;presence: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;confirmation: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="n"&gt;validates&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;format: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;with: &lt;/span&gt;&lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;MailTo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;EMAIL_REGEXP&lt;/span&gt; &lt;span class="p"&gt;}&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;attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attributes&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;save&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;valid?&lt;/span&gt;

    &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&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="ss"&gt;name: &lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email: &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;password: &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;Profile&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="ss"&gt;user: &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;bio: &lt;/span&gt;&lt;span class="n"&gt;bio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="kp"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;RecordInvalid&lt;/span&gt;
    &lt;span class="kp"&gt;false&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: Use the Form Object in the Controller
&lt;/h3&gt;

&lt;p&gt;Modify the &lt;code&gt;UsersController&lt;/code&gt; to use the &lt;code&gt;UserRegistrationForm&lt;/code&gt;:&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;UsersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="vi"&gt;@form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;UserRegistrationForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&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;create&lt;/span&gt;
    &lt;span class="vi"&gt;@form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;UserRegistrationForm&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;user_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;
      &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;root_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;notice: &lt;/span&gt;&lt;span class="s1"&gt;'User registered successfully!'&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;:new&lt;/span&gt;
    &lt;span class="k"&gt;end&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;user_params&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user_registration_form&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;permit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:bio&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: Update the View
&lt;/h3&gt;

&lt;p&gt;Modify the &lt;code&gt;new.html.erb&lt;/code&gt; view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form_with&lt;/span&gt; &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="vi"&gt;@form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="n"&gt;users_path&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;form&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_field&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;email_field&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password_field&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;password_field&lt;/span&gt; &lt;span class="ss"&gt;:password_confirmation&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;label&lt;/span&gt; &lt;span class="ss"&gt;:bio&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text_area&lt;/span&gt; &lt;span class="ss"&gt;:bio&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt; &lt;span class="s1"&gt;'Register'&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits of Using Form Objects
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns&lt;/strong&gt;: Keeps models and controllers focused on their primary responsibilities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Improved Testability&lt;/strong&gt;: You can test form logic independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easier Maintenance&lt;/strong&gt;: Avoids bloated models with unnecessary validations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Form Objects in Ruby on Rails provide a clean way to manage complex form submissions while keeping code organized. By encapsulating form logic in a dedicated class, we improve maintainability, readability, and re-usability in our applications.&lt;/p&gt;

&lt;p&gt;If you're dealing with bloated models and controllers due to complex forms, consider adopting Form Objects as a structured solution!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>Background Jobs in Rails: A Look at SolidQueue</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Wed, 12 Mar 2025 05:43:03 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/background-jobs-in-rails-a-look-at-solidqueue-21nh</link>
      <guid>https://dev.to/travelingwilbur/background-jobs-in-rails-a-look-at-solidqueue-21nh</guid>
      <description>&lt;p&gt;Coming from a Rails background, one of the most common patterns developers rely on is background job processing. Traditionally, this has meant reaching for Sidekiq, Resque, or Delayed Job—external tools that require Redis or additional infrastructure. But what if you could handle background jobs natively within your database? Enter SolidQueue.&lt;/p&gt;

&lt;p&gt;In this post, I’ll explore how SolidQueue changes the game for Rails developers, how it compares to existing background job solutions, and how you can start using it today.&lt;/p&gt;

&lt;h2&gt;
  
  
  SolidQueue in Rails 8: Built-In Background Jobs
&lt;/h2&gt;

&lt;p&gt;With the release of Rails 8, SolidQueue is now bundled as the default background job system. This means that if you're starting a new Rails 8 application, you already have everything you need to manage background jobs without any additional dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minimum Required Version
&lt;/h3&gt;

&lt;p&gt;SolidQueue requires Rails 7.1 or later to function. However, for full integration and the best experience, Rails 8 is recommended since it comes pre-configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding SolidQueue: Background Jobs Without External Dependencies
&lt;/h2&gt;

&lt;p&gt;SolidQueue is a database-backed queuing system designed to work seamlessly with Active Job in Rails. Unlike Sidekiq or Resque, which rely on Redis, SolidQueue keeps everything within your application’s SQL database. The result? Simplified infrastructure, reduced operational complexity, and one less dependency to worry about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features of SolidQueue
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Native Database Integration&lt;/strong&gt;: Jobs are stored and managed using PostgreSQL, MySQL, or SQLite—whichever database your Rails app already uses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Active Job Compatibility&lt;/strong&gt;: Works out of the box with Rails' Active Job framework.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Additional Services Required&lt;/strong&gt;: Eliminates the need for Redis or external queueing systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mission Control UI&lt;/strong&gt;: Provides a web interface to monitor and manage jobs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Job Retries &amp;amp; Error Handling&lt;/strong&gt;: Ensures reliable job execution.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How to Set Up SolidQueue in Rails 8
&lt;/h2&gt;

&lt;p&gt;If you're using Rails 8, SolidQueue is already included, and you just need to enable it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling SolidQueue in a New Rails 8 App
&lt;/h3&gt;

&lt;p&gt;For new Rails 8 applications, SolidQueue is the default Active Job adapter. To ensure it is enabled, check your &lt;code&gt;config/application.rb&lt;/code&gt;:&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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;active_job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queue_adapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:solid_queue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, run the database migrations to set up the necessary tables:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting Up SolidQueue in an Existing Rails 7.1+ App
&lt;/h3&gt;

&lt;p&gt;If you're on Rails 7.1 or later and want to use SolidQueue, you'll need to install it manually:&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;# Add to your Gemfile&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'solid_queue'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, run the installation generator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;rails generate solid_queue:install
rails db:migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining and Enqueueing Jobs
&lt;/h2&gt;

&lt;p&gt;Creating jobs with SolidQueue is no different from using Active Job:&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;ExampleJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&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 job for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&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="no"&gt;ExampleJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Running Jobs
&lt;/h3&gt;

&lt;p&gt;SolidQueue requires a supervisor process to run jobs. Start it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;solid_queue:start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will process jobs from the database queue, similar to how Sidekiq works.&lt;/p&gt;

&lt;h2&gt;
  
  
  A More Detailed Example: Processing an Order in Rails 8
&lt;/h2&gt;

&lt;p&gt;Let’s say we’re building an e-commerce application and need to process orders asynchronously. With SolidQueue in Rails 8, we can handle this with ease.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Define the Job
&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;ProcessOrderJob&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationJob&lt;/span&gt;
  &lt;span class="n"&gt;queue_as&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_payment!&lt;/span&gt;
    &lt;span class="n"&gt;order&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="ss"&gt;status: &lt;/span&gt;&lt;span class="s2"&gt;"completed"&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;"Order #&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; has been processed."&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: Enqueue the Job When an Order is Created
&lt;/h3&gt;

&lt;p&gt;Modify your &lt;code&gt;OrdersController&lt;/code&gt;:&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;OrdersController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;
    &lt;span class="vi"&gt;@order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Order&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="n"&gt;order_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;ProcessOrderJob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_later&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="vi"&gt;@order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;notice: &lt;/span&gt;&lt;span class="s2"&gt;"Your order is being processed."&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: Start the Worker Process
&lt;/h3&gt;

&lt;p&gt;To start processing jobs, simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bundle &lt;span class="nb"&gt;exec &lt;/span&gt;solid_queue:start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, every time a new order is created, it will be processed in the background by SolidQueue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing SolidQueue to Sidekiq
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;SolidQueue (Database-Backed)&lt;/th&gt;
&lt;th&gt;Sidekiq (Redis-Backed)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dependency&lt;/td&gt;
&lt;td&gt;Uses SQL database&lt;/td&gt;
&lt;td&gt;Requires Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infrastructure&lt;/td&gt;
&lt;td&gt;No extra services needed&lt;/td&gt;
&lt;td&gt;Needs Redis, Sidekiq&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Good for most applications&lt;/td&gt;
&lt;td&gt;Optimized for high throughput&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI for Jobs&lt;/td&gt;
&lt;td&gt;Mission Control UI&lt;/td&gt;
&lt;td&gt;Sidekiq Web UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reliability&lt;/td&gt;
&lt;td&gt;Database transactions ensure safety&lt;/td&gt;
&lt;td&gt;Redis-based, requires persistence tuning&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you’re running a high-throughput application with millions of background jobs per day, Sidekiq may still be the best choice. But for most Rails applications, SolidQueue provides a much simpler, integrated solution without the extra operational burden.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should You Use SolidQueue?
&lt;/h2&gt;

&lt;p&gt;SolidQueue is a great choice if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You want to avoid the overhead of running Redis.&lt;/li&gt;
&lt;li&gt;Your application already relies heavily on its database.&lt;/li&gt;
&lt;li&gt;You prefer an all-in-one solution with built-in job monitoring.&lt;/li&gt;
&lt;li&gt;You need Active Job compatibility with minimal setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, if you need extreme performance and high concurrency, Sidekiq might still be the better option.&lt;/p&gt;

&lt;p&gt;SolidQueue represents a shift in how Rails developers can handle background jobs. By leveraging the database as a queueing system, it removes the need for external services like Redis while maintaining reliability and simplicity. With Rails 8, SolidQueue is now the default, making background job processing more accessible than ever.&lt;/p&gt;

&lt;p&gt;If you’re using Rails 8, try it out today—it’s already built in! And if you're on an older version, upgrading to Rails 8 or installing SolidQueue manually can help simplify your background job processing.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>programming</category>
    </item>
    <item>
      <title>Concurrency vs. Parallelism in Go: What Every Developer Should Know</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Tue, 11 Mar 2025 16:05:45 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/concurrency-vs-parallelism-in-go-what-every-developer-should-know-aec</link>
      <guid>https://dev.to/travelingwilbur/concurrency-vs-parallelism-in-go-what-every-developer-should-know-aec</guid>
      <description>&lt;p&gt;Following up with my previous post about &lt;a href="https://dev.to/travelingwilbur/concurrency-in-go-a-rails-developers-first-encounter-with-goroutines-3mfj"&gt;Concurrency in Go&lt;/a&gt;, many developers encounter a common misconception: that Go provides true parallelism by default. While Go excels at concurrency with its lightweight goroutines, achieving effective parallel execution requires understanding Go's runtime scheduler and how &lt;code&gt;GOMAXPROCS&lt;/code&gt; affects program behavior. This post explores how Go handles concurrency, when it achieves parallelism, and how it compares to other programming languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concurrency vs. Parallelism: Fundamental Distinctions
&lt;/h2&gt;

&lt;p&gt;These terms are often conflated but represent distinct concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt;: The ability to structure a program to handle multiple tasks, potentially overlapping in time. It's about program design and decomposition of problems into independently executable units.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallelism&lt;/strong&gt;: The simultaneous execution of multiple computations, typically on separate CPU cores. It's about execution and hardware utilization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As Rob Pike famously said: "Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once."&lt;/p&gt;

&lt;p&gt;Go's goroutines and channels provide elegant concurrency primitives, but actual parallel execution depends on runtime configuration and hardware capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go's Concurrency Model: Goroutines and the Runtime Scheduler
&lt;/h2&gt;

&lt;p&gt;Go implements a CSP-based (Communicating Sequential Processes) concurrency model using goroutines—lightweight, user-space threads managed by Go's runtime rather than the operating system. Compared to OS threads which might require megabytes of stack space, goroutines start with only 2KB, allowing programs to spawn millions of them efficiently.&lt;/p&gt;

&lt;p&gt;Here's a simple example demonstrating goroutine creation:&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="s"&gt;"time"&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;sayHello&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 from a goroutine!"&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// Launch goroutine&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Give goroutine time to execute&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;"Main function continues execution"&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;While this code runs the &lt;code&gt;sayHello()&lt;/code&gt; function concurrently with the main function, it doesn't necessarily execute in parallel. Understanding why requires examining Go's scheduler architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go's Scheduler: The M:P:G Model
&lt;/h2&gt;

&lt;p&gt;Go's scheduler implements what's known as the M:P:G model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;G (Goroutines)&lt;/strong&gt;: Application-level tasks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;M (Machine)&lt;/strong&gt;: OS threads that execute code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;P (Processor)&lt;/strong&gt;: Logical processors that manage execution contexts&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ol&gt;
&lt;li&gt;Each P maintains a local queue of runnable goroutines&lt;/li&gt;
&lt;li&gt;Ms (OS threads) execute goroutines from the P they're assigned to&lt;/li&gt;
&lt;li&gt;When a P's queue is empty, it attempts to steal work from other Ps&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This sophisticated work-stealing scheduler efficiently distributes goroutines across available system resources, but the number of Ps is the key limiting factor for parallel execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Controlling Parallelism with GOMAXPROCS
&lt;/h2&gt;

&lt;p&gt;By default, Go sets &lt;code&gt;GOMAXPROCS&lt;/code&gt; equal to the number of available CPU cores since Go 1.5. This value determines the number of Ps (logical processors) in the runtime.&lt;/p&gt;

&lt;p&gt;You can explicitly control this setting in your code:&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="s"&gt;"runtime"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&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;cpuIntensiveTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;int&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task %d starting on CPU %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="c"&gt;// Simulate CPU-intensive work&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;1e9&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Task %d completed&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&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;numCPU&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"System has %d CPU cores&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numCPU&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numCPU&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Explicitly set to use all cores&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GOMAXPROCS set to %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&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="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Launch CPU-intensive goroutines&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;numCPU&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;cpuIntensiveTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Wait for goroutines to complete (in production, use sync.WaitGroup)&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Execution time: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Since&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&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;When &lt;code&gt;GOMAXPROCS &amp;gt; 1&lt;/code&gt; and your system has multiple cores, Go can truly execute goroutines in parallel. However, several factors can still limit actual parallel performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go's Parallelism: Capabilities and Limitations
&lt;/h2&gt;

&lt;p&gt;Go can achieve true parallelism, but with important caveats:&lt;/p&gt;

&lt;h3&gt;
  
  
  Strengths:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Scaling&lt;/strong&gt;: Go automatically distributes work across cores&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low Overhead&lt;/strong&gt;: Goroutines and channel communication have minimal overhead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Work Stealing&lt;/strong&gt;: Efficient distribution of tasks to prevent cores from idling&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Limitations:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cooperative Scheduling&lt;/strong&gt;: Goroutines yield control only at specific points (function calls, channel operations, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop-the-World GC&lt;/strong&gt;: Garbage collection pauses can temporarily halt all execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduler Overhead&lt;/strong&gt;: The work-stealing algorithm adds some overhead&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network-Bound Performance&lt;/strong&gt;: For I/O-heavy workloads, adding cores may not improve throughput&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Benchmarking Parallelism in Go
&lt;/h3&gt;

&lt;p&gt;To evaluate parallelism gains, you can use the &lt;code&gt;testing&lt;/code&gt; package with the &lt;code&gt;-cpu&lt;/code&gt; flag:&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="c"&gt;// parallelism_test.go&lt;/span&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;"runtime"&lt;/span&gt;
    &lt;span class="s"&gt;"testing"&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;BenchmarkComputation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// CPU-intensive computation&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10000000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;j&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;Run with: &lt;code&gt;go test -bench=. -cpu=1,2,4,8&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparative Analysis: Parallelism Across Languages
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;Parallelism Model&lt;/th&gt;
&lt;th&gt;Strengths&lt;/th&gt;
&lt;th&gt;Limitations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;M:P:G scheduler with goroutines&lt;/td&gt;
&lt;td&gt;Easy concurrency, low overhead, work stealing&lt;/td&gt;
&lt;td&gt;Cooperative scheduling, GC pauses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rust&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OS threads + async/await&lt;/td&gt;
&lt;td&gt;Zero-cost abstractions, fine-grained control&lt;/td&gt;
&lt;td&gt;Steeper learning curve, manual synchronization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;C++ (std::thread)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Direct OS thread mapping&lt;/td&gt;
&lt;td&gt;Maximum performance, precise control&lt;/td&gt;
&lt;td&gt;High thread creation overhead, manual resource management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Java&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Thread pools, ForkJoinPool&lt;/td&gt;
&lt;td&gt;Rich ecosystem, mature tooling&lt;/td&gt;
&lt;td&gt;Higher memory overhead, complex thread management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Python&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GIL in CPython, multiprocessing&lt;/td&gt;
&lt;td&gt;Simple API, good for I/O&lt;/td&gt;
&lt;td&gt;GIL prevents true threading parallelism&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Node.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Event loop + worker threads&lt;/td&gt;
&lt;td&gt;Excellent for I/O, non-blocking&lt;/td&gt;
&lt;td&gt;Single-threaded main loop, callback complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Optimizing Go for Parallel Workloads
&lt;/h2&gt;

&lt;p&gt;For CPU-bound tasks requiring maximum parallelism:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Profile First&lt;/strong&gt;: Use &lt;code&gt;go tool pprof&lt;/code&gt; to identify bottlenecks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tune GOMAXPROCS&lt;/strong&gt;: Sometimes setting lower than available cores improves performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize Work Distribution&lt;/strong&gt;: Divide work into equally sized chunks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize Contention&lt;/strong&gt;: Reduce lock contention and shared memory access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consider sync.Pool&lt;/strong&gt;: Reduce GC pressure for frequently allocated objects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Performance-Oriented Packages&lt;/strong&gt;: Consider &lt;code&gt;github.com/valyala/fasthttp&lt;/code&gt; over &lt;code&gt;net/http&lt;/code&gt; for web servers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example of balanced work distribution:&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="s"&gt;"runtime"&lt;/span&gt;
    &lt;span class="s"&gt;"sync"&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;processRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Done&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="c"&gt;// Process the assigned range&lt;/span&gt;
    &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&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="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;i&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;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Range %d-%d sum: %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;totalWork&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1000000&lt;/span&gt;
    &lt;span class="n"&gt;numCPU&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NumCPU&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GOMAXPROCS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numCPU&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;wg&lt;/span&gt; &lt;span class="n"&gt;sync&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WaitGroup&lt;/span&gt;
    &lt;span class="n"&gt;chunkSize&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;totalWork&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;numCPU&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;numCPU&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&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="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;chunkSize&lt;/span&gt;
        &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;chunkSize&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;numCPU&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;totalWork&lt;/span&gt; &lt;span class="c"&gt;// Handle any remainder in the last chunk&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;processRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Wait&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;"All work completed"&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;h2&gt;
  
  
  When to Emphasize Parallelism in Go
&lt;/h2&gt;

&lt;p&gt;Go's design philosophy prioritizes simplicity and maintainability over raw CPU performance. Consider these factors when deciding how much to invest in parallel optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I/O-Bound vs. CPU-Bound&lt;/strong&gt;: For I/O-bound applications, Go's concurrency model already provides excellent throughput without explicit parallelism tuning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Development Time vs. Runtime&lt;/strong&gt;: Optimize only when performance requirements demand it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability Requirements&lt;/strong&gt;: Consider future workload growth patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Constraints&lt;/strong&gt;: Memory limitations may favor alternative approaches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go provides sophisticated concurrency primitives that make parallel programming more accessible than many other languages. While Go can achieve true parallelism, understanding the nuances of its scheduler, the &lt;code&gt;GOMAXPROCS&lt;/code&gt; setting, and inherent limitations helps developers make informed architectural decisions.&lt;/p&gt;

&lt;p&gt;For most applications, Go's default configuration provides an excellent balance of throughput and simplicity. When optimization is necessary, profiling and benchmark-driven tuning yields the best results.&lt;/p&gt;

&lt;p&gt;Whether you're building high-performance web services, data processing pipelines, or distributed systems, Go's approach to concurrency and parallelism offers a compelling foundation for modern software development.&lt;/p&gt;

&lt;p&gt;What has been your experience with parallelism in Go? Share in the comments below!&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Concurrency in Go: A Rails Developer’s First Encounter with Goroutines</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Wed, 05 Feb 2025 13:55:27 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/concurrency-in-go-a-rails-developers-first-encounter-with-goroutines-3mfj</link>
      <guid>https://dev.to/travelingwilbur/concurrency-in-go-a-rails-developers-first-encounter-with-goroutines-3mfj</guid>
      <description>&lt;p&gt;Coming from a Ruby on Rails background, one of the most striking differences when switching to Go is how it handles concurrency. Rails applications often rely on external tools like Sidekiq, Resque, or Thread-based parallelism to manage background jobs and concurrent tasks. Go, on the other hand, has concurrency built into the language itself, using lightweight &lt;strong&gt;goroutines&lt;/strong&gt; and &lt;strong&gt;channels&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;In this post, I’ll walk through the key differences between Go’s concurrency model and Ruby’s threading model, why Go’s approach is so powerful, and how you can start writing concurrent Go programs.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Understanding Concurrency in Go&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Go was designed from the ground up to support concurrency as a first-class feature. The key components of its concurrency model are:  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Goroutines: Lightweight, Managed Threads&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;goroutine&lt;/strong&gt; is a function that runs concurrently with other functions. Unlike system threads, goroutines are extremely lightweight because they are managed by the Go runtime, not the OS. They start with just a few kilobytes of stack space and grow as needed.  &lt;/p&gt;

&lt;p&gt;Starting a goroutine is as simple as using the &lt;code&gt;go&lt;/code&gt; keyword:&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="s"&gt;"time"&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;sayHello&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 from a Goroutine!"&lt;/span&gt;&lt;span class="p"&gt;)&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="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;sayHello&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;// This runs concurrently&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Prevent main from exiting immediately&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;sayHello()&lt;/code&gt; runs in a separate goroutine. The &lt;code&gt;main&lt;/code&gt; function needs a &lt;code&gt;Sleep&lt;/code&gt; to ensure the goroutine gets time to execute before the program exits.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Channels: Safe Communication Between Goroutines&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Goroutines don’t share memory by default. Instead, they communicate using &lt;strong&gt;channels&lt;/strong&gt;, which provide a safe way to pass data between them.&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="s"&gt;"fmt"&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;ch&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="s"&gt;"Hello, World!"&lt;/span&gt; &lt;span class="c"&gt;// Send data into the channel&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ch&lt;/span&gt; &lt;span class="c"&gt;// Receive data from the channel&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="n"&gt;message&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;This approach eliminates many of the pitfalls of traditional multi-threading, such as race conditions and complex locking mechanisms.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How Ruby Handles Concurrency&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ruby’s concurrency model is different. By default, Ruby threads are OS-managed and can be affected by the &lt;strong&gt;Global Interpreter Lock (GIL)&lt;/strong&gt; in MRI (Matz’s Ruby Interpreter). This means only one thread executes at a time, limiting true parallelism.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Ruby Threads: OS-Managed and Heavyweight&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ruby supports threads, but they are heavier than Go’s goroutines. Here’s a simple example of spawning a thread in Ruby:&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;thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Hello from a Thread!"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt; &lt;span class="c1"&gt;# Wait for the thread to finish&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While this works, Ruby threads consume more memory than goroutines and are subject to OS scheduling.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Background Jobs: Offloading Work&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since Ruby’s threading model isn’t great for high concurrency, Rails developers often turn to &lt;strong&gt;background job processing frameworks&lt;/strong&gt; like Sidekiq or Resque, which rely on Redis and external worker processes to handle concurrency.  &lt;/p&gt;

&lt;p&gt;Example of Sidekiq in Rails:&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;HardWorker&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Worker&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;perform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;count&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;"Doing hard work for &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; times!"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;HardWorker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While these tools work well, they introduce extra dependencies and infrastructure complexity compared to Go’s built-in concurrency model.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Key Differences: Go vs. Ruby Concurrency&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Go (Goroutines &amp;amp; Channels)&lt;/th&gt;
&lt;th&gt;Ruby (Threads &amp;amp; Background Jobs)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lightweight&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes, goroutines are extremely lightweight&lt;/td&gt;
&lt;td&gt;No, Ruby threads are OS-managed and heavier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Managed by&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Go runtime&lt;/td&gt;
&lt;td&gt;OS scheduler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Parallel Execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes, true parallelism possible&lt;/td&gt;
&lt;td&gt;Limited due to GIL in MRI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Built-in Concurrency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes, goroutines &amp;amp; channels are first-class citizens&lt;/td&gt;
&lt;td&gt;No, relies on third-party solutions like Sidekiq&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Memory Usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Low, goroutines share heap efficiently&lt;/td&gt;
&lt;td&gt;High, OS threads are heavier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scalability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scales well due to efficient concurrency model&lt;/td&gt;
&lt;td&gt;Requires external tools for large-scale concurrency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;When to Use Concurrency in Go&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that you see how Go’s concurrency model differs, here are some real-world scenarios where goroutines and channels shine:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Handling thousands of simultaneous requests in a web server&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streaming data processing (e.g., real-time analytics)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient background job execution (e.g., email processing, batch jobs)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-performance APIs with non-blocking I/O&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example of a simple HTTP server in Go that handles requests concurrently using goroutines:&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="s"&gt;"net/http"&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;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello, %s!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8080"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Runs in a goroutine&lt;/span&gt;
    &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c"&gt;// Keep the program running&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each request runs in its own goroutine, making the server highly scalable.&lt;/p&gt;




&lt;p&gt;For a Rails developer transitioning to Go, the built-in support for concurrency is a game-changer. Go’s &lt;strong&gt;goroutines&lt;/strong&gt; and &lt;strong&gt;channels&lt;/strong&gt; eliminate much of the complexity involved in traditional multi-threading. Unlike Ruby, where you often rely on background job queues and OS-managed threads, Go lets you write highly concurrent applications &lt;strong&gt;with minimal dependencies and better performance&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;If you're coming from Rails, expect some initial adjustment when learning Go’s concurrency patterns. However, once you get used to &lt;strong&gt;goroutines, channels, and Go’s structured simplicity&lt;/strong&gt;, you’ll see why Go has become the go-to language for scalable and high-performance systems.  &lt;/p&gt;

</description>
      <category>go</category>
      <category>rails</category>
    </item>
    <item>
      <title>Hash Maps</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Sat, 11 Feb 2023 04:48:36 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/hash-maps-3igh</link>
      <guid>https://dev.to/travelingwilbur/hash-maps-3igh</guid>
      <description>&lt;p&gt;A hash map, also known as a dictionary or associative array, is a data structure that stores key-value pairs and provides fast access to the values based on their keys. In Ruby, the hash map data structure is implemented as a hash, which is represented by curly braces &lt;code&gt;{}&lt;/code&gt; and each key-value pair is separated by a comma &lt;code&gt;,&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's now look at some examples of hash maps in Ruby.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1: Counting occurrences of elements in an array&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this example, we'll create a hash map to count the occurrences of each element in an array.&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;# Define the array&lt;/span&gt;
&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Create a hash map to count the occurrences of each element&lt;/span&gt;
&lt;span class="n"&gt;counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;arr&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;element&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
    &lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&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;# Print the counts&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;counts&lt;/span&gt; &lt;span class="c1"&gt;# Output: {1=&amp;gt;2, 2=&amp;gt;2, 3=&amp;gt;2, 4=&amp;gt;1}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 2: Finding the frequency of words in a string&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this example, we'll create a hash map to find the frequency of words in a string.&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;# Define the string&lt;/span&gt;
&lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Ruby is a dynamic, open source programming language with a focus on simplicity and productivity."&lt;/span&gt;

&lt;span class="c1"&gt;# Create a hash map to find the frequency of words in the string&lt;/span&gt;
&lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;frequency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;words&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;word&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;frequency&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
    &lt;span class="n"&gt;frequency&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;frequency&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&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;# Print the frequency of words&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;frequency&lt;/span&gt; &lt;span class="c1"&gt;# Output: {"Ruby"=&amp;gt;1, "is"=&amp;gt;1, "a"=&amp;gt;2, "dynamic,"=&amp;gt;1, "open"=&amp;gt;1, "source"=&amp;gt;1, "programming"=&amp;gt;1, "language"=&amp;gt;1, "with"=&amp;gt;1, "focus"=&amp;gt;1, "on"=&amp;gt;1, "simplicity"=&amp;gt;1, "and"=&amp;gt;1, "productivity."=&amp;gt;1}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example 3: Grouping elements of an array by their type&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this example, we'll create a hash map to group the elements of an array by their type.&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;# Define the array&lt;/span&gt;
&lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;a: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;b: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;

&lt;span class="c1"&gt;# Create a hash map to group the elements of the array by their type&lt;/span&gt;
&lt;span class="n"&gt;grouped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;arr&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;element&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;grouped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
    &lt;span class="n"&gt;grouped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;grouped&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&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;# Print the grouped elements&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;grouped&lt;/span&gt; &lt;span class="c1"&gt;# Output: {Fixnum=&amp;gt;[1, 2], String=&amp;gt;["Hello"], Float=&amp;gt;[2.0], Array=&amp;gt;[[1, 2, 3]], Hash=&amp;gt;[{:a=&amp;gt;1, :b=&amp;gt;2}]}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Practical Usage of Hash Maps in Ruby&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hash maps are widely used in Ruby for various purposes such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Storing configuration settings&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Counting occurrences of elements in an array&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finding the frequency of words in a string&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grouping elements of an array by their type&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing memoization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing caches&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing symbol tables in compilers&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this blog post, we learned about hash map implementation in Ruby and saw several examples of how they can be used in practice. From counting occurrences of elements in an array to grouping elements of an array by their type, hash maps are a versatile data structure that can make our lives as developers much easier.&lt;/p&gt;

&lt;p&gt;I hope this article helped give you a deeper understanding of hash maps and how to implement them in Ruby. If you have any questions, comments, or examples of your own, feel free to reach out. I'd love to hear from you!&lt;/p&gt;

&lt;p&gt;Remember to share your thoughts, and other implementations in different languages, or simply keep in touch.&lt;/p&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>career</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Stacks and Queues</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Fri, 10 Feb 2023 17:43:15 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/stacks-and-queues-38hf</link>
      <guid>https://dev.to/travelingwilbur/stacks-and-queues-38hf</guid>
      <description>&lt;p&gt;Stacks and Queues are two basic data structures used in computer science and software engineering. This post will explain what stacks and queues are, how they function, and how to use them in Ruby. I will also add RSpec tests for the implementations.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Stacks&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A stack is a data structure that operates on the Last-In-First-Out (LIFO) principle. This indicates that the last item added to the stack will be the first to be deleted. Stacks are frequently used in programs to keep track of function calls (the call stack) or to reverse the order of items.&lt;/p&gt;

&lt;p&gt;Here's an example of a basic Ruby stack implementation:&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;Stack&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;@elements&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;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&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;pop&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&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;empty?&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&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;In this implementation, the push method is used to add an element to the top of the stack, the pop method is used to remove the top element from the stack, and the empty? method is used to determine whether the stack is empty.&lt;/p&gt;

&lt;p&gt;Here are some RSpec tests for our stack implementation:&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;describe&lt;/span&gt; &lt;span class="no"&gt;Stack&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"#push"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"adds an element to the top of the stack"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stack&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;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@elements&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&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="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"#pop"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"removes the top element from the stack"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stack&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;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&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="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@elements&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&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="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"#empty?"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"returns true if the stack is empty"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stack&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"returns false if the stack is not empty"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stack&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;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;false&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Queues&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A Queue is a FIFO (First-In-First-Out) data structure. This implies that the first thing added to the queue will also be the first item withdrawn. Queues are frequently used to create waiting lines or to schedule jobs.&lt;/p&gt;

&lt;p&gt;Here's an example of a simple Ruby queue implementation:&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;Queue&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;@elements&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;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;element&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;dequeue&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shift&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;empty?&lt;/span&gt;
    &lt;span class="vi"&gt;@elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&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;In this implementation, the enqueue method is used to add an element to the end of the queue, and the dequeue method is used to remove the initial element from the queue, and the empty? method determines whether the queue is empty.&lt;/p&gt;

&lt;p&gt;Here are some RSpec tests for our queue implementation:&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;dedescribe&lt;/span&gt; &lt;span class="no"&gt;Queue&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"#enqueue"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"adds an element to the end of the queue"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Queue&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;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enqueue&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="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@elements&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&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="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"#dequeue"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"removes the first element from the queue"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Queue&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;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enqueue&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="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dequeue&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@elements&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&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="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"#empty?"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"returns true if the queue is empty"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Queue&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"returns false if the queue is not empty"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Queue&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;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enqueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="kp"&gt;false&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm thrilled to have shared my knowledge of stack and queue algorithms in Ruby with you. These fundamental ideas are necessary for any computer science student or programmer to understand. Experimenting with these algorithms in Ruby was a great learning experience for me, and I hope it was for you as well.&lt;/p&gt;

&lt;p&gt;It's now your turn! I'd love to learn about how you've implemented these techniques in different programming languages. Share your ideas, ask questions, and let's keep growing and learning together. Don't be afraid to post a comment. I'm looking forward to hearing from you!&lt;/p&gt;

</description>
      <category>software</category>
      <category>tooling</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The most serious programming error to avoid is failing to do thorough testing.</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Thu, 09 Feb 2023 05:56:38 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/the-most-serious-programming-error-to-avoid-is-failing-to-do-thorough-testing-1edl</link>
      <guid>https://dev.to/travelingwilbur/the-most-serious-programming-error-to-avoid-is-failing-to-do-thorough-testing-1edl</guid>
      <description>&lt;p&gt;Programming is a multi-step process that requires a lot of problem-solving. Despite the greatest efforts of programmers, errors are unavoidable. Certain mistakes, however, are more common and have a greater impact on the code's functionality and efficiency. In this blog article, we'll discuss one such blunder that every programmer should avoid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Not sufficiently testing code"&lt;/strong&gt; is the one mistake that everyone should avoid.&lt;/p&gt;

&lt;p&gt;Code testing is an essential part of the software development process. It aids in the detection of bugs and verifying that the code is functioning properly. On the other side, many programmers either do not test their code at all or do not test it well. This may result in unexpected behavior, bugs, and finally dissatisfied consumers.&lt;/p&gt;

&lt;p&gt;To avoid making this mistake, it is critical to establish a rigorous testing approach that tackles all probable scenarios. This includes edge case testing, system compatibility testing, performance testing, and security testing. With the use of automated testing methods, test coverage may be enhanced and the process simplified.&lt;/p&gt;

&lt;p&gt;Using the Test-Driven Development (TDD) approach is one of the best techniques to ensure thorough testing. Developers write tests before writing actual code in the TDD approach. This facilitates the specification of exact code requirements and ensures that the code, once built, conforms with those requirements. TDD assists developers in detecting errors early in the development process, making it easier and faster to resolve them.&lt;/p&gt;

&lt;p&gt;Finally, fully testing code is a crucial piece in the software development process that should not be overlooked. It can save time and effort while eventually improving the user experience. Avoiding this error will result in a more stable and trustworthy codebase that meets user expectations.&lt;/p&gt;

</description>
      <category>search</category>
      <category>ai</category>
      <category>nlp</category>
    </item>
    <item>
      <title>Establishing my own foundation</title>
      <dc:creator>Wilbur Suero</dc:creator>
      <pubDate>Wed, 08 Feb 2023 13:12:24 +0000</pubDate>
      <link>https://dev.to/travelingwilbur/establishing-my-own-foundation-30g0</link>
      <guid>https://dev.to/travelingwilbur/establishing-my-own-foundation-30g0</guid>
      <description>&lt;p&gt;It's easy for me as a developer to become preoccupied with the technical aspects of my profession, such as mastering new tools and technologies, learning new programming languages, and delivering code that meets specifications. But I've realized how important it is to establish a firm foundation of personal convictions to attain great success in my career.&lt;/p&gt;

&lt;p&gt;We'll look at some of the most important personal values for developers and how they might help you thrive and feel happy at work in this post.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pay close attention to the details.
&lt;/h3&gt;

&lt;p&gt;One of the most important personal qualities for developers is attention to detail. To produce high-quality code, one must pay close attention to the details, guarantee that the requirements are satisfied, and ensure that the code is error-free. When you pay attention to detail, you will be able to produce more dependable and efficient code, and your team and stakeholders will appreciate you for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Curiosity and a desire to learn
&lt;/h3&gt;

&lt;p&gt;Curiosity and a desire to acquire knowledge are two other essential characteristics of developers. Because technology and programming languages are always changing, a successful developer must constantly learn and adapt to new tools and techniques. If you like learning, you will be able to stay up with the most recent innovations in your sector and be more productive and efficient at work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Communication skills
&lt;/h3&gt;

&lt;p&gt;Effective communication is a critical personal value for engineers. When working with team members, stakeholders, and clients, you must be able to effectively communicate your ideas and perspectives. Strong communication skills will allow you to work more effectively with others and convey your thoughts and solutions more effectively.&lt;/p&gt;

&lt;h3&gt;
  
  
  Accountability and responsibility
&lt;/h3&gt;

&lt;p&gt;Developers are accountable for the code they write, ensuring that it meets quality requirements and performs as intended. When you have a strong sense of responsibility and accountability, you may create a good reputation as a developer by being more dependable and trustworthy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Empathy and collaboration
&lt;/h3&gt;

&lt;p&gt;To produce high-quality software that meets the needs of users, developers must be able to understand their desires and requirements as well as interact effectively with team members and stakeholders. When you have high collaboration and empathy qualities, you may create long-lasting connections with people and execute effectively in a team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flexibility and adaptability
&lt;/h3&gt;

&lt;p&gt;Developers must be able to pivot quickly in response to changing demands, technologies, and workflows. When you have a flexible and adaptive attitude, you will be better capable of managing changes and unanticipated obstacles, and you will also be more effective and productive at work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quality obsession
&lt;/h3&gt;

&lt;p&gt;A quest for perfection is another important character trait for developers. Developers must be committed to building code that is reliable, scalable, and secure. If you have a strong desire for excellence, you will be more motivated to do your best work and will be more likely to be recognized and rewarded for your efforts.&lt;/p&gt;

&lt;p&gt;Finally, personal values are crucial in determining your success and satisfaction as a developer. By emphasizing qualities such as attention to detail, a love of learning, effective communication, responsibility and accountability, empathy and teamwork, flexibility and adaptation, and a passion for quality, you will be laying the groundwork for a solid career.&lt;/p&gt;

&lt;p&gt;These principles serve as a compass for my work, guiding me in making decisions, confronting obstacles, and interacting with others in a way that is true to who I am and what I stand for. By focusing on my principles, I can continue to grow as a developer and advance professionally.&lt;/p&gt;

&lt;p&gt;So, whether you're a new developer or an experienced veteran, I encourage you to pause and consider your values. What guiding principles drive your work? What motivates and inspires you to do your best work? By focusing on your own convictions, you may establish a firm career foundation and pave the route for success and fulfillment.&lt;/p&gt;

</description>
      <category>security</category>
      <category>howto</category>
      <category>network</category>
    </item>
  </channel>
</rss>
