
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…
Authors: Svyatoslav Kryukov, Backend Engineer, and Travis Turner, Tech Editor
Topics: Rails, DX, Open Source, Vite, JavaScript, React

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.
Why understanding the dependency, execution, and behavioral surfaces of a Rails system makes upgrades more predictable.
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…
Late last year, the Aha! Develop team added support for team line-level reporting. During a team demo in the run-up to the release, we discovered one of our internal sprint reports was taking 15 minutes to load, almost freezing the browser in the p
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…
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 →
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.
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 Over the past few months I’ve been working on a small GIS-oriented stack in Ruby, focused on a simple goal: rendering maps from GeoJSON directly on the server. It started at a low level, building bindings around libgd: ruby-libgd (MIT) … 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: {…
Add…
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…
We deployed an existing Laravel application using Docker and Kamal 2 without touching the app. Here's what worked, what didn't, and what we'd do differently.
Continue Reading
#795 — April 9, 2026
Read on the Web
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:
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…
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…
Authors: Camila Mirabal, Tech writer, and Travis Turner, Tech Editor
Topics: Case Study, DX, Infrastructure, Ruby on Rails

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.
pseudo, adjective: being apparently rather than actually as stated CSS pseudo-classes are like regular classes in that they can be used to select DOM elements. They’re unlike regular classes in that you can’t see them in the HTML. They select elements dynamically, based on their own rules. This is what makes them powerful. I really like them because they let me remove dynamic presentation lo...
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 From the creator of ruby-libgd and libgd-gis comes native Rails integration Many of you already know ruby-libgd – the gem that brings GD graphics power to Ruby. Many of you already know libgd-gis – the GIS rendering layer built on top … Continue reading MapView: Static maps for Rails. No JS. No frontend. Just Ruby. →
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
…
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:
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…
Authors: Vladimir Dementyev, Principal Backend Engineer, and Travis Turner, Tech Editor
Topics: Performance, Rails, Open Source, Performance & scale

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.
The JRuby community is pleased to announce the release of JRuby 10.0.5.0.
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 A new batch of improvements has landed in the Rails codebase this week, focusing on performance refinements, testing reliability, and cleaning up legacy configuration options. Here is what you need to know. The Headline Change: No More Slow SQL Logs … 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 are often ways that developers can have fun by hiding little gems in the code base or provide additional fun without affecting the function of the application. In this episode, we'll explore some of the little easter eggs in the Rails code base.
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 db commands (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.
Full Lyrics
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…
This post explores how dynamic dispatch and ActiveSupport's runtime constant resolution can make Rails code elegant but harder to maintain.
The structural signals that make Rails upgrades hard before the upgrade work even begins.
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…
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…
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…
In this episode, we look at how we can modify our application from a performance aspect to increase our job security. We'll slow down our application to a still usable level, but then swoop in months later and become the hero.
Often, you’ll want to customize the default htmx configuration. There are a couple ways you can do this:
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…
…
Authors: Irina Nazarova, CEO, and Travis Turner, Tech Editor
Topic: Developer Community

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:
Then…
Issues stemming from one tool had major ripple effects across our client's entire app. Here's how we approached it
Continue Reading
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…
We recently introduced Aha! Builder, our new AI-powered product for creating prototypes and business applications. It allows you to describe the app you need, and Elle (our AI assistant) builds it for you. But Elle is not just a UI trick. When a us
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 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 :)
Authors: Yuri Mikhin, Frontend Engineer, and Travis Turner, Tech Editor
Topics: DX, TypeScript, Node.js

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…
### Summary
The Ruby SDK's [streamable_http_transport.rb](https://github.com/modelcontextprotocol/ruby-sdk/blob/main/lib/mcp/server/transports/streamable_http_transport.rb)
implementation contains a session hijacking vulnerability. An attacker
who obtains a valid session ID can completely hijack the victim's
Server-Sent Events (SSE) stream and intercept all real-time data.
### Details
**Root Cause**
The StreamableHTTPTransport implementation stores only one SSE stream
object per session ID and lacks:
- Session-to-user identity binding
- Ownership validation when establishing SSE connections
- Protection against multiple simultaneous connections to the same session
### Impact
While…
## Summary
The `rubyLsp.branch` VS Code workspace setting was interpolated without
sanitization into a generated Gemfile, allowing arbitrary Ruby code
execution when a user opens a project containing a malicious
`.vscode/settings.json`.
Other editors that support workspace setting that get automatically
applied upon opening the editor and trusting the workspace are also
impacted since the server is the component that performs the interpolation.
## Details
The `branch` CLI argument passed to the `ruby-lsp` server was
interpolated in the generated `.ruby-lsp/Gemfile` without sanitization.
Editors that allow defining settings saved at the workspace level
(e.g.: `.vscode/settings.json`)…
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.
Sp…
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 →
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…
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…
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.
Classify…
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 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
How Agentic Workflows Make Large-Scale Refactors Justifiable

Before solving a Rubik cube, a person thinks about the different steps to solve it
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,…
## Impact
Active Storage’s proxy controller does not limit the number of byte
ranges in an HTTP Range header. A request with thousands of small
ranges causes disproportionate CPU usage compared to a normal
request for the same file, possibly resulting in a DoS vulnerability.
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 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 →
AI is moving fast, but good decisions still take time. Our developer, Evaldo Klock, shares what stood out at his first Laracon.
Continue Reading
The Avo 4 Open Beta is here. Try the new UI4 visual style, new features like Collaboration, Forms, Kanban, HTTP Resources, REST API, and Reactive Fields — plus a comprehensive upgrade guide to help you migrate from Avo 3.
### Summary
.ics serialization does not properly sanitize URI property values,
enabling ICS injection through attacker-controlled input, adding
arbitrary calendar lines to the output.
### Details
`Icalendar::Values::Uri` falls back to the raw input string when
`URI.parse` fails and later serializes it with `value.to_s` without
removing or escaping `\r` or `\n` characters. That value is embedded
directly into the final ICS line by the normal serializer, so a
payload containing CRLF can terminate the original property and
create a new ICS property or component. (It looks like you can
inject via url, source, image, organizer, attach, attendee,
conference, tzurl because of this)
Relevant…
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…
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…
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:
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:
## Description
A reflected cross-site scripting (XSS) vulnerability exists in
the `return_to` query parameter used in the avo interface.
An attacker can craft a malicious URL that injects arbitrary
JavaScript, which is executed when he clicks a dynamically
generated navigation button.
## Impact
This vulnerability may allow execution of arbitrary JavaScript
in the context of the application.
Impact varies depending on deployment:
- In unauthenticated setups: exploitable via crafted links sent to users.
- In authenticated setups: limited to authenticated users and
requires interaction.
## Summary
`Loofah::HTML5::Scrub.allowed_uri?` does not correctly reject
`javascript:` URIs when the scheme is split by HTML entity-encoded
control characters such as `
` (carriage return), `
`
(line feed), or ` ` (tab).
## Details
The `allowed_uri?` method strips literal control characters before
decoding HTML entities. Payloads like `java
script:alert(1)`
survive the control character strip, then `
` is decoded to
a carriage return, producing `java\rscript:alert(1)`.
Note that the Loofah sanitizer's default `sanitize()` path is
**not affected** because Nokogiri decodes HTML entities during
parsing before Loofah evaluates the URI protocol. This issue only
affects direct callers of the…
### Impact
A format string injection vulnerability than that lead to denial of
service attacks or information disclosure, when the `allow_duplicate_key:
false` parsing option is used to parse user supplied documents.
This option isn't the default, if you didn't opt-in to use it,
you are not impacted.
### Patches
Patched in `2.19.2`.
### Workarounds
The issue can be avoided by not using the `allow_duplicate_key: false`
parsing option.
Authors: Albert Pazderin, Backend Engineer, Vladimir Dementyev, Principal Backend Engineer, and Travis Turner, Tech Editor
Topics: Open Source, Rails, Local-first, DX, WebAssembly, Ruby, JavaScript

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…
Author: Irina Nazarova, CEO
Topics: Developer Community, Devtools startup advisory

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…
### Impact
An integer overflow in the Java BCrypt implementation for JRuby can
cause zero iterations in the strengthening loop. Impacted
applications must be setting the cost to 31 to see this happen.
The JRuby implementation of bcrypt-ruby (`BCrypt.java`) computes
the key-strengthening round count as a signed 32-bit integer.
When `cost=31` (the maximum allowed by the gem), signed integer
overflow causes the round count to become negative, and the
strengthening loop executes **zero iterations**. This collapses
bcrypt from 2^31 rounds of exponential key-strengthening to
effectively constant-time computation — only the initial
EksBlowfish key setup and final 64x encryption phase…
### Summary
An arbitrary method execution vulnerability has been found which
affects Graphiti's JSONAPI write functionality. An attacker can
craft a malicious JSONAPI payload with arbitrary relationship
names to invoke any public method on the underlying model
instance, class or its associations.
### Impact
Any application exposing Graphiti write endpoints (create/update/delete)
to untrusted users is affected.
The `Graphiti::Util::ValidationResponse#all_valid?` method recursively
calls `model.send(name)` using relationship names taken directly from
user-supplied JSONAPI payloads, without validating them against the
resource's configured sideloads. This allows an attacker to…
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…
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:
Author: Irina Nazarova, CEO
Topics: Developer Community, Devtools startup advisory

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 #=>…
Why?
…
Can Ruby Read an X-Ray? Building a Medical Image Processor March 23, 2026 Published on RubyStackNews Nobody expects Ruby to process medical images. That is exactly why I tried it. This article is about building a medical image analysis prototype in pure Ruby using ruby-libgd as the rendering and pixel manipulation engine. No Python. No … Continue reading Can Ruby Read an X-Ray? Building a Medical Image Processor →
The Ruby language leans on duck typing rather than formal interfaces.
“If it walks like a duck and quacks like a duck, it’s a duck.”
bodies = [poem, essay, case_study, user_manual].map(&:body)
These objects come from different classes but all respond to body,
so you can treat them uniformly. That’s informal polymorphism: no
type annotations, no ceremony.
Duck typing is great, but what I miss is enforcement. If one class
implements a method and another forgets to, I want something to
complain.
The interface is a living document
In Ruby, interfaces are implicit. They live in the public methods of
your classes. Private methods are implementation details and not part
of the…
My last weeks on logging represented the last of the major additions I wanted for our upcoming Hanami release. From here I need to start closing all my parentheses.
This week I started on the parenthetical that is Hanami Minitest. I now have that gem pretty much ready to go. Thanks to our community feedback, this now features a test do block-based DSL for declaring tests. I also settled on the naming, with Hanami::Minitest::Test, Hanami::Minitest::RequestTest and Hanami::Minitest::FeatureTest being the final names. This decision also gave me the chance to bring some of the basic setup code into the gem itself (such as setting up the Capybara basics) rather than having all of that be…
Why Rails upgrades become unpredictable in mature systems, and why successful upgrade work starts with discovery rather than execution.