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:
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ā¦
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
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 #=>ā¦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
Meet Duck Typer: your new duck typing friend
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 doblock-based DSL for declaring tests. I also settled on the naming, withHanami::Minitest::Test,Hanami::Minitest::RequestTestandHanami::Minitest::FeatureTestbeing 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ā¦
Direct link to podcast audio file
The promise of Breaking Change is that with every major version (this being the 60th episode of the program, but only the 53rd such release), I will break something. Well, I finally did it. I think I broke the show. Find out how by listening for yourself!
Want to be my friend? Drop me a line at justin@searls.co. Want to file a complaint with my supervisor? Forward your concerns to podcast@searls.co.
These links may rot, but alasādeath comes for us all:
Spoken Latin
This post is an entry for 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.
Specifically, spoken Latin as a hobby language.
Why Latin?
tl;dr: because it has the unusual combination of being:
- no oneās native language, so everyone is a learner.
- a historical language, with texts ranging from two thousand years old to cā¦
Hi, itās gregmolnar. Letās explore this weekās changes in the Rails codebase.
Batch SQL statements when creating tables
This change batches the SQL statements during loading a database schema to improve the performance of the process.
Deprecate require_dependency
require_dependency is deprecated without replacement and will be removed in Rails 9.
Add MySQL lock option and extend algorithm to column Data Definition Language (DDL) operations
This pull request adds:
-
lock:option for MySQLadd_index,remove_index, and ALTER TABLE column operations (add_column,remove_column,change_column,rename_column) -
algorithm:option support extended to ALTER TABLE column operations on MySQL Comā¦
MySQL supports ALGORITHM = {DEFAULT|COPY|INPLACE|INSTANT} and LOCK = {DEFAULT|NONE|SHARED|EXCLUSIVE} to control how DDLā¦
Unraveling GitHub Actions & Modern Auth Challenges
On this episode, Andrewās buried in messy authentication work spread across legacy code, Chris recounts a frustrating GitHub Actions debugging session, and David explains the mental drain of working across both Vue 2 and Vue 3 in the same application. They talk about using workflow run triggers, scheduled builds, and GitHubās new Agentic Copilot workflows such as CI Doctor, Automatic Code Simplifier, and issue/PR management, while lamenting low-quality AI-generated PRs and paid AI code review tools. Andrew makes a special announcement about Blastoff Rails, they compare LazyVim, lazy.nvim, and Kickstart Neovim, we hear about Ruby 3.4.9 and its bug-fix release, and Marco Rothās Herbā¦
Generated automatically by RubyEventsBot using ruby-libgd. Updated every 7 days. Updated by: https://github.com/koxya | Twitter: @koxya
IndieRails Podcast: The Conductor
I hopped on IndieRails with Jess and Jeremy (again). We covered a lot of ground in about 90 minutes. Quick business catch up and then dove into how AI has changed pretty much everything about how I work.
Some of the highlights:
Business Updates. Flipper Cloud almost doubled revenue last year, with most of the growth in the last few months. No AI headwinds on docs or conversion. Fireside is stabilizing ā we flattened churn and had our first three month stretch of even or growing customers since taking it over. Momentum, the coworking space I invested in, is filling up and becoming a real community in South Bend.
Following the Inspiration. I'm a mood person. I follow the energy. Having multipleā¦
#ā792 ā March 19, 2026
Ruby Weekly
Should RubyGems/Bundler Have a 'Cooldown' Feature? ā RubyGemsā maintainer reflects on the idea, quickly gathering steam with other package managers (e.g.), of having a waiting period before newly released packages are installed. Hiroshi says yes, but as an opt-in feature, as it's no silverĀ bullet.
Hiroshi Shibata
No AI Code in Production Directive ā Have you heard Amazon now requires senior engineer approval for all AI-generated code after several severity-0 incidents? Should you ban it, too? We say: there's no such thing as AI code. There's justĀ code.
ā¦Transfer Manager Directory Support for AWS SDK for Ruby
Managing bulk file transfer to Amazon Simple Storage Service (Amazon S3) can be complex when transferring directories containing multiple files and subdirectories. AWS SDK for Ruby Transfer Manager (aws-sdk-s3 version 1.215) now supports directory upload and download. This feature can help streamline bulk transfers by providing multipart handling and parallelism options.
Previously, uploading directories to Amazon S3 required manual iteration and handling. You also had to manage multipart uploads for large files and implement parallelism for performance. With directory support in Transfer Manager, you can handle this with a single method call that automates the process. In this post, weā¦
Recently I had to build something using the canvas element. Today Iāll show you how to build an interactive emoji composer using HTML Canvas and Stimulus. Click emojis to add them to a canvas, drag them around and export your creation as an image. It is quite fun (coming from an emoji connoisseur)! šš

