All Articles

Herb on Rails

ERB does not know that it is generating HTML. It finds the <% %> tags, evaluates the Ruby inside them, and concatenates everything else as plain text. Whether the result is valid markup has never been its problem.

Herb changes that. On August 25, 2026, the Ruby on Rails core team merged Add Herb as an HTML-aware ERB implementation opens a new window , which brings in Herb opens a new window , an ERB implementation that parses HTML and ERB into a single syntax tree and uses Prism opens a new window for the Ruby inside the tags. Broken markup can now fail while the template compiles, instead of reaching a browser.

In this article, you will learn what Herb is, how to audit your own views with it today, what it can fix for you, what it cannot, and what it costs to run. We used the FastRuby.io views as the test subject.

Read more of Herb on Rails opens a new window

Rails 8.2: The HTTP QUERY Method

RFC 10008, published in June 2026, defines the QUERY method as safe and idempotent like GET, and it carries its query in the request body like POST. Ruby on Rails merged support for QUERY on August 14, 2026, under the 8.2.0 milestone.

I set up a small application on edge Rails to check it working. The routing and the request object are ready, but the parts of the specification that make QUERY more than a POST with better manners are not quite there yet, since Rails parses only JSON bodies and does not enforce the content type rule RFC 10008 requires. In this article, we will check how the QUERY method works in Rails, how to route and test it, how Puma is handling it, and which pieces of the specification are still missing. Everything below reflects the state of things at the beginning of September 2026, and since Rails, Rack, and Puma all have the interesting parts sitting on unreleased branches, it is worth checking the versions yourself before trusting any of it.

Read more of Rails 8.2: The HTTP QUERY Method opens a new window

Irish Chess Union Upgrades to Rails 8.1

Founded in 1912, the Irish Chess Union (ICU) is the governing body for chess across the island of Ireland. It has about 2,500 members and run entirely by volunteers.

Its website, icu.ie opens a new window , has been maintained by webmaster Jonathan O’Connor since 2015. Earlier this year, Jonathan reached out to us. He wanted help taking the ICU’s Rails application from 7.0 to 8.1.

We used Claude Code and our open source Claude Code Rails Upgrade Skill opens a new window to get it done. We also recorded the sessions as a video series, so other teams could see the methodology in practice.

In this article, we’ll walk through the upgrade, one version at a time, and share what Jonathan thought of the process.

Read more of Irish Chess Union Upgrades to Rails 8.1 opens a new window

Upgrading a Deprecated Postgres on Heroku

Heroku sent us an email about the database behind ips.fastruby.io opens a new window , a small app we run for sharing benchmark-ips opens a new window results. That database runs Postgres 15, and the email gave it an end-of-life date on Heroku of January 20, 2027. If we do nothing before December 20, 2026, they will upgrade it to Postgres 18 for us.

Staying in control of when that happens beats finding out on Heroku’s schedule, so I upgraded it that same night. I skipped the method Heroku recommends for a documented one that suited this database better, and still finished the job with commands that are not in their documentation.

In this article, you will learn how we moved a Heroku Postgres database off a deprecated version, why we copied the data into a new database instead of upgrading in place, how much downtime to plan for, and which parts of Heroku’s tooling failed on us. We upgraded from Postgres 15 to 18, but the steps are much the same whichever version you are leaving behind.

Read more of Upgrading a Deprecated Postgres on Heroku opens a new window

The Rails Deprecations You Missed This Summer

Ruby on Rails keeps changing between releases. Five This Week in Rails opens a new window issues rolled in eight Active Record deprecations and behavior changes on Rails main over the last few weeks. Most are small renames. One is a real bug fix that stops a write from leaking outside its association. None of it has shipped in a tagged release yet, main is currently versioned 8.2.0.alpha. Rails has shipped a new minor version roughly every year (8.0 in November 2024, 8.1 in October 2025), so 8.2 landing sometime around the end of 2026 is a reasonable bet, well ahead of binds, which has a committed removal date of 8.3. uniq! is the one to not expect soon: its removal is tied to 9.0, and Rails hasn’t announced a timeline for that one yet. Nothing in your Gemfile breaks today, but you’ll want to know about it before it does. If you’ve been tracking this kind of thing, you might remember we covered deprecated associations in Rails 8.1 opens a new window back in July. This is the next batch.

