<?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: Madhusudhanan</title>
    <description>The latest articles on DEV Community by Madhusudhanan (@madhuhari188).</description>
    <link>https://dev.to/madhuhari188</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%2F1073380%2F4c86602a-1a78-44b4-9458-cb29f0a07406.png</url>
      <title>DEV Community: Madhusudhanan</title>
      <link>https://dev.to/madhuhari188</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/madhuhari188"/>
    <language>en</language>
    <item>
      <title>🧩 How We Solved “Unable to Get Certificate CRL” in Rails: A Debugging Story</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Fri, 14 Nov 2025 07:30:00 +0000</pubDate>
      <link>https://dev.to/madhuhari188/how-we-solved-unable-to-get-certificate-crl-in-rails-a-debugging-story-2pna</link>
      <guid>https://dev.to/madhuhari188/how-we-solved-unable-to-get-certificate-crl-in-rails-a-debugging-story-2pna</guid>
      <description>&lt;p&gt;If you’ve been around Rails long enough, you’ve probably battled your fair share of SSL demons. But this one? This one had &lt;em&gt;personality&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It was a &lt;code&gt;Seahorse::Client::NetworkingError&lt;/code&gt; that failed &lt;strong&gt;only on macOS&lt;/strong&gt; — yet worked perfectly inside Docker. The kind of “it works on my container” bug that makes you question every life choice leading up to this point.&lt;/p&gt;

&lt;p&gt;So here’s the story of how we chased down a ghostly SSL error, only to discover that the real culprit was… OpenSSL itself.&lt;/p&gt;

&lt;h2&gt;⚠️ The Error&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;Seahorse::Client::NetworkingError
SSL_connect returned=1 errno=0 peeraddr=[...]
state=error: certificate verify failed (unable to get certificate CRL)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This popped up whenever our Rails app tried connecting to AWS S3 using the &lt;code&gt;aws-sdk-ruby&lt;/code&gt; gem.&lt;/p&gt;

&lt;h2&gt;🔍 The Contradiction That Made No Sense&lt;/h2&gt;

&lt;p&gt;From the get-go, the bug refused to play by any rules of logic.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;❌ &lt;strong&gt;It failed locally&lt;/strong&gt; but&lt;/li&gt;
  &lt;li&gt;✅ &lt;strong&gt;Worked flawlessly in Docker&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That told us one thing: the problem wasn’t our code. It was the environment. macOS and Docker’s Linux setup were behaving differently.&lt;/p&gt;

&lt;h2&gt;🧪 The “Wait, What?” Moment&lt;/h2&gt;

&lt;p&gt;We decided to test the SSL connection manually, expecting it to fail the same way:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;openssl s_client -connect 52.219.66.109:443 -servername s3.ap-south-1.amazonaws.com &amp;lt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Result?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Verify return code: 0 (ok)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So, macOS’s OpenSSL tool had no problem verifying the certificate.  
But Rails (and the AWS SDK) still choked on it.&lt;/p&gt;

&lt;p&gt;At this point, confusion levels were high. Coffee consumption was higher.&lt;/p&gt;

&lt;h2&gt;🧠 The Real Test — Inside the Rails Console&lt;/h2&gt;

&lt;p&gt;To rule out any system-level differences, we went straight into &lt;code&gt;rails c&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;require 'aws-sdk-s3'
s3 = Aws::S3::Client.new(region: 'ap-south-1')
s3.list_buckets
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;certificate verify failed (unable to get certificate CRL)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Boom. So the system OpenSSL was fine, but Ruby’s built-in OpenSSL (via &lt;code&gt;Net::HTTP&lt;/code&gt;) was throwing a tantrum.&lt;/p&gt;

&lt;h2&gt;🧩 The Root Cause — A Policy Change in OpenSSL&lt;/h2&gt;

&lt;p&gt;That cryptic message — &lt;em&gt;“unable to get certificate CRL”&lt;/em&gt; — turned out to be the key.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;CRL (Certificate Revocation List)&lt;/strong&gt; is basically a “blacklist” for certificates that have been revoked. The problem? The AWS certificate didn’t actually &lt;em&gt;have&lt;/em&gt; a CRL defined.&lt;/p&gt;