Click a face emoji, add some accessories, position everything just right and download your custom creation. All running in the browser with no external dependencies.
The HTML
Start with a simple layout that divides the screen into a canvas area and emoji picker:
<div data-controller="canvas-composer image-exporter">
<div class="gridā¦Have you ever looked at a VitePress documentation site and felt a little jealous?
The sidebar navigation. The āOn this pageā outline on the right. The search that pops up with /. The homepage that actually looks like a product page, not a README with a nav bar. Dark mode that just works. Code blocks with copy buttons and language labels. It all looks like someone sat down and designed the whole experience.
Because someone did. VitePress is genuinely great. And Ruby developers know it, because some of the most visible projects in our community are shipping their docs on VitePress. Not on a Jekyll theme, not on a Ruby tool. On a JavaScript static site generator built for Vue.
I donāt blameā¦
I had a simple index.html page, a marketing site for a client in Spanish.
They asked an English version too, so I opened the chat to Claudeās Opus 4.5 model and asked it to create a near-identical en/index.html with content translated.
Easy peasy.
I opened both files side by side and skimmed, they looked the same with lines in different languages. But Iām used to testing changes, and agents find things to fix before I start more careful checking. While I had this thought, the client recalled theyād need a version in Portuguese as well. āSureā.
Now, would they synchronize updates in Spanish to the other two languages? Content and design will surely drift.
The solution
I used Claudeās /ā¦
2D Histograms in Pure Ruby March 18, 2026 Published on RubyStackNews One of the most useful tools in exploratory data analysis is the 2D histogram. Not the bar chart kind ā the density map kind. Given a cloud of points, it answers a simple question: where do most of them live? This article shows how ⦠Continue reading 2D Histograms in PureĀ Ruby
Intro
Since the post at the end of last year, ZJIT has grown and changed in some exciting ways. This is the story of how a new, self-contained optimization pass causes ZJIT performance to surpass YJIT on an interesting microbenchmark. It has been 10 months since ZJIT was merged into Ruby, and weāre now beginning to see the design differences between YJIT and ZJIT manifest themselves in performance divergences. In this post, we will explore the details of one new optimization in ZJIT called load-store optimization. This implementation is part of ZJITās optimizer in HIR. Recall that the structure of ZJIT looks roughly like the following.
flowchart LR
A(["Ruby"])
A -->ā¦The Rails Infrastructure team has been working on making Bundler faster and our work has paid off. A cold bundle install is 3x faster on a Gemfile with 452 gems compared to Bundler 2.7. But āfasterā only means something if everyone agrees on whatās being measured. If two people are running benchmarks with different definitions of ācold installā or different cache states, the results arenāt comparable. We needed a shared tool that would give us confidence, both internally and externally, that weāre tackling the right problems and actually making Bundler faster. And along the way we learned when Claude can be helpful and when to not outsource our own expertise and thinking.
What affectsā¦
RubyLLM 1.14 ships a full chat UI generator. Two commands and you have a working AI chat app with Turbo streaming, model selection, and tool call display, in under two minutes. The demo above shows the whole thing: new Rails app to working chat in 1:46, including trying it out.
Why This Matters
RubyLLM turned one last week. 1.0 shipped on March 11, 2025 with Rails integration from day one: ActiveRecord models, acts_as_chat, Turbo streaming, persistence out of the box. 1.4 added the install generator. 1.7 brought the first scaffold chat UI with Turbo Streams. 1.12 introduced agents with prompt conventions. Each release got closer to the same thing: AI that works the way Rails works.
1.14ā¦
GHSA-qmpg-8xg6-ph5q (action_text-trix): Trix has a Stored XSS vulnerability through serialized attributes
GHSA-57hq-95w6-v4fc (devise): Confirmable "change email" race condition permits user to confirm email they have no access to
Ruby on Rails ā Complete Reference of Methods, Classes & Features Not in Ruby March 17, 2026 Rails is much more than a framework on top of Ruby ā it adds hundreds of methods, classes, and abstractions that plain Ruby simply doesn't have. This is a complete reference of everything Rails brings to the table, ⦠Continue reading Ruby on Rails ā Complete Reference of Methods, Classes & Features Not inĀ Ruby
Not the usual content on this blog, bnut this is an interesting story to tell I believe. I own a 2015 Chrysler Town and Country minivan. It is a really good car and filled with electric components. The side doors, the booth, there are 2 screens a DVD player and a bunch of other stuff. Awesome when all is good, not so much when something breaks.
NO AI CODE IN PRODUCTION DIRECTIVE
At SINAPTIA, we started enforcing a no āAI code in productionā directive.
LOL, no. We are not the next tier of Luddites! We started using AI-assisted code generation a little over a year ago, and from the looks of it, we are going to use it even more in the near future. AI is here to stay, and programming will never be the same, what a time to be alive and so on, and so onā¦
But also, in a couple of years, weāll all lose our jobs. What a time to be alive, indeed.
We continually ask ourselves: whatās the AI capable of? Can it really replace us? Can it change the way we work? Will it make our problems simpler? Or there will be another kind of problems, more problems? Are we attending theā¦
šļø Merge Commits podcast - freeCodeCamp: Which Devs Are Screwed?
Direct link to podcast audio file
Quincy Larson over at freeCodeCamp had me on their podcast to discuss how the rapidly changing software industry is impacting junior developers and what they can do about it. I don't normally spend time talking about this stuff, because I started programming in the 90s and can't claim to know anything about what it's like to just be starting now. I've also always discouraged people from getting into software development unless they're super passionate about it, which has been out of step with the "learn to code" hype train that gathered steam over the last fifteen years only to run into a brick wall recently.
His audience is way larger and composedā¦
Less code, more power: Why we rolled our own React Server Components framework

