April 15, 2026
See the LIVE DEMO in action MapView Render maps directly from your backend no external APIs required. Fast, controlled, and production-ready. Try the demo → Today I created a flyer to send to Ruby on Rails Kaigi about my library stack. I strongly recommend keeping an eye on that conference. After … Continue reading Create QR Codes from Scratch with Ruby, ruby-libgd, and rqrcode
Slow database queries can significantly impact the user experience of any Rails application. Identifying and fixing these performance bottlenecks requires a systematic approach and the right set of tools.
In this post, we will explore various approaches to debugging query performance in Rails, from built in Rails tools to database specific utilities.
Understanding the Problem
Before diving into debugging tools, it’s important to understand what makes a query slow. Common causes include:
- Missing or inefficient indexes
- N+1 query problems
- Full table scans
- Complex joins without proper optimization
- Large result sets being loaded into memory
- Inefficient WHERE clauses
Rails…
rubygems.org has a public roadmap
rubygems.org has been a busy project. This past year we shipped formal policies for the first time in the registry’s history, launched the Organizations private beta, and made some meaningful security improvements to how gems get validated and how compromised passwords get caught. A lot of that work happened quietly. If you wanted to know where things were headed, you had to catch the right conference talk or subscribe to the right newsletter, and even then you’d only get pieces. The roadmap puts it in one place.
The roadmap covers work at different stages, from Organizations moving toward general availability to longer-horizon work on security tooling, gem archival, and acceptable use…
Every design team I’ve worked with has had the same complaint about clients.
“They sent over a PowerPoint with mockups.” Eye rolls. Crossed arms. The unspoken accusation: you’re stepping on my domain.
I got it. The client would shortcut the process. Fall in love with their own wireframes. Hand the designer a solution instead of a problem.
That friction was real.
But here’s what nobody said out loud… the designers were doing the same thing to the developers.
A designer would disappear for a few weeks. Come back with approved comps. Hand them off to a dev team with zero context on the constraints they’d just inherited. The developers would look at the designs and realize that one…
Building Resilient Mobile Apps: A Layered Testing Strategy for Long-Term Stability

Mobile teams shipping on a weekly cadence need automated confidence that changes won’t break what’s already working. At Gusto, our iOS codebase had unit tests, but coverage was uneven, and we hadn’t yet adopted snapshot testing. Major upgrades and component refactors still required significant manual verification. We wanted a more deliberate, layered approach — one that would scale with the team and the product.
The moment that sharpened our focus: a localization string change wasn’t caught by our existing automation and surfaced just one day before release. The fix took minutes — but the late discovery cost a full release cycle.
Manual testing doesn’t scale with growing teams and faster…