&lt;p&gt;We checked with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;openssl s_client ... | openssl x509 -noout -text | grep "CRL Distribution Points"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Result:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;X509v3 CRL Distribution Points:
# (empty)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Comparing environments made things click:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Environment&lt;/th&gt;
      &lt;th&gt;OpenSSL Version&lt;/th&gt;
      &lt;th&gt;Result&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;macOS (failing)&lt;/td&gt;
      &lt;td&gt;3.4.0 (new)&lt;/td&gt;
      &lt;td&gt;❌ Fails&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Docker (working)&lt;/td&gt;
      &lt;td&gt;3.0.11 (stable)&lt;/td&gt;
      &lt;td&gt;✅ Works&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Turns out, &lt;strong&gt;OpenSSL 3.4.0 introduced stricter validation rules&lt;/strong&gt;.  
It now treats missing CRL entries as fatal errors — whereas the 3.0.x series simply shrugged and moved on.&lt;/p&gt;

&lt;p&gt;So no, your Mac isn’t broken — it’s just being &lt;em&gt;too helpful&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;🛠 The Fixes — Two Paths to Sanity&lt;/h2&gt;

&lt;p&gt;After a lot of trial (and some error), we landed on two solid fixes.&lt;/p&gt;

&lt;h3&gt;🧩 Fix 1: The Local-Only (Insecure but Practical) Workaround&lt;/h3&gt;

&lt;p&gt;Since this issue only showed up in development, one quick way to move on is to tell AWS SDK to skip SSL verification locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create:&lt;/strong&gt; &lt;code&gt;config/initializers/aws_ssl_workaround.rb&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# WARNING: LOCAL DEVELOPMENT ONLY
# OpenSSL 3.4.0 enforces stricter CRL policies, so skip verification here.
if Rails.env.development?
  Aws.config.update(ssl_verify_peer: false)
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;✅ Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Works instantly&lt;/li&gt;
  &lt;li&gt;Doesn’t affect production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚠️ Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Insecure (but fine for local development)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;🧠 Fix 2: Match Environments (I tried this one!)&lt;/h3&gt;

&lt;p&gt;The better long-term solution is to make your local OpenSSL match Docker’s version.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
&lt;strong&gt;Install an older OpenSSL (3.0.x):&lt;/strong&gt;
    &lt;pre&gt;&lt;code&gt;brew install openssl@3.0&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;
&lt;strong&gt;Reinstall Ruby:&lt;/strong&gt;
    &lt;pre&gt;&lt;code&gt;rbenv uninstall 3.2.2
RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@3.0)" rbenv install 3.2.2&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;

  &lt;li&gt;
&lt;strong&gt;Reinstall gems:&lt;/strong&gt;
    &lt;pre&gt;&lt;code&gt;gem install bundler
bundle install&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now your local Ruby is linked against OpenSSL 3.0 — just like Docker and peace is restored.&lt;/p&gt;

&lt;h2&gt;🧾 Confirmation &amp;amp; References&lt;/h2&gt;

&lt;p&gt;Turns out, we weren’t the only ones haunted by this ghost:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
&lt;a href="https://github.com/openssl/openssl/issues/28758" rel="noopener noreferrer"&gt;openssl/openssl#28758&lt;/a&gt; — CRL verification failures in OpenSSL 3.6.0&lt;/li&gt;
  &lt;li&gt;
&lt;a href="https://github.com/ruby/openssl/issues/949" rel="noopener noreferrer"&gt;ruby/openssl#949&lt;/a&gt; — Net::HTTP failing due to stricter CRL rules&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;💡 Takeaway&lt;/h2&gt;

&lt;p&gt;SSL errors can feel like black magic, but more often than not, they’re &lt;em&gt;version mismatches in disguise&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;So next time something works in Docker but not on your laptop, remember:  
sometimes it’s not your code, it’s just your OpenSSL being extra.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading! If you found this helpful, share it with a fellow developer who’s currently staring at an SSL error and losing their mind.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>tutorial</category>
      <category>security</category>
    </item>
    <item>
      <title>💡 Rails Tip:
Use bundle exec rails c or bin/rails c to ensure the console runs with your app’s gem versions.
rails c alone can load mismatched gems 🚫</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Tue, 28 Oct 2025 11:48:22 +0000</pubDate>
      <link>https://dev.to/madhuhari188/rails-tip-use-bundle-exec-rails-c-or-binrails-c-to-ensure-the-console-runs-with-your-apps-gem-1nig</link>
      <guid>https://dev.to/madhuhari188/rails-tip-use-bundle-exec-rails-c-or-binrails-c-to-ensure-the-console-runs-with-your-apps-gem-1nig</guid>
      <description></description>
      <category>cli</category>
      <category>rails</category>
      <category>ruby</category>
    </item>
    <item>
      <title>The One-Letter Rails Bug That Slipped Past Rubocop, CI, and Code Reviews</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Wed, 03 Sep 2025 08:33:55 +0000</pubDate>
      <link>https://dev.to/madhuhari188/the-one-letter-rails-bug-that-slipped-past-rubocop-ci-and-code-reviews-12im</link>
      <guid>https://dev.to/madhuhari188/the-one-letter-rails-bug-that-slipped-past-rubocop-ci-and-code-reviews-12im</guid>
      <description>&lt;p&gt;We often think production bugs happen because of big oversights or complex logic failures. But sometimes, it’s the smallest things a single typo that sneak past every safeguard and cause trouble in live environments.&lt;/p&gt;

&lt;p&gt;Recently, I had one such experience in a Rails project. It wasn’t a major crash, but it did break a piece of business logic under specific conditions. More importantly, it taught me valuable lessons about code reviews, rubocop, and testing discipline lessons I’d like to share here.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Safeguards We Already Had
&lt;/h3&gt;

&lt;p&gt;Like most teams, we don’t push code directly to production. Instead, we follow a layered safety net:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;✅ Pre-commit checks to catch obvious mistakes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ RSpec test cases to validate logic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ CI pipelines to enforce standards and run checks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ Code reviews to ensure human oversight&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;✅ QA testing before deployment&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’d think with all this in place, no typo could possibly slip through. So how did it happen?&lt;/p&gt;

&lt;h3&gt;
  
  
  Where Things Went Wrong: Rubocop and a “Helpful” Auto Fix
&lt;/h3&gt;

&lt;p&gt;In this Rails project, we rely on Rubocop for code style enforcement. Normally, we fix issues in one of two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Manually correcting the code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Running rubocop -A for automatic fixes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But this time, I chose a third option: letting my AI powered IDE auto suggest fixes. And that’s where the trouble began.&lt;/p&gt;

&lt;p&gt;The IDE suggested changing this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="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;"start_date DESC"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Existing&lt;/span&gt;

&lt;span class="c1"&gt;#to this:&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="ss"&gt;start_date: :des&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Auto suggested&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the problem? &lt;code&gt;:des&lt;/code&gt; is a typo it should have been &lt;code&gt;:desc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Rubocop didn’t catch it. Tests didn’t cover that exact line. Reviewers missed it. And before we knew it, the code went live.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Aftermath
&lt;/h3&gt;

&lt;p&gt;A few hours after deployment, we noticed the issue in a read replica query. By then, the rake task had already run. Thankfully, the impact was limited, and we quickly reverted the change.&lt;/p&gt;

&lt;p&gt;After proper testing, we fixed the issue and redeployed safely. But the lesson was loud and clear: automation is powerful, but not infallible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways for Rails Developers
&lt;/h3&gt;

&lt;p&gt;Here are the practical lessons I walked away with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Don’t skip QA when unrelated code changes occur. Even if you’re only fixing style or small tweaks, ensure major areas affected by the change get tested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review staged changes before committing. Don’t blindly trust auto fixes. Double-check what’s being committed in your name.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Re-review your PR on GitHub or GitLab. Even after staging, a second look often catches mistakes that slip through the first pass.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stay aware of “helpful” AI and IDE suggestions. They’re great tools—but you own the final responsibility for what’s shipped.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;This experience reinforced something every Rails developer should remember: typos are small, but their impact isn’t. Between Rubocop, CI pipelines, and human reviews, we have strong safety nets but no safeguard replaces mindful coding and thorough reviews.&lt;/p&gt;

&lt;p&gt;So the next time your IDE “helpfully” suggests a change, pause for a second. That quick check might save you from the kind of bug that inspired this post.&lt;/p&gt;

&lt;p&gt;👉 What about you? Have you ever had a tiny mistake sneak into production despite all your safeguards? I’d love to hear your stories in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>rails</category>
      <category>rubocop</category>
      <category>ai</category>
    </item>
    <item>
      <title>Python VEnv Setup: A Rails Developer's Survival Guide 🐍</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Thu, 05 Jun 2025 09:00:00 +0000</pubDate>
      <link>https://dev.to/madhuhari188/python-venv-setup-a-rails-developers-survival-guide-ofk</link>
      <guid>https://dev.to/madhuhari188/python-venv-setup-a-rails-developers-survival-guide-ofk</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;Ever been in a situation where you solve a tricky technical problem, celebrate your victory, only to face the exact same problem months later with no memory of your brilliant solution? 😅 That's exactly what happened to me, and it taught me a valuable lesson about documenting those "one-off" solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Genesis of a Python Problem 💡