Nothing could make me switch from Keynote to web-based slides. Then, I did! And as a WebSocket geek, I realized it opens up new opportunities! Here's my contribution to making your web presentations beautifully interactive.
Nothing could make me switch from Keynote. I tried. Sli.dev, Google SlidesāI'd poke around, appreciate the novelty, and then go right back. Keynote was my home base; ready to express any creative idea with powerful animations and my own muscle memory. Then, about a month ago, something shifted, and it wasn't about the slide tech, but about how I work. Thisā¦
498: Season 2 Recap
Our hosts come together to wrap up season 2 and share some of their highlights along the way.
Our trio expand and recap on some key topics covered over the last few months, Sally and Joƫl provide updates on their work with typescripts and LLMs, and Aji accidentally stumbles into an idea for a new keynote topic.
ā
Your hosts for this episode have been thoughtbotās own JoĆ«l Quenneville, Sally Hall and Aji Slater.
If you would like to support the show, head over to our GitHub page, or check out our website.
Got a question or comment about the show? Why not write to our hosts: hosts@bikeshed.fm
This has been a thoughtbot podcast.
Stay up to date by following us on socialā¦
Polymorphism with Strategies
One of the most frequent code smells in Rails is an excessive use of inheritance. A serious drawback from using inheritance to achieve polymorphism is the implicit coupling it creates between parent and child classes.

Consider the following example, a range of messaging campaigns:
class Campaign
def deliver
addressees.find_each do |addressee|
transport.deliver(to: addressee, body: prepare_message_body)
end
end
private
def prepare_message_body
# e.g. process merge tags etc.
end
def transport
raise NotImplementedError, "Subclasses of Campaign must implement #transport"
end
end
class Campaigns::Email < Campaign
def transport =ā¦Ruby 4.0.2 Released
Ruby 4.0.2 has been released.
This is a routine update that includes a bugfix in YJIT for NoMethodError on Puma. Please see the GitHub Releases for further details.
Release Schedule
We intend to release the latest stable Ruby version (currently Ruby 4.0) every two months following the most recent release. Ruby 4.0.3 will be released in May, 4.0.4 in July, 4.0.5 in September, and 4.0.6 in November.
If a change arises that significantly affects users, a release may occur earlier than planned, and the subsequent schedule may shift accordingly.
Download
-
https://cache.ruby-lang.org/pub/ruby/4.0/ruby-4.0.2.tar.gz
SIZE: 23824654 SHA1:ā¦
CVE-2026-4324 (katello): Katello - Denial of Service and potential information disclosure via SQL injection'
Welcome to Hotwire Weekly!
Welcome to another issue of Hotwire Weekly! Happy reading! šāØ
šĀ Articles, Tutorials, and Videos
Herb v0.9.0 summary
What's new in Herb v0.9 - Marco Roth announces Herb v0.9 with Action View tag helper support, Prism AST node integration for deeper Ruby understanding, a strict parsing mode, 24 new linter rules, and language server enhancements like code folding and document highlights.
Smooth UI animations on server-rendered HTML - Adrien Siami shows how to create SPA-like animations in server-rendered Rails apps by combining Turbo's morphing with the View Transitions API. Adding a single meta tag and view-transition-name properties to elements enables smoothā¦
Great Work Partners Keep You on YourĀ Toes