Introducing rails_vite—a new Vite integration for Rails that works with Propshaft, not against it. Drop it into an existing jsbundling app for instant CSS HMR, or use the full gem for manifest-based asset resolution.
Vite is the build tool every frontend developer reaches for. But you won't find it in rails new. Vite runs a dev server. Propshaft—Rails' asset pipeline—expects files on disk. For years, these two have refused to share a stage. rails_vite makes this incompatibility …disappear.
A Preflight for Rails Upgrades
Continuations 2026/15: Mustermann bump
Hello from Tainan! We’re just about to head back to Taipei for a last couple of days in Taiwan. It’s been a great trip.
I’ve managed a little time for holiday programming on Decaf Sucks, building out the “write a review” flow. A few firsts for this one: first operation, first validation contract, first cross-container import (making
"search"from the Geocoding slice available as"geocoding.search"inside the Main slice), and a nice little RSpec facility to manage stubbed container keys for feature tests. No code to share yet, but I should have something pushed up in the next week or so.After a couple of iterations, Max pushed up the design for our community page on the new site. This…
Creating software is complicated. It’s hard to figure out exactly what you need to build without a lot of trial and error. It almost always requires both exploring possible options and refining something until it works really well. But those things aren’t the same! Your research prototype is not a good product that people will happily pay for.
Back in the olden days, when software literally came from BigCo R&D departments, we managed to invent Unix, and the mouse, and GUIs, and Ethernet, and TCP/IP, and a ton of other stuff we all use constantly today. Those research divisions didn’t ship viable consumer products, though. Doug Englebart demoed a mouse-driven GUI in 1968, but you couldn’t…
Use Rails Combined Credentials
To deal with secrets and credential handling most Rails apps have ended up with a hotchpotch of ENV.fetch calls and credentials.dig lookups throughout the codebase, depending on where each secret lives.
Rails 8.1 fixes this.
Instead of…
…mixing ENV and credential lookups:
class StripeChargeService
def initialize
@api_key = ENV.fetch("STRIPE_API_KEY")
@webhook_secret = Rails.application.credentials.dig(:stripe, :webhook_secret)
@price_id = ENV.fetch("STRIPE_PRICE_ID") { Rails.application.credentials.dig(:stripe, :price_id) }
end
end
Use…
…the combined credentials API:
class StripeChargeService
def initialize
@api_key = Rails.app.creds.require(:stripe, :api_key)
…MapView: Server-Side Map Rendering for Rails April 12, 2026 After an extensive development journey, MapView has arrived: a powerful API for generating map images directly from your Ruby server. What is MapView? MapView is a Ruby gem that enables you to render maps, routes, points, and polygons with zoom levels ranging from a global world … Continue reading MapView: Server-Side Map Rendering for Rails
✉️ Content Hiatus
This is a copy of the Searls of Wisdom newsletter delivered to subscribers on April 10, 2026.
I've decided to go on a content hiatus. This will be my last dispatch for a while. I don't know how long I'll be gone.
Why? Because I've been posting to an anonymous audience on the Internet almost every day since I was eleven years old. I posted through Bill Clinton's impeachment, 9/11, the Iraq War, the Deepwater Horizon oil spill, the version of Siri that would tell you where to hide a body, binders full of women, and a pandemic that changed everything and then nothing at all.
Very few of my friends live like I do. They aren't pundits. They don't post takes. They lead normal-looking…
If I’ve sent you this, it’s because I will eventually need to give you constructive feedback. Not necessarily right now, but it is going to happen. If I’m your manager I’m going to be giving you feedback fairly regularly because it’s a requirement of my job. And I want to set your mind at ease about it by explaining the process up front, and hopefully showing you that it’s no big deal.
How I Made $360 by Serving Markdown to A.I. agents from My Jekyll Blog
In April 2025 I wrote Apologizing for My Obsessiveness Over Punctuation, a post about my various organizational compulsions. Near the end, almost as an aside, I mentioned that I obsessively categorize expenses in Monarch, a personal finance app, linking it with my referral code. That post earned me exactly one referral in the nine months that followed.
Then, on January 15th, 2026, I wrote Serving Markdown for AI Agents. The idea is simple: for every post on this blog, there’s now a .md version at the same URL. AI agents can discover and fetch clean markdown instead of parsing HTML. I didn’t think much of it.
Exactly thirty days later - the length of Monarch’s free trial — I started…
Before AI coding assistants, a typical engineering team built expertise with the years: new team members joined, contributed small bug fixes, then were given more ambitious tasks over time as they became more comfortable in a codebase, to ultimately become experts. This process took years.
In contrast, today, almost every engineer, and many non-engineers, have access to tools that can gather context from any codebase, and produce a large volume of high-quality code in a day. This lowers the bar for contributing meaningful changes to the software we build and enables many more individuals without domain or codebase expertise with good ideas to see them to light.
At work, I asked my team to…
Human preface: I’m doing a little side project to see for myself how far AI agents have come and what they’re capable of. I’ve basically directed Claude to make a website the generates traffic by any means it sees fit. Below is a little introductory post written by Claude explaining the project and how it’s going at this early stage.
Building a Complete GIS Stack in Rails: ruby-libgd + libgd-gis + map_view April 10, 2026
See the LIVE DEMO in action MapView Render maps directly from your backend no external APIs required. Fast, controlled, and production-ready. Try the demo → Over the past few months I’ve been working on a small GIS-oriented stack in … Continue reading Building a Complete GIS Stack in Rails: ruby-libgd + libgd-gis + map_view
Hi, I’m Emmanuel Hayford. Here’s what caught my eye in Rails this week.
Fix GET+JSON+params in integration tests for API-only apps
params: in integration test helpers was ambiguous for GET requests with as: :json — it wasn’t clear whether params should go in the query string or request body. The original workaround converted GET to POST with X-Http-Method-Override, which broke API-only apps that exclude Rack::MethodOverride. New query: and body: kwargs give explicit control: query: always lands in the URL query string, body: always goes into the encoded request body, and params: keeps its existing behavior unchanged.
get "/search", query: { q: "rails" }, as: :json
post "/search", query: {…Governance, Security Flaws, and AI Tools
This episode of Remote Ruby opens with stories of exhaustion from a sleepless week. Then, Chris, Andrew, and David spend most of the episode unpacking two big themes: trust and governance in open source, and the growing mess of software security and AI-assisted development. They dig into the new Ruby Central write-up on the RubyGems/Bundler fracture and question whether it actually clarifies the path forward, then pivot into the Axios npm compromise, supply-chain risk, and how fragile modern package ecosystems can feel. Then, they go into a wide-ranging discussion on AI coding, bloated production apps, image-performance headaches, CSS/rendering quirks, and why teams may need to rethink…
#795 — April 9, 2026
Ruby Weekly
A Maintainer's Guide to Ruby's Release Cycle — Core team member hsbt explains how Ruby 3.2 and 3.3 are reaching their end, how Ruby versioning works generally, who maintains what, and what terms like ‘security maintenance’ mean in the context of a Ruby version’s lifecycle.
Hiroshi Shibata
Your GitHub Actions workflows, but actually fast — Depot CI runs your existing GitHub Actions YAML — no rewrites needed. Pre-warmed sandboxes so jobs start fast, built-in caching, and SSH into any running job to debug. Migrate your workflows in one command: depot…
Depot sponsor
⚡️ IN BRIEF:
-
Hiroshi…
Webhooks are one of those super simple but really powerful tools that almost every developer has needed to use at least once. From Stripe, GitHub to Postmark. Setting up webhooks is not difficult, but there is quite a bit of boilerplate involved: payload storage, event routing and signature verification. Repetitive. Tedious. Boring. Oh, and did I mention debugging?
Meet Fuik: a Rails engine that catches and stores webhooks from any provider, then gives you a clean way to process them.
👉 If you want to check out the repo and star ⭐ it, that would make my day! 😊

You can install Fuik simply by running bundle add fuik and then run the install generator and migrate the database. Seconds of…
Protecting rubygems.org from the outside in: DoS prevention and compromised passwords
Every gem published to rubygems.org ends up running on someone’s computer. It’s up to rubygems.org to ensure that each gem contains what it claims, that its metadata is well-formed, and that the person who pushed it is who they say they are.
We’ve been chipping away at that. Over the past few months, we shipped two changes that tighten rubygems.org’s defences at very different layers: stronger validation of gem contents at push time, and integration with Have I Been Pwned to catch compromised passwords at login.
What rubygems.org checks when you gem push
A RubyGem is actually just a regular tar file, which contains 3 sections: the code, metadata, and checksums, which you can inspect for…

Evil Martians migrated Wallarm's core event pipeline from NATS to Kafka in two months with zero downtime. Learn how we also handle event deduplication and reconstruct business flows for better understanding of the application.
Wallarm (YC S16) is a series C cybersecurity startup protecting more than 20,000 applications with its API security platform. It sits in front of clients' apps, analyzes every incoming request, and blocks malicious traffic in real time.
When building a SaaS with Rails, I often have more complex logic that spans multiple models and actions. Over time, I’ve settled on two distinct patterns: Form Objects and what I’ll just call classes (or POROs). They serve different purposes, and knowing when to reach for each has made my code easier to reason about and test.
Let me walk you through how I use them both.
Use Form Objects for user input
I use Form Objects when I have a form that a user interacts with directly, and that form needs to create (or update) more than one record. The key is the direct mapping to the form itself.
A Form Object should “quack” like an Active Record model. It validates input, it responds to #save, and…
MapView: Static maps for Rails. No JS. No frontend. Just Ruby. April 7, 2026
See the LIVE DEMO in action MapView Render maps directly from your backend no external APIs required. Fast, controlled, and production-ready. Try the demo → From the creator of ruby-libgd and libgd-gis comes native Rails integration Many of you already … Continue reading MapView: Static maps for Rails. No JS. No frontend. Just Ruby.
4.0.10 Released
RubyGems 4.0.10 includes enhancements and bug fixes and Bundler 4.0.10 includes enhancements and bug fixes.
To update to the latest RubyGems you can run:
gem update --system [--pre]
To update to the latest Bundler you can run:
gem install bundler [--pre]
bundle update --bundler=4.0.10
RubyGems Release Notes
Enhancements:
- Ignore warnings with spec different platforms. Pull request #8508 by hsbt
- Better algorithm for sorting gem version. Pull request #9421 by Edouard-chin
- Update SPDX license list as of 2026-02-20. Pull request #9434 by hsbt
- Installs bundler 4.0.10 as a default gem.
Bug fixes:
- Register native extension files in default spec map. Pull request #9431 by hsbt …
Spoken Latin
Normally this is a programming blog, but here’s something different.
My justification is April Cools’ Club, which henceforth will allow me once a year to write about something completely random (something I’ve done before without knowing it was excusable).
My inspiration was the Spring 2026 Lobsters blog carnival, where participants are provoked to defend the superiority of our favorite language. I accept the challenge, and I step forward to defend the honor of…
Latin.
…One new skill in this release: rails-upgrade.
Why I built this
Seeing the skills for upgrading a Rails app released in the last months with the one from OmbuLabs/FastRuby.io being released last week:
-
OmbuLabs/FastRuby.io: detection patterns, gem compatibility data, upgrade methodology
-
maquina-app/rails-upgrade-skill by Mario Alberto Chávez Cárdenas: breaking changes reference tables, deprecation timeline
I got thinking that maybe it is time for superpowers-rusuperpowers-rubyby to have such a skill.
The workflow
The skill runs a six-step process, but three of those steps are hard gates: the agent cannot proceed past them unless a condition is met.
The first gate is a green test suite.…
When you build a product that uses LLMs and prompts, security becomes a specific kind of hard problem.
Simon Willison described the core risk well in The Lethal Trifecta. When three things combine in a system: access to private data, exposure to untrusted content, and the ability to communicate externally, the situation becomes dangerous.
The reason is structural: LLMs follow instructions in content. That is what makes them useful. It is also what makes them exploitable. An attacker embeds instructions in a document, an email, a webpage, and the model may execute them.
Prompt injection is the number one vulnerability in LLM applications according to OWASP's Top 10 for LLMs. And unlike SQL…
I’m one of the operators of rubygems.org. Here’s what’s been happening over the past week, and a temporary change we’re making as a result.
For the past seven days, rubygems.org has been under sustained bot traffic from many different sources scraping data from every published gem. The volume has been large enough to force the site offline while we respond. The bots are deliberately bypassing the Fastly cache, hitting our origin servers directly.
The primary target has been our language locale pages, the translated versions of rubygems.org. Unfortunately, the locale system wasn’t designed to cache easily through a CDN. To protect site stability, we’re temporarily disabling language…
Your agent’s context window is the most precious resource it has. The more you stuff into it, the worse your agent performs.
Researchers call it context rot: the more tokens in the window, the harder it becomes for the model to follow instructions, retrieve information, and stay on task. Chroma tested 18 frontier models and found that accuracy drops up to 30% when you go from a focused 300-token input to 113k tokens of conversation history, with the task held constant. The model essentially became dumber.
This holds true regardless of how big the window is, yet most agent setups treat the context window like a junk drawer.
“Just toss it in there, the LLM will figure it out!”
MCP: the…

Learn what's new in the world of slow tests and how TestProf continues to help Rails teams to keep CI build times under control.
Behind every release of TestProf is a story about battling a real-world Rails application's test suite slowness. This time, we've picked standout cases from Evil Martians' recent CI performance gig at Whop. Learn what we used to identify and fix them and how this experience shaped TestProf v1.6.0.
JRuby 10.0.5.0 Released
The JRuby community is pleased to announce the release of JRuby 10.0.5.0.
- Homepage: https://www.jruby.org/
- Download: https://www.jruby.org/download
JRuby 10.0.5.x targets Ruby 3.4 compatibility.
Thank you to our contributors this release, you help keep JRuby moving forward! @evaniainbrooks, @kares, @chadlwilson, #jimtng
Compatibility
- Fixed: Two bugs in the JIT compiler that broke certain super calls and defined_method yields. (#8944, #8946, #9310, #9349)
- Fixed: Fiber#raise left the fiber in an resumable state by not correctly transfering control. (#9297, #9356)
- Fixed: Connecting a socket using nonblocking operations failed to complete the establishment of the connection.…
JVM Integration
- Java 26 is officially supported. (#9332)
Pl…
Dear Heroku,
As friends, long time marketplace-partners, supporters, and customers, we here at Judoscale — along with so many others from the developer community — are a bit confused about what’s going on over there in San Francisco. Frustrations aside, we’re having a hard time figuring out what to think about this whole ‘Heroku thing’.
First came the blog post on February 6th that, sort of out of nowhere, announced that:
Heroku is transitioning to a sustaining engineering model focused on stability, security, reliability, and support… with an emphasis on maintaining quality and operational excellence rather than introducing new features…
Enterprise Account contracts will no…
Which, full disclosure, sounds an awful lot like a product going into “Maintenance Mode”, even if that specific phrase isn’t said. Speaking of specific phrases, what exactly is a…
This Week in Rails: Faster Logs, Reliable Parallel Tests, and Key Deprecations April 5, 2026
See the LIVE DEMO in action MapView Render maps directly from your backend no external APIs required. Fast, controlled, and production-ready. Try the demo → A new batch of improvements has landed in the Rails codebase this week, focusing … Continue reading This Week in Rails: Faster Logs, Reliable Parallel Tests, and Key Deprecations
Hi, it’s Vipul. Let’s explore this week’s changes in the Rails codebase.
Remove fast_string_to_time workaround in ActiveModel::Type::Helpers::TimeValue
Ruby 3.2.0 had a bug where Time.new(..., in: "UTC") could return an invalid Time object.
With the minimum supported Ruby now at 3.3.1, the runtime probe and workaround are dead code and have been removed.
Add prepend: true option to ActiveSupport::Notifications.subscribe
A new prepend: true option on ActiveSupport::Notifications.subscribe ensures a subscriber runs before all others
enabling payload mutation before any downstream handler sees it.
ActiveSupport::Cache add a fast path for string keys
Since most cache keys are already…
Easter Eggs
Continuations 2026/14: Taiwan Edition
Welcome to a special 🇹🇼 Taiwan Edition of my weeknotes. We’ll be spending the next couple of weeks here on a family holiday. Right now I am tired (after 24+ hours of travel) but happy and full of delicious food. I aim to keep the weeknotes coming, but I’ll try to keep the next few brief.
This week I finished my rewrite of Hanami Mailer! It’s all merged now and ready for testing as a standalone system. The next step here is to get the integration with full Hanami apps happening.
We had a good question come into our chat about how Hanami CLI calls the Postgres CLI tools for its
dbcommands (tl;dr, nothing special, you just need them on your$PATH). It eventually got onto the topic of how…
Frequently Played 🔗
I tend to listen to the same songs or albums on repeat that are evocative of how I’m feeling or what’s going on with me. Here is what I’m currently listening to over, and over, and over, and over, again.
Witch Dance 🔗
Grief, perseverance, the search for community, the desire for answers.
And I met every monster from the bar to Broadway
And all their violent offers, I just turn them away
And your threats and your promises, they don’t scare me
After all, there’s nobody more monstrous than me
Opening of The Land Of Hope And Dreams American Tour 🔗
I finally watched Deliver Me From Nowhere. My recommendation? Read the book. Or, better, listen to Nebraska.
The mighty E Street…
Ruby is a programming language created for the happiness of the programmer, but apparently this happiness did not account for the installation process of the language itself. If you go to the official language page, you will find a list of solutions to install and manage Ruby versions. But almost all of them have one problem: you have to compile the version locally, and the time it takes will depend on how fast your CPU is.
Now that is changing; a new tool called rv has emerged. It is described as “an extremely fast way to manage your Ruby versions and gems”. In this post, I want to explain a bit how it works, why it is so fast compared to previous solutions, how you can use it to install…
Memcached Mayhem
On this episode, Chris, Andrew, and David bounce from Ruby and Rails security updates into the messy realities of caching, UI architecture, and browser support. They break down the latest Zlib-related Ruby CVE, Dalli updates, Rails security and bugfix releases, and what maintenance windows mean in practice. Then, they swap stories about Redis, Memcached, observations about GitHub’s reliability amid massive Claude attributed code activity, and the kinds of performance problems that only show up at scale. The episode closes with a thoughtful Rails frontend discussion covering nested layouts, active sidebar links, CSS-powered empty states, pagination behavior, popovers, anchor positioning, and…
Last week, three members of Ruby Central’s board published a new statement about RubyGems and Bundler, and this week they published an incident report on the events last year. The first statement reports that Ruby Central has now completed a third audit of RubyGems.org’s infrastructure: first by the sole remaining RubyGems.org maintainer, the second by Cloud Security Partners, and the third by Hogan Lovells.
In all three cases, Ruby Central found no evidence of compromised end user data, accounts, gems, or infrastructure availability. I hope this can conclusively put to rest the idea that I have any remaining access to the RubyGems.org production systems, or that I caused any harm to the…
I also appreciate that Ruby Central is taking its share…
#794 — April 2, 2026
Ruby Weekly
The 'RubyGems Fracture' Incident Report — A postmortem of the Ruby Central vs Bundler story in late 2025 which resulted in the Ruby core team taking stewardship of RubyGems and Bundler. The timeline of events is laid out in detail, but it’s unlikely to resolve the matter entirely (as demonstrated in this Reddit comment by Mike Perham).
Richard Schneeman (Ruby Central)
💡 The Register also has a good independent take on this update factoring in some of the responses to it.
How a Solo SaaS Founder Stopped Worrying About Rails Maintenance — "FastRuby.io is…
This article is taken from the book JavaScript for Rails Developers (use ONE-YEAR-OLD to get 25% discount; valid until 2025-04-09 🥳). It is a book I published about a year ago. Over that period, many hundreds bought the book. It is written for Ruby/Rails developers to make JavaScript your 2nd favourite language.
I always get a little excited when I see a good refactoring happen. So I want to share this article; it is one of the last chapters where I go over an exisintg part of the code that is created in the book to refactor it with the goal to make it:
- more readable;
- easier to understand at a glance.
This is the current code it started with:
import { Annotation, Transaction } from "@code…Basic role management
Believe it or not, I don’t only work on or write about SQLite, and today I want to share a simple pattern for role management in Rails inspired by the rolify gem. I have been using this setup in the Rails app I am currently working on, and it has been a lovely experience. I’ve also had to evolve the pattern a bit recently, so I thought now was a great time to share the current state of things. Let’s jump into it!
The pattern works with 3 core models and then any number of related models. The core models are (you guessed it) User, Role, and UserRole. The User model represents, well, a user of your application. The Role model is a role that a user can have. The UserRole model is the join…
N+1 Driven Development
htmx Configuration
Often, you’ll want to customize the default htmx configuration. There are a couple ways you can do this:
-
Globally.
-
Per page.
We’ll discuss each including how you can make short order of these configuration changes in your Ruby applications. For the purposes of this discussion, we’ll use Hanami as our web application but what you see here can be applied to your specific web stack.
With the above in mind, let’s get started by first setting up our htmx provider.
Provider
As documented in Hanami Containers, the best way to have access to the HTMX gem is to implement a corresponding provider. Here’s…
…We analyzed 1,140 devtools funding rounds—here's who's writing checks and why

We analyzed 1,140 early-stage funding rounds in developer tools, cybersecurity, and infrastructure from January 2025 through March 2026. Here are the top VCs and investors writing checks, the metrics that got companies funded, and the exact person to email based on what you're building.
In other places, founder dreams might include sports cars or fancy watches, but here in San Francisco, every devtools founder wants one thing: to be on a bus. Specifically, their logo painted on a Muni line crossing Market Street. If you're on a Muni, you've made it, like Modal, Blacksmith, Posthog, Hex. Another way to…
Rails apps have layers but no modules
You can have 200 models and zero modules. That’s the problem with typical Rails conventions. Rails supports layers - models, views, controllers. But layers are not modules. Within one layer - especially models - usually all is mixed together. There are no boundaries.
Order.first.user.invoices.last.line_items
Such code is not so uncommon. It crosses 4 business boundaries. In just 1 line of code. All thanks to associations.
The problem with associations
One of the first thing we teach in Rails is associations.
class Order < ApplicationRecord
belongs_to :user
end
It’s very readable, feels right. Allows us to call it like this:
Order.first.user
Then…
When Search Breaks Everything: Lessons from a Client's Unexpected App Outage
Judoscale ‘On Tour’ Series
- “The Friction Model” & Heroku (This page!)
- Render (Coming soon…)
- Railway (Coming soon…)
- Fly (Coming soon…)
- Northflank (Coming soon…)
- Digital Ocean (Coming soon…)
- Amazon ECS Fargate (Coming soon…)
Thus we begin our tour! As we mentioned in our last post, we’re going to take our production app on a hosting tour to fully experience what each option in today’s hosting marketplace looks like, feels like, and runs like. But before we do any of that, we need a baseline and a strategy.
Judoscale has been on Heroku since its origins ten years ago. Adam, Judoscale’s founder, has been using Heroku since it was a first-days startup! All that to say,…
Last year, I announced plans to rewrite this blog in Ruby on Rails. It was hosted on Ghost for all these years (which is built with Node.js), and the idea was to rebuild it from scratch in Rails and write about the process as I went along. I even published a few posts as I started development.
However, as you may have noticed, I haven't published consistently for the past six to eight months. What's more, for the last two months, I haven't even written a single post.
Part of the reason is AI, and the proliferation of AI-generated writing everywhere which completely killed my motivation to write. Why spend hours and even days writing a detailed technical blog post when Claude or…
This is a copy of the canonical report I published on RubyCentral’s site. I recommend reading there for the most updated copy. This document attempts to give closure to the Ruby community about the events that led to the incident, September 10-18, 2025, which I’ve named “RubyGems Fracture.”
Preamble
I joined Ruby Central’s Open Source Committee on October 22nd, 2025, after the GitHub access changes. I was adamant internally and externally from day one about performing a retrospective to try to wrap my head around the full, true picture of what happened and why.
In the pursuit of this task, I’ve spent 20+ hours interviewing and chasing up leads, easily quadrupling that time…
RubyGems Fracture Incident Report
By: Richard Schneeman
This document attempts to give closure to the Ruby community about the events that led to the incident, September 10-18, 2025, which I’ve named “RubyGems Fracture.”
Preamble
I joined Ruby Central’s Open Source Committee on October 22nd, 2025, after the GitHub access changes. I was adamant internally and externally from day one about performing a retrospective to try to wrap my head around the full, true picture of what happened and why.
In the pursuit of this task, I’ve spent 20+ hours interviewing and chasing up leads, easily quadrupling that time spent reviewing other artifacts such as chats and raw GitHub access logs. For any fact learned verbally, I’ve…
A new way to decouple code since Rails 8.1.

There are these moments where you feel stuck between the devil and the deep blue sea. Two possible solutions, neither quite up to the job.
Let’s start with a simple example that illustrates what we’re competing against. You are implementing an e-commerce solution that sells digital products. After a purchase is placed, a few things need to happen: send a confirmation email, track the event in your analytics, and ping your team on Slack. Your first pass looks something like this:
def create
@order = Order.create!(order_params)
OrderMailer.confirmation(@order).deliver_later
Ahoy::Event.create!(name: "order.created", properties: {…Configuring monitors in Hyprland means writing monitor= lines by hand. A 4K display at 1.33x scale is effectively 2880x1620 pixels, so the monitor next to it needs to start at x=2880. Vertically centering a 1080p panel against it means doing division in your head to get the y-offset right. You reload, you’re off by 40 pixels, you edit, you reload again. There’s no visual feedback until after you’ve committed to a config.
Then it gets worse. You unplug your laptop, go to a conference, plug into a projector, and you’re back to editing config files backstage before your talk. You come home, dock the laptop, and the layout is wrong again.
I looked at what was available. The closest to what I…
Haggis Ruby returns to Glasgow on April 23-24, and thoughtbot will be there.
Rob Whittaker and Mina Slater are attending, and Aji Slater is speaking. Their talk is about playfulness in exploration when tackling novel challenges. What is the challenge in this case? Using Ruby for procedural generation of an endless haunted house.
Haggis Ruby is one of the smaller Ruby conferences, and that’s part of what makes it good. The conversations are better when the room is smaller. If you’re in or around Glasgow in late April, it’s worth the trip.
We’re looking forward to it. If you’re going, find us.
If you enjoyed this post, you might also like:
Ruby Argentina March meetup
Ruby Argentina opened its 2026 meetup season at Eryx’s office in Buenos Aires, and the night set the tone quickly: pay attention to Ruby’s warnings, then make room for a few lightning talks.
The event kicked off with Ariel Juodziukynas’ talk “Warnings en Ruby: NO LOS IGNORES!!!”. Ariel focused on an easy part of everyday Ruby work to ignore: warnings. His talk was a reminder that the yellow text in our terminal often points to real problems. He showed practical examples of common warnings and how to fix them.
After Ariel’s talk, we took a break to catch up, meet new people, and keep the conversations going over drinks and empanadas.
The lightning talks took the night in a looser…
I joined Jared again on the Dead Code Podcast to go a bit deeper on my post, The Death of a Software Craftsman. The outlook is kinda bleak, but plenty of digs at agile software practices :)

NestJS is code-first by default meaning decorators describe your API, and the spec is generated from code. But decorators don't enforce anything at compile time. This post shows how to flip the flow to generate controller method types from an OpenAPI spec and let TypeScript catch contract drift before reaching production.
NestJS defaults to code-first: you write controllers, decorate them, and generate the spec from code. The spec is a byproduct. But those decorators are runtime metadata, so TypeScript doesn't check them against your actual return types. This article flips the flow. We…
CVE-2026-33946 (mcp): MCP Ruby SDK - Insufficient Session Binding Allows SSE Stream Hijacking via Session ID Replay
CVE-2026-34060 (ruby-lsp): Ruby LSP has arbitrary code execution through branch setting
Welcome to Hotwire Weekly!
Welcome to another issue of Hotwire Weekly! Happy reading! 🚀✨
📚 Articles, Tutorials, and Videos
Add to Calendar Bridge Component for Hotwire Native - Mike Dalton walks through building a Hotwire Native bridge component that triggers native calendar APIs from a Rails view, using iOS EventKit to present an EKEventEditViewController and an Android Intent to open the device calendar app.
Build custom emojis with Stimulus - Rails Designer shows how to build an interactive emoji composer using HTML Canvas and Stimulus. Click face emojis, add accessories, drag them into position, and export the creation as an image, all in the browser with no external dependencies.
Check it out, Jessitron and I are podcasting again! You can catch the first episode, and find links to subscribe, on Graceful.Dev: “I’ve often wished I could fork myself…”
ruby-libgd: The Modern Ruby Image Library You've Been Sleeping On March 30, 2026 Reading time: 8 minutes Status: Benchmark-driven, production-ready Executive Summary After extensive benchmarking against RMagick, ChunkyPNG, and ruby-vips, ruby-libgd demonstrates overwhelming superiority in drawing operations (28x faster), pixel access (2.6x faster), sepia filtering (2.5x faster), and memory efficiency (3.7x less RAM). But speed … Continue reading ruby-libgd: The Modern Ruby Image Library You’ve Been Sleeping On
Another good week of closing parentheses. Merged the new Hanami Minitest. Added --test=minitest support to
hanami new. Merged undecorated exposures for views, along with some fixed tests to go along with it.Looped back to my earlier work on Hanami Action doing body parsing, and adjusted it to parse multipart bodies when there is no explicit format configured, which preserves the no-config support for multipart parsing we introduced in Hanami 2.3. This allowed me to remove the body parsing middleware from default Hanami apps. Begone, awkward solution! I also removed the deprecated action format config from the pre-2.3 era. Cleaning up!
The biggest parenthesis yet to close is the new…
English has plenty of irregular plurals. Criterion becomes criteria, not criterions. Rails handles many common ones already, but your domain might include words it doesn’t know about.
Instead of…
…accepting Rails’s best guess at a plural:
"criterion".pluralize #=> "criterions"
"matrix".pluralize #=> "matrices" # this one Rails knows!
Use…
…inflect.irregular to teach Rails the correct pair:
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular "criterion", "criteria"
end
Now:
"criterion".pluralize #=> "criteria"
"criteria".singularize #=> "criterion"
Why?
Give irregular the singular and plural forms and Rails…
I noticed I kept switching between planning skills mid-session. One skill had the best forcing questions. Another had the best implementation structure. A third had the best review discipline. Also I think I have too many plugin collections and each seem to have a planning skill somehow.
So I analyzed 48+ planning skills across five repositories and combined the strongest elements into one flow. That is superplanning.
The problem with using multiple planning skills
When I started using Claude Code for serious product work, I had at least five planning-related skills available: ce:brainstorm for requirements, ce:plan-beta for implementation units, office-hours for pressure-testing ideas, pla…
Measuring Memory for Ruby Methods
When a process uses more memory than expected, you need to know which method is
responsible. ObjectSpace.memsize_of_all gives you a before/after delta.
The Pattern
require 'objspace'
GC.start
before = ObjectSpace.memsize_of_all
# ... run method here ...
after = ObjectSpace.memsize_of_all
puts "mem delta: #{((after - before) / 1024.0 / 1024.0).round(2)} MB"
GC.start forces a garbage collection cycle before measuring so prior
allocations don’t skew the result.
A Real Example
Two approaches to build a list of 50,000 user records. Save as measure_memory.rb:
require 'objspace'
# old approach - full AR objects with map
GC.start
before = ObjectSpace.memsize_of_all
scope = User.where.not(c…Over the past several months, there has been significant discussion, disagreement, and concern about RubyGems, Bundler, and Ruby Central’s role in stewarding RubyGems and supporting the Ruby ecosystem.
Because this matter has involved ongoing legal discussions, we have been limited in what we could say publicly. Our priority has been to resolve the situation responsibly and avoid escalating a conflict that affects the broader Ruby ecosystem.
With several new board members joining Ruby Central in recent months, it has also taken time to come up to speed on a complicated situation and begin charting a path forward.
Ruby Central’s actions during this period were taken in response to a breakdown…
Using Perfetto in ZJIT
Look! A trace of slow events in a benchmark! Hover over the image to see it get bigger.
img.hover-zoom:hover { transform: scale(2); transition: transform 0.1s ease-in; } img.hover-zoom:not(:hover) { transition: transform 0.1s ease-out; }
A sneak preview of what the trace looks like.
Now read on to see what the slow events are and how we got this pretty picture.
The rules
The first rule of just-in-time compilers is: you stay in JIT code. The second rule of JIT is: you STAY in JIT code!
When control leaves the compiled code to run in the interpreter—what the ZJIT team calls either a “side-exit” or a “deopt”, depending on who you talk to—things slow down. In a well-tuned…
For more than 8 years, we have been publishing detailed guides on how to upgrade Rails applications.
We have documented every minor version from Rails 2.3 through 8.1 in our Rails Upgrade Series and distilled our methodology into an ebook: The Complete Guide to Upgrade Rails

All of that knowledge comes from more than 60,000 developer-hours of hands-on upgrade work for companies of all sizes, from solo-founded SaaS products to huge Rails monoliths running at Fortune 500 public companies.
Today, we are making that methodology available to everyone as an open source Claude Code Skill: claude-code_rails-upgrade-skill.
Why a Claude Code Skill?
Claude Code is a powerful AI assistant for…
Conferences, AI Trends, and Sleepless Nights
Chris, Andrew, and David catch up on health, sleep deprivation, and the new Invincible season and Fallout. David shares some RubyConf CFP submissions news and this year’s broad conference themes. They discuss Andrew finishing difficult authentication work, touching on OAuth/SSO complexity and pricing, the idea of products built more for bots than humans, and where AI is proving useful, especially for debugging and research. The conversation eventually widens into a more skeptical look at the AI industry itself, touching on scraped code, deepfakes, surveillance, lobbying, and whether the promised productivity gains really match reality. Hit download now!
Links
Hi, it’s zzak. Let’s explore this week’s changes in the Rails codebase.
New Rails releases this week
Rails 7.2.3.1, 8.0.4.1, and 8.1.2.1 shipped as security releases, followed by 8.0.5 and 8.1.3 bugfix releases the next day.
Combine per-validator and top-level :if/:unless/:on in validates
validates now combines top-level and per-validator :if, :unless, and :on options instead of letting the inner options silently win.
validates :title, presence: { if: :local? }, if: :global?
# both conditions are now applied
Fix titleize to capitalize unicode lowercase letters
titleize now capitalizes Unicode lowercase letters as well as ASCII, so titleize("über ñoño") becomes Über Ñoño.
Late 2024 I published Rails Icons 1.0 (slighly off-topic, but I mentioned a modest few thousand downloads in that article; now it is close to 250k; I expect the same + a bit more for Perron). Today I like to re-introduce Rails Icons again to you: here is version 1.8.
(I did not expect SVG icons could be this exciting; and I have a few more ideas still! 🤯)
First I extracted the sync and SVG creation logic (the bit people have copy-pasted instead of using/contributing to the gem) into its own gem: Icons, I wrote about it here. The main goal was to make the “behind-the-scenes” architecture (syncing, normalizing icon names, etc.) available for others to build a similar gem for their framework…
Ruby 3.2.11 Released
Ruby 3.2.11 has been released. This release includes an update to the zlib gem addressing CVE-2026-27820.
Please see the GitHub releases for further details.
This is the final release of the Ruby 3.2 series. We will not provide any further updates, including security fixes, for the Ruby 3.2 series.
We recommend upgrading to Ruby 3.4 or 4.0.
Download
-
https://cache.ruby-lang.org/pub/ruby/3.2/ruby-3.2.11.tar.gz
SIZE: 19984344 SHA1: 9534a3aa08d2ccb4d3c50b1301b2da9a9b91c4ab SHA256: b3eeabd6636f334531db3ffdc3229eb05e524740e6c84fdc043720573cf2f8b2 SHA512:…
Worth the Squeeze
How Agentic Workflows Make Large-Scale Refactors Justifiable
Every mature codebase carries its history in the code. Patterns that were once best practice become deprecated. Constructs that were convenient when the project was small become performance bottlenecks at scale. As engineers, we see these opportunities for improvement all the time. We know exactly what should change. And yet, the question we keep coming back to is always the same: “Is it worth the squeeze?”
I’ve asked myself this question more times than I can count. The math rarely worked out. Hundreds of instances scattered across dozens of teams,…
CVE-2026-33658 (activestorage): Rails Active Storage has a possible DoS vulnerability in proxy mode via multi-range requests
#793 — March 26, 2026
Ruby Weekly
How to Install a Gem (It's Harder Than It Sounds) — As one of the people behind Bundler 1.0 and a former maintainer of RubyGems.org, and now working on gem.coop and rv, André knows a few things about how gems tick (big understatement). This post is full of ‘aha’ moments as he walks through installing a gem by hand, giving us an idea of what tools like gem and rv do for us.
André Arko
A Solo Founder Story: 'I Got Fed Up Chasing Contractors' — Tim tried hiring and outsourcing, but nothing fit. Then he found Bonsai. Now he gets reliable monthly Rails…
RubyMine 2026.1 is here! This release brings a range of improvements aimed at making Ruby and Rails development faster and more enjoyable.
You can get the new build from our website or via the free Toolbox App.
Let’s take a look at the highlights of this release.
AI
RubyMine continues to evolve as an open platform that lets you bring your preferred AI tools directly into your development workflow. With RubyMine 2026.1, working with multiple AI agents and integrating them into your IDE experience is now easier than ever.
Use more AI agents in RubyMine
In addition to Junie and Claude Agent, you can now choose more agents in the AI chat, including Codex. Additionally, C…
Ruby 3.3.11 Released
Ruby 3.3.11 has been released. This release includes an update to the zlib gem addressing CVE-2026-27820, along with some bug fixes.
Please see the GitHub releases for further details.
This is the last release of normal maintenance for the Ruby 3.3 series. After this release, Ruby 3.3 enters a security maintenance phase. During this phase, we will only backport security fixes and fixes for critical build issues, without any regular bug fixes.
The security maintenance phase is scheduled to last for one year, until the end of March 2027. At that point, official support for Ruby 3.3 will end. We recommend that you begin planning your migration to Ruby 3.4 or 4.0.
Download
March 25, 2026 Published on RubyStackNews Ruby is a high-level language. C is a low-level language. At some point, every serious Ruby application needs to cross that boundary. Maybe you need a cryptography library. Maybe a signal processing engine. Maybe a hardware interface. Maybe raw performance on a hot path. There are two ways to … Continue reading FFI: How Ruby Talks to C
Avo 4 Open Beta
CVE-2026-33635 (icalendar): iCalendar has ICS injection via unsanitized URI property values
Here are some additions I did for superpowers-ruby collection of plugins and skills. A fork from the well known superpowers plugin where I added some skills from compound-engineering-plugin which I think you should install it as it is.
The compound skill
I found that the compound skill from the folks at Every solves the problem of redisovering the same solution in various forms. The idea is simple: right after you and your agent fix something - while the context is still fresh - you capture what you actually did into a structured learning doc in docs/solutions/.
Next time you hit the same class of problem, the agent learns and uses it.
I think this is one of the most useful skills to add to…
How to Install a Gem
This post was originally given as a talk at SF Ruby Meetup. The slides are also available.
It’s more complicated than it sounds
Hello, and welcome to How To Install A Gem. My name is André Arko, and I go by @indirect on all the internet services. You might know me from being 1/3 of the team that shipped Bundler 1.0, or perhaps the 10+ years I spent trying to keep RubyGems.org up and running for everyone to use.
More recently, I’ve been working on new projects: rv, a CLI to install Ruby versions and gems at unprecedented speeds, and gem.coop, a community gem server designed from the ground up so Bundler and rv can install gems faster and more securely than ever before.
So, with that…
4.0.9 Released
RubyGems 4.0.9 includes enhancements, bug fixes and documentation and Bundler 4.0.9 includes enhancements and bug fixes.
To update to the latest RubyGems you can run:
gem update --system [--pre]
To update to the latest Bundler you can run:
gem install bundler [--pre]
bundle update --bundler=4.0.9
RubyGems Release Notes
Enhancements:
- Fix: include owner role in
gem owner. Pull request #9403 by gjtorikian - Installs bundler 4.0.9 as a default gem.
Bug fixes:
- Fix: Ensure trailing slash is added to source URIs added via gem sources. Pull request #9055 by zirni
Documentation:
- [DOC] Fix link. Pull request #9409 by BurdetteLamar
Bundler Release Notes
Enhancements:
- Che…
I joined Jared again on the Dead Code Podcast to go a bit deeper on my post, The Death of a Software Craftsman. The outlook is kinda bleak, but plenty of digs at agile software practices :)
Hello again everyone! Long time no see 😆.
Rails Versions 8.0.5 and 8.1.3 have been released! These are regular bugfix releases.
These also include the changes from yesterday’s security releases, so if you haven’t upgraded yet you’ll get those fixes too.
The Rails 8.1 series will continue receiving bug fixes until October 2026. The 8.0 series will change to only receiving security updates in May next month, so this might be the last bug fix release in that series. See our Maintenance policy for more information.
CHANGES since 8.1.2
To see a summary of changes, please read the release on GitHub:
8.1.3 CHANGELOG To view the changes for each gem, please read the changelogs on GitHub:
GHSA-46fp-8f5p-pf2m (loofah): Improper detection of disallowed URIs by Loofah `allowed_uri?`

The final report for Ruby Association Grant on TutorialKit.rb—a toolkit for building interactive Ruby and Rails tutorials that run entirely in the browser using WebAssembly and WebContainers. Featuring a full-featured installer, agent-friendly development workflow, deployment pipelines, HTTP support, and real-world examples.
TutorialKit.rb, a toolkit for building interactive Ruby and Rails tutorials that run entirely in the browser, has reached the release candidate stage and is ready for general…

How do you measure product-market fit for a developer tool? A PMF scoring model from Evil Martians—a product development consultancy for developer tools startups—built on data from 37 devtools companies across AI, infrastructure, and cybersecurity. Five metrics, real benchmarks, and a dual score that tells you whether to invest in product or go-to-market.
Everyone talks about product-market fit. But what does it actually mean for a developer tools startup? "Are we close?" "Getting closer?" "What should we focus on to get closer?" At Evil Martians, we've spent nearly 20 years working with devtools companies—from…
CVE-2026-33306 (bcrypt): bcrypt-ruby has an Integer Overflow that Causes Zero Key-Strengthening Iterations at Cost=31 on JRuby
CVE-2026-33286 (graphiti): Graphiti Affected by Arbitrary Method Execution via Unvalidated Relationship Names
Supercharge Your Ruby on Rails Forms With Form Builders and Form Objects
Custom form helpers and builders can help reduce fragmentation if every developer in the team solves the same problem differently.

Have you come across instances where inside your Rails forms you need to fall back to plain input tags, like this form using a honeypot to prevent spam signups?
<%= form_with model: @signup do |f| %>
<%= f.email_field :email %>
<input type="hidden" name="utm_source" value="<%= params[:utm_source] %>">
<!-- Honeypot: should stay blank -->
<div class="hp" aria-hidden="true">
<label for="signup_company">Company</label>
<input type="text" id="signup_company" name="company" tabindex="-1" autocomplete="off">
</div>
<% end…Comb Shaped Slices
A friend who’s built and shut down companies in this space sat across from me at breakfast during a conference recently. He knows what I’m building: Chat with Work, an AI tool that lets you talk to your actual work data. He wanted to know what my plan was. I think he was a bit concerned.
“Add more integrations, finish the security assessment, market it well.” I said.
That didn’t help. “All those LLM providers are going to eat the whole market. They’ll ship every integration you can think of. If you want a slice of the pie, you need to pick a vertical and own it.”
I told him I was going to grab a T shaped slice of the pie instead.
He looked at me like I’d lost it.
Here’s the thing…
Although Devise is a fantastic authentication library, I’ve been reaching for Rails’s built in authentication generator since it was introduced in Rails 8. Almost all of my hobby apps are for a single user (me!) so I don’t really need all the features of devise.
Recently, I finally removed devise from an old project and replaced it with the generated authentication code. This turned out to be far easier than expected. Here are my notes:
Run the generator
The first thing to do is to run the generator:
rails generate authentication
This creates a bunch of files and overwrites some of our existing code, especially the User model. (Here’s an excellent walkthrough of the generated code.)
…
Hi friends!
Rails Versions 7.2.3.1, 8.0.4.1, and 8.1.2.1 have been released!
These are security patches addressing 10 security issues:
- An issue where in development mode, an exception could be printed without escaping. This could affect a developer running a server locally and clicking a malicious URL.
- Multiple potential XSS vulnerabilities in Action Pack, Action View, and Active Support
- Two potential DoS vulnerabilities in Active Storage related to range requests
- Two potential DoS vulnerabilities in Active Support related to number formatting
- A potential path traversal and glob injection vulnerability in Active Storage DiskService
- Insufficient filtering of metadata in…
We strongly recommend upgrading as soon as possible.
Older versions of Rails are unsupported, and users are recommended to upgrade to at least the 7.2 series. See our maintenance policy for details.
Here is a list of security issues that these releases address:
The Devtools PMF Compass

How do you measure product-market fit for a developer tool? A PMF scoring model from Evil Martians—a product development consultancy for developer tools startups—built on data from 37 devtools companies across AI, infrastructure, and cybersecurity. Five metrics, real benchmarks, and a dual score that tells you whether to invest in product or go-to-market.
Everyone talks about product-market fit. But what does it actually mean for a developer tools startup? "Are we close?" "Getting closer?" "What should we focus on to get closer?" At Evil Martians, we've spent nearly 20 years working with devtools companies—from…
Some English words don’t have a separate plural form. “Staff” is staff, “metadata” is metadata, “feedback” is feedback. Rails doesn’t always know this—it will happily generate a staffs table or a metadatas route if you let it.
Instead of…
…fighting Rails when it pluralises words that shouldn’t change:
"staff".pluralize #=> "staffs"
"metadata".pluralize #=> "metadatas"
"feedback".pluralize #=> "feedbacks"
Use…
…inflect.uncountable to tell Rails these words stay the same:
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.uncountable %w[staff metadata feedback]
end
Now:
"staff".pluralize #=> "staff"
"metadata".pluralize #=>…