&lt;/h3&gt;

&lt;p&gt;In our project, we had a unique requirement: efficiently manage feature flags. Our solution involved moving one of our API endpoints to an AWS Lambda Function. My task? Replicate the existing API response using Python and, of course, use the same environment variables. Sounds straightforward, right?&lt;/p&gt;

&lt;p&gt;Initially, it felt like smooth sailing. I got hold of the existing Python code used for authorization, analyzed how to handle requests and responses, and started writing my own. But then came the pain point: setting up a Python virtual environment (venv). As a Rails developer, Python venvs were a foreign concept to me. I was completely lost! 😵‍💫&lt;/p&gt;

&lt;p&gt;I scoured the web, consulted AI, and eventually, with some help from my Python-savvy teammates, I managed to set up the venv and get my code working locally. Phew!&lt;/p&gt;

&lt;h3&gt;
  
  
  The Deployment Gauntlet 🚀
&lt;/h3&gt;

&lt;p&gt;But the challenges didn't stop there. When deploying the code to Lambda, I ran into package issues. No idea why! 🤔 Thankfully, sharing the local packages from my venv (a quick fix suggested by a teammate) resolved the deployment woes. After a bit more testing, it was finally in production and working perfectly! 🎉&lt;/p&gt;

&lt;h3&gt;
  
  
  Deja Vu... Six Months Later! 🤦‍♂️
&lt;/h3&gt;

&lt;p&gt;Fast forward six months. We needed to migrate another API using the same approach. And guess what? I'd completely forgotten the venv setup steps! It felt like a joke, but it wasn't. While the DevOps and code changes were fresh in my mind, the local Python setup was a blank slate. I had to start from scratch.&lt;/p&gt;

&lt;p&gt;However, this time, with the help of AI and some residual knowledge tucked away in my brain, I managed to get it done much faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Power of Documentation ✍️
&lt;/h3&gt;

&lt;p&gt;This recurring struggle highlighted a crucial point: the immense importance of documenting solutions that aren't covered at the project or framework level. These are the "hidden gems" of knowledge that can save you (and your colleagues) countless hours in the future.&lt;/p&gt;

&lt;p&gt;For example, a simple note like this could have saved me a lot of hassle:&lt;/p&gt;

&lt;h2&gt;
  
  
  How to set up a Python virtual environment (venv) for this project:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Navigate to your project directory&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;your_project_name

&lt;span class="c"&gt;# 2. Create the virtual environment&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv venv

&lt;span class="c"&gt;# 3. Activate the virtual environment&lt;/span&gt;
&lt;span class="nb"&gt;source &lt;/span&gt;venv/bin/activate

&lt;span class="c"&gt;# 4. Install dependencies (assuming you have a requirements.txt)&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# To deactivate:&lt;/span&gt;
deactivate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This experience solidified my belief that documenting these small, specific solutions is just as important as documenting the core project. It's a collaborative effort that benefits everyone!&lt;/p&gt;

&lt;p&gt;That's it for this one! I hope my experience encourages you to document those tricky solutions. Until next time, keep coding and keep learning! 💻📚&lt;/p&gt;

</description>
      <category>rails</category>
      <category>python</category>
      <category>aws</category>
      <category>documentation</category>
    </item>
    <item>
      <title>How to Add V2 on Swagger: Adding Version 2 (V2) with Swagger!</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Fri, 18 Apr 2025 12:40:49 +0000</pubDate>
      <link>https://dev.to/madhuhari188/leveling-up-our-api-adding-version-2-v2-with-swagger-and-a-little-detour--lf0</link>
      <guid>https://dev.to/madhuhari188/leveling-up-our-api-adding-version-2-v2-with-swagger-and-a-little-detour--lf0</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;So, recently I tackled a really interesting challenge: implementing API versioning for one of our projects and making sure the documentation stayed crystal clear. We decided to go with Swagger (now OpenAPI Specification) for the docs, and I wanted to share the steps we took to bring V2 of our API to life alongside its shiny new documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Laying the Foundation for V2 Controllers