Iāve been trying to pinpoint why some work relationships feel like pulling teeth while others feel like aĀ relief.
And in my reflection, I found it wasnāt about raw skill or ability. For example, I work with some brilliant Data Scientists, PMs, Designers, and Engineers who can still make it feel like Iām working between silos. For example, weād pass work items back and forth, like āhereās the mockupā or āhereās the queryā, but it didnāt ever feel like we were building together.
And then there are those few people who change the trajectory of the work we do, who just make everything click, just because they do three specificĀ things.
1. They are willing toā¦
Ben Thompson's latest rests on a single load-bearing assumption: that the harness and the model are tightly coupled, the way Apple's hardware and software are.
It follows, then, that if agents require integration between model and harness, that the companies building that integrationāspecifically Anthropic and OpenAIāare actually poised to be significantly more profitable than it might have seemed as recently as late last year.
This assumption is incorrect. To date, agents have not clearly benefited from proprietary integration to their favored model. I thought this was obvious, but I sometimes forget that not everybody else has made it their full-time hobby to mix and match variousā¦
-
I completed my Hanami logging improvements this week, and Iām so happy with how it turned out. Logs are beautiful now!
After merging the universal logger (which gives us structured and tagged logging no matter what kind logger is configured), I moved on to emitting structured log entries for SQL queries, syntax highlighting SQL in logs (complete with ENV-driven theme selection), and finally adding colours to our standard rack logs (with colours chosen based on request method and status code). The out of the box experience has become so much nicer, all while making things flexible enough for those who want to bring their own logger. This is the Hanami spirit!ā¦
I merged our Dry Transaction to Dry Operation migration guide. Now weāre just a blog post away from sharing all of this with the world.
Carolyn is back with another fantastic docs update, this time adding a delete action and bringing our getting started guide to a full 7 RESTful actions. I reviewed the change and made a few small suggestions. Looking forward to merging this one soon. Thanks Carolyn!
Katafrakt Korner: PaweÅ found and fixed an encoding bug in Dry Logger, which I merged and immediately released as v1.2.2 on Friday. PaweÅ also merged and synced our hardened GitHub Actions. It is so nice to see these improvements happen!
Theā¦
Declare Acronyms in Rails Inflections
A lot of Railsās naming magic comes from its clever use of inflections. user.rb defines the User class, backed by the users table, managed by UsersController, accessible at the /users/ routes.
Every Rails app generates config/initializers/inflections.rb to let you customise this behaviour. Most developers leave it empty. Then one day you namespace a controller under API and Rails starts generating Api::UsersController instead of API::UsersController.
Instead ofā¦
ā¦accepting the wrong casing in your class names:
# app/controllers/api/users_controller.rb
class Api::UsersController < ApplicationController
end
Useā¦
ā¦inflect.acronym to teach Rails the correct casing:
#ā¦People Third Leadership
You may have heard managers describe themselves as having a people first leadership style. Itās so incredibly safe. Who has ever got in trouble for declaring themselves to put people above all else in some vague, detail-free fashion? How could anyone argue against it? Well hold my weave because Iām going in.
Looking at how it plays out in practice, stripped of its emotional appeal, āpeople firstā could be seen as a euphemism for discrimination and plundering the common good. Thatās bad.
Iām going to compare and contrast it with something I call people third leadership, which has the following set of priorities:
- Ethics (Universal Principles)
- The Business (The Commons)
- Peopleā¦
Iām going to argue that by placingā¦
March 16, 2026 Published on RubyStackNews After the last article, Jupyter proved to be an awesome sandbox for testing code interactively. I spent the entire weekend asking myself one question: can Ruby render a real 3D plot? I started convinced the answer was no. By Sunday night, ruby-libgd had proven me wrong. The question nobody ⦠Continue reading Ruby for Data Science ā Is ItĀ Possible?
CVE-2026-32700 (devise): Confirmable "change email" race condition permits user to confirm email they have no access to
From Heroku to Render
After the announcement that Heroku is entering maintenance mode, I got wary of the one (1) application I host on there going down. Itās a Rails app for photos for my kid, which has almost 2,500 photos of her since before she was born until the modern day. I created the app to share these photos with my family back in Adelaide.
I was also listening to this Remote Ruby episode Saturday morning that convinced me to go looking abroad too.
For a Rails app thatās nearing ten years old (for a kid thatās nearing ten years old), it holds up pretty well. This weekend-gone I bumped the Ruby and Rails versions to modern ones without much fuss. The biggest thing in that upgrade was moving offā¦
At one of our productized services for Ruby and Rails maintenance (FastRuby.io), we spend a lot of time thinking making our processes maintainable, efficient, and adaptable over time.
That mindset is what led us to build an internal AI system to automate one of the most important (and time-consuming) parts of our fixed-cost monthly maintenance service (Bonsai): Our quarterly progress reports.
This article walks through how we mapped a very human, manual process to a structured AI-driven workflow and what we learned along the way.
What Is Bonsai?
Bonsai is our signature fixed-cost, monthly maintenance service for Ruby and Rails applications
The idea is simple:
- Gradually pay downā¦