I’ll get into what’s changing in each of the eight, why the Rails team made the change, and what to update in your own code once it ships. If you want the general playbook for handling deprecation warnings during an upgrade, we have a guide for that too opens a new window .

Read more of The Rails Deprecations You Missed This Summer opens a new window

Turning Audit Findings into CI Checks

You get a site audit report and it looks manageable. A few dozen findings, most of them small: a page with barely any text on it, a link whose text is just “here”, a page whose title tag is a copy of its H1, a hero image heavy enough to hurt the largest contentful paint opens a new window . None of it is that hard. You spend an afternoon on it, close the tickets, and move on.

Then a few months pass, a dozen new pages ship, and the next audit reports the same findings again. Not because anyone ignored the first round, but because the first round fixed pages instead of fixing the process that produces pages.

That happened to us, on this site and on OmbuLabs.ai opens a new window . So the second time around we spent the effort somewhere else. Instead of just fixing the pages, we wrote checks that run on every build and say when a new page has the same problem. It is roughly the same idea as automating a tech debt audit opens a new window : most of the value is not in the report, it is in being able to produce the report again for free. No two of them wanted the same kind of check.

The goal here is search traffic, not a clean report. Thin pages, vague link text, and duplicated title tags are the things that hold a page back in search results, and a page that ships with them costs us traffic until the next audit finds it. A check on every build moves that discovery from months later to the pull request.

In this article, you will learn how we turned three kinds of audit findings into checks that run in CI.

Read more of Turning Audit Findings into CI Checks opens a new window

How to Avoid APM Bill Surprises

You approved an APM tool at a modest monthly rate. A year later, the renewal invoice bears little resemblance to what you signed, and nobody remembers deciding to spend that much more.

APM is worth having when it’s used well: it resolves incidents faster by showing you where in the stack a problem started, it gives you warning before a threshold alert turns into an outage, and it gives you a defensible answer when a client or stakeholder asks whether you hit your SLA (often measured through percentile response times opens a new window like p95 and p99). None of that is in question here. What tends to go unexamined is whether the bill still matches what you’re getting for it.

In this article, we’ll walk through where APM spend typically concentrates, the warning signs that a bill has drifted from usage-driven growth into unmanaged creep, and a concrete checklist for getting ahead of it before your next renewal.

Read more of How to Avoid APM Bill Surprises opens a new window

Repay Tech Debt with the Strangler Fig Pattern

Replacing a business-critical legacy system does not have to mean committing to a risky, all-at-once rewrite. The strangler fig pattern offers a practical alternative: migrate one capability at a time, run the old and new systems side by side, and gradually retire the legacy code as each replacement is validated. This post walks through how it works, where it fits, and a practical Rails-based example of migrating one piece of functionality without stopping the business to do it.

Read more of Repay Tech Debt with the Strangler Fig Pattern opens a new window

What Replacing React with Hotwire Really Costs

It’s common to see a Rails app using React to handle front-end interactions, with a Redux store that mostly mirrors the database and react-router re-declaring routes Rails already knows about. React does its job well enough, but every user-facing feature now costs twice, once in Ruby and once in JavaScript.

So eventually the question will appear: what would it take to delete all of this and use a Rails-way solution like Hotwire opens a new window ? The honest answer is “it depends.” In this article, we will go through what the code difference actually looks like, what you can expect from bundle size, which pain points to plan for, and how to scope the work before committing to it.

Read more of What Replacing React with Hotwire Really Costs opens a new window

SimpleCov is now version 1!