&lt;/h2&gt;

&lt;p&gt;First things first, we needed a dedicated space for our V2 controllers. It felt nice and organized to create a new directory structure. Here's a peek at how we set it up in our Ruby on Rails app:&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/controllers/api/v2/users/users_controller.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Api&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;V2&lt;/span&gt;
    &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Users&lt;/span&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="c1"&gt;# Our awesome V2 controller methods will live here!&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps things nice and tidy, separating the concerns of different API versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Telling Swagger About V2
&lt;/h2&gt;

&lt;p&gt;Next up, we needed to tell Swagger about our new V2. This involved tweaking our &lt;code&gt;swagger_helper.rb&lt;/code&gt; file. We essentially added a whole new section to define the documentation specifically for V2:&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;# spec/swagger_helper.rb&lt;/span&gt;
&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&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;config&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;swagger_docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'v1/swagger.json'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;# Our existing V1 configuration stayed here&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="s1"&gt;'v2/swagger.json'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;openapi: &lt;/span&gt;&lt;span class="s1"&gt;'3.0.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;info: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;title: &lt;/span&gt;&lt;span class="s1"&gt;'API V2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;version: &lt;/span&gt;&lt;span class="s1"&gt;'v2'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;description: &lt;/span&gt;&lt;span class="s1"&gt;'User service V2 APIs'&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="ss"&gt;paths: &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="ss"&gt;servers: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="s1"&gt;'{defaultHost}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;variables: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="ss"&gt;defaultHost: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="s1"&gt;'http://localhost:3000'&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="ss"&gt;components: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;securitySchemes: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;# Our security setup...&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="ss"&gt;schemas: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;# Defining our data structures...&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="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how we defined a separate entry for &lt;code&gt;'v2/swagger.json'&lt;/code&gt; with its own info section, clearly marking it as V2.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Writing Specs That Know Their Version
&lt;/h2&gt;

&lt;p&gt;To make sure our V2 endpoints were properly documented, we created new request spec files specifically for them. The key here was linking these specs to the V2 Swagger documentation:&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;# spec/requests/api/v2/users_spec.rb&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'swagger_helper'&lt;/span&gt;

&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'api/v2/users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;swagger_doc: &lt;/span&gt;&lt;span class="s1"&gt;'v2/swagger.json'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;type: :request&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="s1"&gt;'/api/v2/users/send_otp'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'send otp'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;# All the details about this V2 endpoint go here!&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;That &lt;code&gt;swagger_doc: 'v2/swagger.json'&lt;/code&gt; line is the magic that tells RSwag to include this documentation in our V2 Swagger file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Giving Users a Choice on the Docs Page
&lt;/h2&gt;

&lt;p&gt;Okay, so we had the V2 documentation all set up behind the scenes. But what good is it if you can't actually see it alongside the original? We needed to give users a way to easily switch between API versions right there on the documentation page. My initial thought was to configure the RSwag UI to list both V1 and V2 endpoints. Here's what I added to our config/initializers/rswag_ui.rb:&lt;/p&gt;

&lt;p&gt;Done the below thing in your Rails app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# config/initializers/rswag_ui.rb&lt;/span&gt;
&lt;span class="no"&gt;Rswag&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Ui&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&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;c&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openapi_endpoint&lt;/span&gt; &lt;span class="s2"&gt;"/api-docs/v1/swagger.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"API V1 Docs"&lt;/span&gt;
  &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openapi_endpoint&lt;/span&gt; &lt;span class="s2"&gt;"/api-docs/v2/swagger.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"API V2 Docs"&lt;/span&gt;

  &lt;span class="c1"&gt;# Add Basic Auth in case your API is private&lt;/span&gt;
  &lt;span class="c1"&gt;# c.basic_auth_enabled = true&lt;/span&gt;
  &lt;span class="c1"&gt;# c.basic_auth_credentials 'username', 'password'&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 theory, this should have presented a nice little dropdown or list in the UI, allowing seamless navigation between API V1 and V2. But... spoiler alert... it didn't work right away! Cue the head-scratching and mild frustration. I knew I must have missed something obvious, and I made a mental note to revisit this mystery at the end of the post.&lt;/p&gt;

&lt;p&gt;This should have given a clear and intuitive way to navigate between the different API versions in the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Unleashing the Swagger Rake Task!
&lt;/h2&gt;

&lt;p&gt;With all the configurations in place, it was time to generate the actual Swagger documentation files. This was as simple as running this Rake task:&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;rake rswag:specs:swaggerize
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OR&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This command did its thing and, lo and behold, we had both &lt;code&gt;swagger/v1/swagger.json&lt;/code&gt; and &lt;code&gt;swagger/v2/swagger.json&lt;/code&gt; ready to go!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: The Importance of Testing Across Versions
&lt;/h2&gt;

&lt;p&gt;Of course, no development process is perfect, and we did hit a few snags along the way:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ensuring V1 Still Plays Nice:&lt;/strong&gt; We had to double-check that any underlying V1 methods we reused in V2 were still working as expected and didn't have any unintended side effects.&lt;br&gt;
Key Takeaways from the Journey&lt;br&gt;
Here are a few things that really stood out during this process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Keep Schemas Separate:&lt;/strong&gt;
Maintaining distinct schemas for each API version in swagger_helper.rb is key for clarity and avoids confusion.
Be Explicit with swagger_doc: Using the swagger_doc parameter in your request specs is essential for linking the documentation to the correct version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embrace Component Reuse (Where Sensible):&lt;/strong&gt; If there are common data structures or security schemes, reusing them across versions can save time and effort, but be mindful of potential version-specific changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test, Test, Test Across Versions:&lt;/strong&gt; I can't stress this enough! Thorough testing of both old and new API versions is vital for a smooth transition and to prevent breaking existing functionality.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The thing I missed is very funny. Since we change the initializers file, we need to restart the server. I totally missed that and spent some additional time scratching my head! Later found my own silly mistake and fixed it 😂. Always the simple things, right?&lt;/p&gt;

&lt;p&gt;Overall, implementing API versioning and documenting it with Swagger was a worthwhile effort. It provides a much cleaner and more organized way to evolve our API while keeping our developers (and anyone integrating with us) well-informed.&lt;/p&gt;

&lt;p&gt;What are your experiences with API versioning and documentation? I'd love to hear your thoughts and any tips you might have! 😊&lt;/p&gt;

</description>
      <category>api</category>
      <category>rails</category>
      <category>documentation</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Sharing Your Local Rails App for Development and Testing with Ngrok</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Thu, 10 Oct 2024 08:27:00 +0000</pubDate>
      <link>https://dev.to/madhuhari188/sharing-your-local-rails-app-for-development-and-testing-with-ngrok-2k91</link>
      <guid>https://dev.to/madhuhari188/sharing-your-local-rails-app-for-development-and-testing-with-ngrok-2k91</guid>
      <description>&lt;p&gt;Developing an application often involves testing on your own system or with dedicated tools. But what if you need to share your progress or test features with devices not on your network?&lt;/p&gt;

&lt;p&gt;Enter Ngrok, a powerful tool for developers! Ngrok allows you to expose your local web server to the internet securely, creating temporary URLs accessible from any device.&lt;/p&gt;

&lt;p&gt;This guide will show you how to set up Ngrok and use it with your Rails app, streamlining your development and testing workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Sign Up for Ngrok
&lt;/h2&gt;

&lt;p&gt;Head over to the Ngrok platform and create an account. On the welcome page, you'll see options for different agent types (software used to interact with Ngrok).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Friey1zwih304cfn5zcd2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Friey1zwih304cfn5zcd2.png" alt="Welcome dashboard" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Install Ngrok (Docker Method)
&lt;/h2&gt;

&lt;p&gt;For this guide, we'll use the Docker agent. However, Ngrok offers various agent types.  Choose the one that best suits your environment, and follow the installation instructions provided on the Ngrok dashboard.&lt;/p&gt;

&lt;p&gt;Here's the Docker command to run Ngrok and expose your Rails app on port 80:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;NGROK_AUTHTOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;****&lt;/span&gt; ngrok/ngrok:latest http 80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important Note: Replace "****" with your actual Ngrok auth token, which you can find in your Ngrok account dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Ensure Firewall Permissions
&lt;/h2&gt;

&lt;p&gt;Verify that your firewall allows incoming connections to the port your application is running on (usually port 80). Refer to the screenshot below for an example of firewall settings on macOS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4odpj3am7ac8vqq21cx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm4odpj3am7ac8vqq21cx.png" alt="Firewall settings on mac" width="562" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Start Your Rails App &amp;amp; Configure Local Development
&lt;/h2&gt;