Here at FastRuby.io we work with test suites and test coverage reports every single day, given our specialty. In the Ruby world that means we interact with SimpleCov every day. Not only that, we explicitely rely on SimpleCov reports in two of the open source projects we maintain, RubyCritic opens a new window and Skunk opens a new window .

Which is why, after more than a decade at 0.x, we were super excited to see SimpleCov opens a new window ship its first stable release on July 12, 2026. In this article we’d like to share the details on the breaking changes, the deprecations and how to address them, if you’re impacted by them.

Read more of SimpleCov is now version 1! opens a new window

How to Distribute Private Gems

When I first started thinking about private gem distribution, I approached the problem the way I always do, backward from bundle install. What does a developer need to make that command succeed for a private library? Three things: a source (URL or repo), credentials that work in CI and locally, and a reliable way to receive updates without breaking deployments.

Not all code belongs on RubyGems.org opens a new window , and that’s okay. Sometimes the goal is internal reuse- sharing an SDK or auth client across services. Sometimes it’s a business model: you ship a private gem behind a license. Either way, the constraints are the same: authentication, delivery, and trust.

In this blog post, we’ll give an overview of the options for distributing private gems.

Read more of How to Distribute Private Gems opens a new window

Why To Use A Multi-Stage Dockerfile

Docker has made it easy to use the same environment everywhere, from development to production. But the most basic Dockerfile, where all your dependencies are lumped together in one image, has hidden costs. In this article, we’ll learn the advantages of multi-stage Dockerfiles both from a security and a performance standpoint, primarily for production images.

Read more of Why To Use A Multi-Stage Dockerfile opens a new window

Measuring Code Coverage For Non-Ruby Runners

When we think about Ruby code coverage, our go-to gem for this is SimpleCov opens a new window , which works great when the test suite uses Minitest opens a new window , RSpec opens a new window , Cucumber opens a new window , Capybara opens a new window , and all these tools that are integrated with Ruby and Rails. But many applications also use other tools like Playwright opens a new window or Cypress opens a new window to run e2e tests, and we can’t use SimpleCov the same way.

Most of the time, what we have seen is that the Ruby code executed when running these tools ends up left behind and not being counted for the total code coverage, even though we know the code is actually being tested.

Read more of Measuring Code Coverage For Non-Ruby Runners opens a new window

Opening a Repo Is Now an Execution Event

If you work on Rails for a living, you clone repositories you didn’t write all week long: a gem you’re debugging, a client’s application you’re about to audit, a bug reproduction attached to an issue. For years, opening one of those in your editor was the safe part. You were reading someone else’s code, not running it, and the only real rule was to not run anything until you had looked.

That rule quietly stopped being enough. AI coding editors like Claude Code and Cursor read project-local configuration the moment you open a repository, and some of that configuration is executable. A repo you cloned five seconds ago can hand your editor a command to run before you have read a line of it, and this is not hypothetical: the npm worm that hit keyv this week (Socket opens a new window , Aikido opens a new window , and Microsoft opens a new window all covered it) weaponized exactly this, writing itself into .claude/settings.json so it runs again for anyone who opens the project.

In this post, we’ll look at why opening a repository in an AI editor is now an execution event, how the keyv worm turned that into a live attack, and what to check in a cloned repo’s .claude/ and .vscode/ directories before you point your editor at it.

Read more of Opening a Repo Is Now an Execution Event opens a new window

Why Your Yarn App Suddenly Looks for Bun

You run bundle update, kick off a build, and asset precompilation stops on this:”

cssbundling-rails: Command install failed, ensure bun is installed
Tasks: TOP => assets:precompile => css:build => css:install

Except your application uses Yarn. It has always used Yarn. Nothing in the project references Bun, and nobody on the team added it.

This is not an exotic edge case. It can happen to ordinary Yarn applications, and it lingers because the fix has been merged upstream but never released. In this post, we’ll walk through why cssbundling-rails misidentifies your package manager, and how to unblock your build.

Read more of Why Your Yarn App Suddenly Looks for Bun opens a new window