&lt;p&gt;Launch your local Rails development server with the port mentioned in the Ngrok command output (usually port 80 in this case).&lt;/p&gt;

&lt;p&gt;If you're using a local development environment, add the following line to your config.hosts file in config/environments/development.rb:&lt;/p&gt;

&lt;p&gt;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;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hosts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s1"&gt;'.ngrok-free.app'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sharing Your App&lt;/p&gt;

&lt;p&gt;Voila! Now you have a temporary public URL provided by Ngrok.  Share this URL with your collaborators or test it on any device with an internet connection.&lt;/p&gt;

&lt;p&gt;Advanced Ngrok Features&lt;/p&gt;

&lt;p&gt;Ngrok offers a variety of features beyond basic tunnelling. In a future post, we'll delve deeper into exploring the full potential of Ngrok!&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Tips:
&lt;/h2&gt;

&lt;p&gt;Ngrok offers a free plan with limitations. Upgrading to a paid plan unlocks additional features and extended tunnel durations.&lt;br&gt;
For enhanced security, consider using Ngrok with authentication methods offered in their paid plans.&lt;br&gt;
This guide should get you started with Ngrok and streamline the development and testing process for your Rails app. Feel free to share your experiences and ask any questions in the comments below!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>beginners</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Is Using an Integer Column as an Array a Good Practice in Rails with PostgreSQL?</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Sat, 08 Jul 2023 08:52:28 +0000</pubDate>
      <link>https://dev.to/madhuhari188/using-integer-column-as-array-is-fine-rails-with-postgres-1ogo</link>
      <guid>https://dev.to/madhuhari188/using-integer-column-as-array-is-fine-rails-with-postgres-1ogo</guid>
      <description>&lt;p&gt;Hi everyone! I'm back with another blog post. Today, I want to share with you a recent experience I had while working on a project that involved storing an array of integer values in a database. I initially used an integer column with an array type and an empty array as the default value. Let me show you the 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="n"&gt;add_column&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:selected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;array: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="p"&gt;[]&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="no"&gt;SELECTED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"0"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Blue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"2"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Red"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, when my senior reviewed my code, he pointed out that integer data type columns should only be used for storing integer values, not other data types. He suggested that the selected column's data type should be a string. Additionally, he asked me to investigate whether using an array in an integer column was a good practice.&lt;/p&gt;

&lt;p&gt;To address his concerns, I turned to the official PostgreSQL documentation. According to the documentation,&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;PostgreSQL allows columns of a table to be defined as variable-length multidimensional arrays. Arrays of any built-in or user-defined base type, enum type, composite type, range type, or domain can be created.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Armed with this information, I explained my findings to my senior. In response, he shared another reference link that outlined the permitted params when using the array type in a database column. Here's what he shared:&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;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&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;:selected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;selected: &lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;He warned me that if we submit an array as nil or containing nil values, it would raise an error. The error message stated:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Value for params[:selected] was set to nil, because it was one of [], [null] or [null, null, ...]. Go to &lt;a href="http://guides.rubyonrails.org/security.html#unsafe-query-generation" rel="noopener noreferrer"&gt;http://guides.rubyonrails.org/security.html#unsafe-query-generation&lt;/a&gt; for more information. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand this error better, I consulted the &lt;a href="http://guides.rubyonrails.org/security.html#unsafe-query-generation" rel="noopener noreferrer"&gt;Rails guides on security&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The guide explained that&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Due to the way Active Record interprets parameters in combination with the way that Rack parses query parameters it was possible to issue unexpected database queries with IS NULL where clauses. As a response to that security issue (CVE-2012-2660, CVE-2012-2694 and CVE-2013-0155) deep_munge method was introduced as a solution to keep Rails secure by default.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The deep_munge method replaces some values with nil to prevent unsafe query generation. Here's how the parameters are transformed based on the JSON sent in the request:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;JSON&lt;/th&gt;
&lt;th&gt;Parameters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;{ "person": null }&lt;/td&gt;
&lt;td&gt;{ :person =&amp;gt; nil }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{ "person": [] }&lt;/td&gt;
&lt;td&gt;{ :person =&amp;gt; [] }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{ "person": [null] }&lt;/td&gt;
&lt;td&gt;{ :person =&amp;gt; [] }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{ "person": [null, null, ...] }&lt;/td&gt;
&lt;td&gt;{ :person =&amp;gt; [] }&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{ "person": ["foo", null] }&lt;/td&gt;
&lt;td&gt;{ :person =&amp;gt; ["foo"] }&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It is possible to return to old behavior and disable deep_munge configuring your application if you are aware of the risk and know how to handle it:&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;action_dispatch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;perform_deep_munge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After considering all of this information, my senior agreed that using an array in an integer column was a suitable approach. So, we celebrated our decision to use arrays in integer columns! 🥳&lt;/p&gt;

&lt;p&gt;This was a positive experience for me. If something happens that makes me interested or teaches me something new, I will let you friends know.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>postgres</category>
      <category>webdev</category>
      <category>ruby</category>
    </item>
    <item>
      <title>How to pass boolean values in Rspec</title>
      <dc:creator>Madhusudhanan</dc:creator>
      <pubDate>Sat, 24 Jun 2023 04:54:21 +0000</pubDate>
      <link>https://dev.to/madhuhari188/how-to-pass-boolean-values-in-rspec-469</link>
      <guid>https://dev.to/madhuhari188/how-to-pass-boolean-values-in-rspec-469</guid>
      <description>&lt;p&gt;Hey there, fellow programmer! 🤓 Let's dive into the world of Rails API testing and explore how to handle boolean parameters correctly. It's time to put on our detective hats and solve the mystery of unexpected test failures!&lt;/p&gt;

&lt;p&gt;So, picture this: you're working on an API endpoint in your Rails application, and you want to test if it correctly handles a boolean parameter called active. You decide to use RSpec for your testing needs because, well, it's awesome! Here's how you might write the test case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe 'API Endpoint' do
  it 'handles boolean parameter correctly' do
    get '/api/endpoint', params: { active: true }
    expect(response.status).to eq(200)
    expect(response.body).to include('Success')
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looks good, right? But hold your horses, my friend! There's a sneaky bug lurking in the shadows. When you run this test, you might encounter a failure, even though your API endpoint is implemented correctly. What sorcery is this? 🧙‍♂️&lt;/p&gt;

&lt;p&gt;Well, here's the deal: boolean values passed in the params can sometimes be converted into strings. And that's exactly what's happening here. The innocent-looking true is being transformed into the mischievous string "true". No wonder our test is failing!&lt;/p&gt;

&lt;p&gt;To get to the bottom of this, let's add a little detective work to our test case. We'll use a puts statement to print the params in the console:&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="s1"&gt;'API Endpoint'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'handles boolean parameter correctly'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s1"&gt;'/api/endpoint'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;params: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;active: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nb"&gt;puts&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;inspect&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&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;200&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;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="nf"&gt;to&lt;/span&gt; &lt;span class="kp"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Success'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, when we run the test, we can inspect the params and see what's really going on. And voila! We discover that our innocent true has indeed been transformed into the string "true". No wonder our if condition might pass when it shouldn't. This is a classic case of mistaken identity!&lt;/p&gt;

&lt;p&gt;But fear not, my friend! We have the power to fix this issue and restore justice to our code. We just need to ensure that the parameters are passed in the correct format. And one way to do that is by setting the format as JSON. 🦸‍♀️&lt;/p&gt;

&lt;p&gt;By setting the format as JSON, Rails will handle boolean values correctly and prevent them from being converted into strings. To achieve this, we can modify our test case like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;describe 'API Endpoint' do
  it 'handles boolean parameter correctly' do
    get '/api/endpoint', params: { active: true }, as: :json
    expect(response.status).to eq(200)
    expect(response.body).to include('Success')
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See what we did there? We added the as: :json option to our test case. This little gem explicitly tells Rails to treat the params as JSON. And guess what? It works like magic! 🎩✨&lt;/p&gt;

&lt;p&gt;Now, when we run our test, the boolean value true will be preserved as an actual boolean, and not transformed into a string. Our if condition will behave as expected, and our test will pass with flying colors!&lt;/p&gt;

&lt;p&gt;So there you have it, my fellow programmer. You now know how to handle boolean parameters correctly in Rails API testing with RSpec. Remember to set the format as JSON in your test cases, and those pesky string conversions will be a thing of the past. Happy testing! 🚀🎉&lt;/p&gt;

&lt;p&gt;Here is the reference Link: &lt;a href=":%20https://github.com/rspec/rspec-rails/issues/1519"&gt;Github&lt;/a&gt; &lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>webdev</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
