The ruby-enum gem is a small library I maintain that adds enum-like behavior to a class via include Ruby::Enum and define :KEY, value. Four pull requests landed against it recently, each fixing a different symptom, and all four turned out to be the same underlying bug: class-level instance variables set in a module’s included hook are not inherited by subclasses the way you might expect. All of these fixes shipped in ruby-enum 1.2.0.
Ruby::Enum stores its keys and values in instance variables on the class itself, set up when the module is included.
def self.included(base)
base.extend ClassMethods
base.instance_variable_set(:@_enum_hash, {})
base.instance_variable_set(:@_enums_by_val…
This works fine for a single class. It gets interesting the moment subclasses or class reloading show…
My previous post walked through four bugs in ruby-enum, a gem I maintain, all stemming from the fact that class-level instance variables aren’t inherited by subclasses. The third fix, #59, made keys, key?, value?, key, value, to_h, parse and each walk up superclass and merge in a parent’s enums, so a subclass would see everything its ancestors defined. It was correct, fully tested, and shipped. It also made every one of those methods roughly 5x slower on any subclass.
def _enum_hash
if superclass < Ruby::Enum
superclass.send(:_enum_hash).merge(_own_enum_hash)
else
_own_enum_hash
end
end
This recomputes the merged hash, walking the entire ancestor chain, on every single…
Both phrases cut Claude's sentences in half when explaining code. The vague Simple Technical English loses 8.5% of the facts, and the real standard ASD-STE100 loses 46.8%.
If your team uses Claude to draft client-facing copy, documents, or images, you have probably seen some version of the news by now: Anthropic announced that Claude’s output will carry an imperceptible watermark in text and signed provenance metadata in files, worldwide, as its implementation of the EU AI Act’s Article 50 transparency rules. A lot of comments and interpretations have followed: detectors can now catch your AI-assisted content, you can strip the watermark out if you find the hidden characters, your clients can trace a document back to you.
Most of that is wrong, and the loudest claim, that every Claude output is already watermarked, happens to be the easiest one to check. So…
Shipping Podia’s New Shop, AI Code Woes, and a Major Rails libvips CVE
In this episode, Chris, Andrew, and David dig into their latest experiences building with Claude, from massive diffs and unnecessary view specs to the challenge of catching subtle mistakes in AI-generated code. Andrew shares what went into launching Podia’s new Shop experience, Chris breaks down a serious Rails Active Storage security vulnerability, and David earns a developer rite of passage by accidentally bringing production to its knees. Along the way, they talk Redis 6, smarter Active Record queries, testing philosophy, and why sometimes the fastest solution is still jumping into the code yourself. Hit download now to hear more!
Links
Hi, Wojtek here. Let’s explore this week’s news in the Rails.
Agents on Rails
Read the announcement and the first benchmark report.
Add support for the HTTP QUERY method
QUERY is a safe and idempotent HTTP method that conveys the query in the request content, making it suitable for queries too large or structured for a URL query string:
# config/routes.rb
query "search", to: "search#index"
match "filter", to: "search#filter", via: :query
# request handling
request.query? # => true
request.request_method_symbol # => :query
# integration tests
query "/search", params: { filters: { status: "active" } }, as: :json
Show bin/console startup banner based on IRB
Show a…
Dr. Claude Watson investigates how a suspended CRuby frame kept a raw Fiber pointer after garbage collection had reclaimed its owner.
A mature app's history has to survive the feature being built (and AI can't do that on its own!).
Continue Reading
Checking in on where things are on my current book project, and what's on the way.
One morning, a developer announced in our Slack channel that some tests were failing on our main branch. The cause of the failures was not obvious. No recent PRs seemed related, and neither the code nor the tests had changed in a long time. The test

Thinking of applying to next year's RubyConf Scholars and Guides program? Read on to hear from this year's Scholars about what it was like and why you should take the leap and apply!

Name:
KJ Loving
Professional Title:
Junior Developer
How did you get into Ruby? What's your Ruby story?
I got into Ruby through Code the Dream and learned on The Odin Project curriculum. I had zero background in programming but I wanted to try the backend program because it seemed a bit intimidating to me. I quickly found a loving, kind and supportive community. I couldn't have picked a better place to land.
Are there any Ruby projects you're working on that you're excited about? Tell us all about it!
Too many to list,…
Docker has made it easy to use the same environment everywhere, from development to production. But the most basic Dockerfile, where all your dependencies are lumped together in one image, has hidden costs. In this article, we’ll learn the advantages of multi-stage Dockerfiles both from a security and a performance standpoint, primarily for production images.
What is a Multi-Stage Dockerfile?
You might have a Dockerfile in your application that looks something like this:
FROM ruby:3.2
WORKDIR /app
# Install system dependencies needed to compile native gems
RUN apt-get update && apt-get install -y \
gcc \
make \
libpq-dev
# Install gems
COPY Gemfile Gemfile.lock ./
RUN bu…
This is a typical single-stage setup. There’s one base image, for…
Today we’re sharing the first results of Agents on Rails, a new, ongoing initiative to measure how well today’s leading agentic coding tools (both frontier and open-weight) actually perform on Ruby on Rails codebases.
The Rails Foundation commissioned Evil Martians for this project, which will roll out in several stages over the next few weeks.
Read more about the project below, check out the leaderboard, or jump right over to the first benchmark report.
Why we built this.
The use of coding agents has skyrocketed in the past year with nearly every developer or team using AI to write code. But the options are overwhelming, with new models dropping nearly every week. The cost of running…
TL;DR
We ran 8 models against 21 atomic Rails tasks, 3 runs each. Every task runs against Writebook: a bug report, a security finding, a feature request, each written the way you’d actually file it. Read our announcement post for more information about the project.

So, as of August 2026, which model is best?
-
Most accurate: Claude Opus 5, 92% of runs solved (58 of 63)*.
-
Cheapest: GPT-5.6 Luna, 73% at its default medium reasoning effort, and all 63 of its runs cost 91 cents combined. Not a typo.
-
Fastest: Luna again, at a median of 3.3 minutes per run task.
-
Best combination of all three: GPT-5.6 Sol: 84%, about $0.52 and five minutes per run.
* Claude Fable 5 might lead with…
## Summary
Using Database#create_aggregate, #create_aggregate_handler, or
Database#define_aggregator to define an aggregate function that takes
two or more arguments, and then evaluating it over TEXT or BLOB column
values, can free the Ruby objects holding those arguments while a
later argument is still being converted, during ordinary garbage
collection. The aggregate's step method then receives an incorrect
object, or the process crashes with a segmentation fault.
## Credits
Reported by Jeremy Daer (@jeremy).
Something I must confess is that I absolutely hate writing these blog posts.
It’s not quite as bad as having to give a conference talk, but it’s up there on the list of activities that feel like pulling teeth to me.
Not that I’m not proud of the result.
I absolutely am.
But the process of writing them is very painful for me.
It’s particularly true of the very first sentence, as the post progresses, it gets a bit easier
Yet, I force myself to do it, because it helps me think about problems, and “compile” knowledge in my head.
I’m so terrified of posting something wrong or inaccurate that I tend to double-check some long-held assumptions,
dig into more details about how some things are…
The eleven-shade color scale from Tailwind CSS is one of those ideas I keep stealing. You know the one: 50 through 950 gives you enough stops for backgrounds, borders, hover states, text, everything. I use it even when I’m not using Tailwind.
But I almost never use the defaults (your site/app ends up looking like every other site built by LLMs).
The fix is not complicated. You don’t need a color theory degree or a five-color palette generator (you know the ones 🥹). You only need two or three color scales, and you can derive them all from a single value.
How to choose your brand hue
Rule of thumb: pick a color that fits the problem, not your personal taste (I like pink but not use it all…
Beyond travel_to: The Block-Scoped State Pattern Hidden in Rails Testing August 12, 2026 Rails developers often use travel_to without thinking much about how it works. travel_to Time.zone.parse("2026-08-12 10:00") do # Test code runs as if it were 10:00 end The API is simple: change the perceived time, run some code, and automatically return to the … Continue reading Beyond travel_to: The Block-Scoped State Pattern Hidden in Rails Testing →
Authors: Rita Klubochkina, Sr. Frontend Engineer, and Travis Turner, Tech Editor
Topics: AI, DX, Agent Experience, LLMs, Jamstack

How to publish agent skills so any AI coding agent can find and install them: the .well-known/agent-skills/index.json discovery index, SHA-256 integrity digests, single-file vs multi-file vs bundle packaging, and every install command. Worked from the catalog we just open-sourced.
Two posts ago, an AI startup found us because Claude, which recommended Evil Martians when they asked for a senior dev agency. One post ago, we measured the traffic behind that. Over two months, coding agents read evilmartians.com more than twice as often as people did: 268,000 agent…
Maintaining an organizational knowledge graph with an LLM and event sourcing
Organizations are surprisingly good at forgetting.
Decisions are made on calls, insights get buried in Slack threads, and a month later no one remembers why things are the way they are.
Arkency is no exception.
Weekly calls, ad-hoc meetings, our book clubs, Slack discussions, GitHub mentions, email inbox - we could use some support in organizing all those signals.
Then Ruby Community Conference 2026 happened in March.
In Kraków, Obie Fernandez showed some parts of his NEXUS system.
He had already described it on his blog back in January, but the conference was where I first came across it.
That was the push I…
When it was…
Yet again instead of tweets, a blog post. The backlog got out of hand - 40 of them this time.
Usual caveat: every number below is whatever the author measured on their own machine with their own workload. Some are microbenchmarks. Don't compare them against each other, and don't assume they'll show up in your app. Click through if you care about methodology.
byroot is still speedrunning Ruby and Rails
Jean Boussier shows up often enough that he gets a section instead of bullets scattered through the post.
-
Make Monitor a core class - giving it access to Ruby's internal routines strips out a chunk of overhead.
Monitor#synchronize goes from about 19.8M to 23.7M calls a second; a plain Mutex…
Andy Kroll joins the podcast to talk about Brighton Ruby, the impact AI is having on software development, and how the changing technology landscape is affecting everything from conference budgets to engineering teams.
Andy shares how tools like Claude Code have changed his day-to-day work, making previously neglected projects more achievable while putting even more emphasis on code review, judgment, and maintaining a sustainable Rails application. They also dig into one of the harder questions created by AI: how do you interview software engineers when take-home coding exercises and traditional technical tests are increasingly easy to hand off to a model?
Andy explains how…
What the HANDBOOK.md benchmark measures, why the best model still fails two of every three tasks under strict grading, and what that means for the rules you keep in CLAUDE.md and AGENTS.md.
The slack-ruby-client library, an open source Ruby gem I maintain, runs a scheduled GitHub Actions workflow that regenerates code from Slack’s API definitions and opens a pull request with the diff. The commit message and CHANGELOG entry used to be a generic “Update API (2026-08-11)”, which told a reviewer nothing about what actually changed. Here’s how we taught the workflow to describe its own diffs, using GitHub Copilot CLI, which open source maintainers can get for free.

The Idea
The workflow already computes a diff before opening the pull request. Instead of a boilerplate commit message, we pipe that diff through an LLM and ask it to summarize what changed, then use the response as…
Fall is shaping up to be a busy season for thoughtbot. Over the next two
months, thoughtbotters are speaking, attending, and hosting events across
six cities on two continents. If you’re nearby, come find us.

XO Ruby Vancouver, August 15, Vancouver, Canada
XO Ruby Vancouver kicks things
off. Fernando Perales will be speaking on “The Ruby Guide
to Responsible LLM Integration,” a talk about the production challenges of
wiring large language models into Ruby applications: malformed input, data
leaks, prompt injection, outages, and rate limits, and the patterns that
keep things stable once real users start hitting them.
EuRuKo 2026, September 16-18, Brno, Czech Republic
…
Authors: Alexander Baygeldin, Backend Engineer, and Travis Turner, Tech Editor
Topics: Rails, Performance, Ruby, Sidekiq, Redis

Are you treating your users fairly? They could be stuck in the queue while a greedy user monopolizes resources. And you might not even know it! In this post, you’ll see if it’s time for you to take background job prioritization seriously, and how to make it fair for all users.
Are you treating your users fairly? They could be stuck in the queue while a greedy user monopolizes resources. And you might not even know it! In this post, you’ll see if it’s time for you to take background job prioritization seriously, and how to make it fair for all users.

This is part of an ongoing series of Ruby Runway Spotlights, celebrating the founders who took part in the inaugural Ruby Runway Showcase at RubyConf 2026. Each spotlight is a chance to hear directly from the builders turning Ruby into real, live businesses, and to cheer them on as they keep going.

Tell us your name, your startup, and what it does in one or two sentences.
Stowzilla is your personal warehouse service. Know what you have, and get value from the things you no longer need.
What problem are you solving, and who feels it most? How does your Ruby-powered solution change things for them?
We're solving the problem of getting valuable stuff to people who can use it, and giving space back…
The following is one of those posts where I share some concrete memories/experiences that I associate with some musings, but otherwise doesn’t really have a strong point other than I want to write it down.
When I worked at Code for America, I helped design and deliver two different technical interviews.
The first interview, which I feel confident I can take credit for wholly, was security related. Me, the interviewer, would first have the candidate read about Cross Domain Referer Leakage, and then we’d talk about it:
- How would you summarize the vulnerability in your own words?
- Describe to me a scenario for how an attacker would exploit this.
- Can you think of…
I want to make Ruby the best language to work with LLMs. Part of that is a great JSON Schema DSL.
Schematist is a general purpose JSON Schema DSL that emits Draft 2020-12 schemas. Describe an API payload, a config file, a contract between two services, or the structured output you want back from a model. Trapping that inside another gem’s namespace was a disservice to anyone looking for a great JSON Schema DSL, so it got its own name.
gem 'schematist'
It Emits Actual JSON Schema
This is the breaking change.
to_json_schema used to return this:
{ name: "PersonSchema", description: nil, schema: { type: "object", ... }, strict: true }
That’s not a JSON Schema. It’s OpenAI’s response_fo…
One week of agent-first backend work in the logs: 2,200 session files across four tools, 350 prompts typed by hand, and which checks actually found real defects.
It’s been a whole year since we ran our first sponsorship drive. We’ve been hard at work since then: we shipped Hanami 2.3, unified our ecosystem and launched Hanakai (plus this beautiful new site!), and shipped Hanami 3.0, our most complete release ever. (If you want to catch up on more behind this, hear me on the Dead Code podcast.)
Thanks to our sponsors’ financial support, I’ve been able to maintain at least one full working day on Hanakai every week over the last year. This has been crucial for achieving all of the above. It’s an honour to spend this time serving our community, and a privilege I don’t take lightly. This is why I also spent the last year writing weeknotes, to make our…
My main goal for the last week preparing to kick off our sponsorship drive. I finished drafting the first post, lined everything else up, and now we’re ready to go! Stand by for that first post—in just a few hours!
I spent some time reviewing Ryan’s “Hanami for Rails devs” guides, and relocated them so they appear right below our main Getting started guide—these will be an important part of helping our future users! There’s still a bit of feedback left to sort out, but hopefully these can merge soon.
I put together some notes to set the table for what the team and I can work on for Hanami 3.1. This is going to be a slightly shorter development cycle for us to make a second release this…
This week, Anthropic shipped a new messaging feature to Claude Code. It sounds innocuous enough:
Cross-session messaging lets Claude deliver a message from one of your Claude Code sessions to another. When a change in one session breaks what another is building on, Claude can warn that session before you notice. When one session settles a question another is blocked on, Claude can send the answer across.
And because I sometimes have multiple agents working in the same project simultaneously, it didn't take long for them to start coordinating behind my back so as to avoid interfering with each other's work:
Also, another Claude session (working on performance rugs) pinged mid-turn; I told…
When we think about Ruby code coverage, our go-to gem for this is SimpleCov, which works great when the test suite uses Minitest, RSpec, Cucumber, Capybara, and all these tools that are integrated with Ruby and Rails. But many applications also use other tools like Playwright or Cypress to run e2e tests, and we can’t use SimpleCov the same way.
Most of the time, what we have seen is that the Ruby code executed when running these tools ends up left behind and not being counted for the total code coverage, even though we know the code is actually being tested.
Sample Application
To make it easier to try this, we created a sample application that uses the cypress-on-rails gem along with…
AI Adoption Is More About Culture Than Tools
A few weeks ago, we sat down with a potential client for a project kickoff conversation. The goal was to find out how we could help them integrate AI into their company. Their whole team joined the call, about 15 people, and within the first ten minutes, it was clear everyone had a different idea of what “using AI” meant to them.
One person wanted an easier way to schedule meetings. Another wanted AI to summarize call notes. A few wanted to search through years of client history. Some of what people described, honestly, was closer to plain automation than a need for artificial intelligence. More than a few people in the room were hesitant to…

The problem with our old setup
PDF generation is a core part of Gusto’s business. To serve our customers, we generate reports, invoices, tax documents, employee handbooks, and more. Many of these features relied on a now-deprecated library: wkhtmltopdf.
That reliance had become a liability. Maintenance on the library had stopped, which meant no more security patches. It rendered HTML using WebKit, an engine that had drifted away from how modern browsers display the same markup, so our PDFs didn’t always come out the way we expected. And because PDF generation is memory-intensive by nature, it put pressure on the other services it shared resources with.
Why build a new service?
We decided to…
I love Ruby and it is my goto scripting language. Even in the age of AI, I like
to write short custom scripts for my tool arsenal. One way to find subdomains of
a potential hacking target is to initiate a DNS zone transfer. You can use
various shell tools for this, but if it is part of a process(my case), it might
be easier and more flexible to just script it in Ruby.
I decided to use the dnsruby gem to save some work, otherwise I would need to
do a TCP connection to the nameservers myself. For the sake of demonstration, I
converted my script into a command line one, that will accept 2 parameters, the
host and an optional IP address of a nameserver:
### Summary
Ruby's JSON native C extension clears the consumed `JSON::ResumableParser`
input buffer but leaves `state.start`, `state.cursor`, and `state.end`
pointing into released storage.
When `partial_value` reconstructs an incomplete object containing
duplicate keys, the duplicate-key warning path calls `cursor_position`,
which dereferences those stale pointers. This results in a
heap-use-after-free and can terminate the Ruby process.
An attacker who can supply JSON stream data to an application using
`JSON::ResumableParser` may cause process termination when the
application calls `partial_value` on incomplete attacker-controlled
input containing duplicate object keys.
The issue was…
The method
This process applies the scientific method to a defect. The six phases are the steps of that method. They carry the names a developer uses.
Scientific method Phase You produce
----------------- ----- -----------
Build the apparatus 1. Build a feedback loop one command that goes red on this bug
Observe under control 2. Reproduce and minimise a minimal case that repeats
State the hypotheses 3. Write the hypotheses 3 to 5 ranked causes, each with a prediction
Run the experiment 4. Instrument one probe per prediction, one variable at a time
Confirm the result 5. Fix and add a test a…
If you need more context on why Rails needs a new leadership, here is David Celis summing it up a year ago, Paul Battley a few weeks ago, and—even though it is hard to believe—it even got worse since then.
How could a fork even work?
Rails is a huge code base and has multiple engineers who can invest significant work time into improving it. How could a few people fork and maintain it in their free time? Because Rails is done. Since I started to update The Rails 5 Way to Rails 6 (and then later 7 and 8), I’ve been monitoring the changes to Rails closely:
If you generate a Rails application with rails new --minimal, you only get the core parts of the framework (railties, actionpack,…
transaction is one of the few Active Record APIs that reads like a promise. Wrap the work in a block, and either all of it happens, or none of it does.
An account upgrade shows where the reading breaks:
Account.transaction do
account.update!(plan: "growth")
ProvisioningClient.enable_growth_features(account.external_id)
AuditEvent.create!(account:, action: "plan_upgraded")
end
A validation added to the AuditEvent a week earlier rejects the new audit record, so create! raises ActiveRecord::RecordInvalid. The SQL log ends the way it should:
BEGIN
UPDATE "accounts" SET "plan" = 'growth' ...
INSERT INTO "audit_events" ...
ROLLBACK
The account row goes back to starter, so the ticket is closed as…
Direct link to podcast audio file
We cut our trip a day short, so I found myself with a totally free day with no plans. Naturally, I wasted it by recording a 3-hour podcast. Dang.
I always enjoy shooting the shit with/at you, and if you'd like to be a more active participant in the shit-shooting, then hit me up at podcast@searls.co. Really, I'll be nicer to you than I am to Sam Altman and Tang Tan. I promise.
Back to manually writing links. The zen of monotonous input tasks is suddenly something to be cherished in the current era.
After Rails’ Dear Leader DHH once again espoused far-right views on his blog (which I’m not going to link to here), some of the Ruby community said “enough is enough” and decided to fork Rails into a project called Amiko. I don’t want to mince words here, so I’ll talk straight: I think this is a vain attempt at virtue signalling, and will ultimately end up achieving very little.
The Amiko project has started out this fork by renaming all the Rails things into Amiko flavoured things. They have amiko-pack, amiko-view, and so on. All the rails commands are now amiko commands. The structure of the framework remains the same, so far.
The momentum behind the Rails framework itself is monumental…
Some things that should have worked all along finally do… like alias_attribute in associations, pluck on unsaved records, search_field with autosave: true. The rest of the week went into sharper SQL logs, sturdier job continuations, and more Ractor-ready registries. Here’s what’s new in Rails:
Matz is coming to Rails World 2026!
Ruby creator Yukihiro “Matz” Matsumoto is coming to Rails World 2026! He’ll join DHH, Aaron Patterson, Robby Russell, and the rest of the lineup in Austin this September, and the full conference agenda is now live. If you’ve been waiting to see what’s planned before grabbing a ticket or planning your schedule, now’s the time to take a look.
Fix pluck ignoring…
SF Ruby 2026 with Irina and Vladimir
Irina Nazarova and Vladimir Dementyev from Evil Martians return to preview the second annual SF Ruby Startup Conference and share what they learned from bringing the event to life for the first time. They discuss the conference’s new focus on ambitious builders, the importance of creating meaningful connections for attendees, and why Ruby on Rails remains a powerful foundation for startups tackling difficult, real-world problems. The conversation also explores open-source innovation, AI-assisted development, hidden pockets of Ruby adoption, and how the community can help the next generation of companies confidently build and grow with Rails. Hit download now!
Links
Hi everyone!
Rails World 2026 is just 47 days away, and we have a few fun updates for you. If you haven’t already, you can grab your ticket here.
Now for the updates:
Matz is coming
Big news first: Matz is coming to Rails World 2026! He’ll sit down with DHH on day 2 for a fireside chat. It’s been two years since the last chat in Toronto, and so much has changed since then. We’re living in a different world, so we wanted to bring these two together on stage again to chat about Ruby, Rails, AI, and what the future holds for programming.
Attendees will be able to submit their questions beforehand. This session was made possible by the generous support of our Event Partner and sponsor, Sho…
August 6, 2026 Most Rails applications that implement multi-tenancy eventually face the same question: Where should the PostgreSQL tenant context be established? Many implementations set the tenant at the controller or middleware level. While that identifies the current tenant, it doesn't necessarily guarantee that every database connection carries the correct PostgreSQL session state. A cleaner … Continue reading Hooking into ActiveRecord’s Connection Pool: A Clean Way to Enable PostgreSQL Row-Level Security →
Where are the benefits of using AI? Last Monday I woke up with this question on my mind, I, from my corner of the world far away from big techs, millions of dollars, datacenters, posts on X and LLM-generated posts on LinkedIn.
Eight years ago I started working as a programmer, two at the company where I am currently and one since they started pushing us to use AI to accelerate the development process. I don’t deny that my speed for spitting out code has increased, solving problems has become faster and reaching solutions is less complicated. But what sense does it make if I drift away from what I like most: using my capacities and knowledge to write code that solves a problem and then,…
#812 — August 6, 2026
Read on the Web
Ruby Weekly
Shrinking Ruby Hashes — Hash uses 2-4x the memory of a Struct holding the same data. Ruby committer Jean Boussier digs into why, looking at the layout changes from Ruby 2.3 to now, and shows off the patches that could shrink small hashes in Ruby 4.1.
Jean Boussier
Make Your Next Rails Crash Make Sense — Errors, N+1 queries, slow SQL, Sidekiq jobs, and host metrics in one Ruby gem. Every feature on every plan, predictable pricing, and real engineers on support. 30-day free trial, no credit card, two-minute install.
AppSignal sponsor
▶ Tenderlove on Ractors,…
If you work on Rails for a living, you clone repositories you didn’t write all week long: a gem you’re debugging, a client’s application you’re about to audit, a bug reproduction attached to an issue. For years, opening one of those in your editor was the safe part. You were reading someone else’s code, not running it, and the only real rule was to not run anything until you had looked.
That rule quietly stopped being enough. AI coding editors like Claude Code and Cursor read project-local configuration the moment you open a repository, and some of that configuration is executable. A repo you cloned five seconds ago can hand your editor a command to run before you have read a line of it,…
You run bundle update, kick off a build, and asset precompilation stops on this:”
cssbundling-rails: Command install failed, ensure bun is installed
Tasks: TOP => assets:precompile => css:build => css:install
Except your application uses Yarn. It has always used Yarn. Nothing in the project references Bun, and nobody on the team added it.
This is not an exotic edge case. It can happen to ordinary Yarn applications, and it lingers because the fix has been merged upstream but never released. In this post, we’ll walk through why cssbundling-rails misidentifies your package manager, and how to unblock your build.
The Short Version
cssbundling-rails 1.4.3 added yarn.lock to the list of……
You’re evaluating AI vendors for a company-wide rollout, and every conversation ends the same way: it’s safe, it’s anonymized, we have guardrails. We’ve watched this play out recently, and the questions don’t stop at that answer. Safe how, and which guardrails are actually in place to prevent a leak? Vendor reps tend to stall on the specifics: how access is managed at the level of an individual AI agent, not just the account, and which models and model providers are actually involved, with what safety assurances at each one, not because they’re hiding something, but because “we have guardrails” is often as far as the pitch was built to go.
That gap is worth taking seriously, because the…
This is part 2 of a two-part series. Part 1 covered controllers and lifecycle.

Controllers connect and disconnect. That is not useful on its own. The value comes from three things: referencing elements inside the controller, handling events without inline JavaScript and reacting to data changes. Stimulus calls these targets, actions and values.
Each maps to a distinct JavaScript feature. And none of them repeat the tricks from part 1.
Here is the code. See the full commit on GitHub.
Targets: dynamic getters
A target is a named element inside a controller’s scope. Declare it in the class and get a getter for free:
class HelloController extends Controller {
static targets = ["name",…
The getter this.nameTarget returns the first element…
Where Claude Code, Codex, Cursor, Amp, opencode, and pi store session logs, which formats they use, how long they keep them, and what remains undocumented.
The RubyGems guides at guides.rubygems.org are read by more than humans these days. AI agents fetch them to answer questions about building, publishing, and installing gems. Evil Martians’ Ruby/Rails LLM discoverability scorecard asks how easily an agent can find and read Ruby documentation, and the guides had no good answer. There was no machine readable index, and no way to get a page without its navigation and markup. This week we merged three changes that close both gaps.
The first change adds sitemap.xml and robots.txt (rubygems/guides#523), giving crawlers a complete map of the site. The robots.txt allows everyone, AI crawlers included. Some documentation sites have gone the other…
As you may know, one area of Ruby performance optimization that particularly interests me is memory usage.
Given that most Ruby deployments rely on fork, improving Copy-on-Write performance is generally where you get the
biggest bang for your buck, but that only helps with the somewhat static part of an application heap.
A significant contributor to memory usage is also the transient memory that is allocated during a request or job
cycle and released soon after.
As such, it’s also interesting to keep an eye out for opportunities to make various Ruby objects smaller.
And the Ruby object type that’s probably the biggest contributor to memory usage is likely Hash.
Hash instances are…
When you have to fix an accessibility issue without interrupting users- here's what that actually looks like in a mature Laravel app.
Continue Reading
We're excited to welcome Rubyroid Labs as a Ruby Alliance Supporter, joining a growing group of organizations investing in the long-term health of Ruby and its open source ecosystem.
Every day, millions of developers rely on RubyGems.org without thinking twice about it. That's exactly how great infrastructure should work—reliable, secure, and always there when you need it.
Keeping it that way takes a community.
Since 2013, Rubyroid Labs has helped startups and enterprises build and scale Ruby on Rails applications while actively giving back to the Ruby community through conferences, education, and technical content. Now they're expanding that commitment by contributing engineering resources to…
Authors: Nina Torgunakova, Frontend Engineer, and Travis Turner, Tech Editor
Topics: Tailwind CSS, CSS, JavaScript

Tailwind CSS has become a very popular CSS framework, and it can speed up development. But using it without proper caution can add mayhem to your code. Learn best practices to avoid getting swept away!
Working with Tailwind CSS is pretty fast and easy (that's why it's received such wide recognition). You just paste a list of different classes in your HTML—and your interface immediately becomes attractive! But, as the application grows, the lists of classes grow. Then, one day you realize you can't understand your code, you're confused with the structure of the application and…
I'm happy to announce that Karafka 2.6 and Karafka Web UI 1.0 have just been released.
For those new here: Karafka is a Ruby and Rails multi-threaded, efficient Kafka processing framework, and its Web UI is a monitoring and management dashboard that ships alongside it. As with every release in the 2.x line, this is a continuation rather than a rewrite - you upgrade, apply a couple of small changes, and keep going.
On the surface, 2.6 is a focused set of features - redesigned Declarative Topics, dynamic worker pool scaling, a new low-level offsets API, and lag compensation for paused partitions. Underneath, it is the largest internal reorganization the framework has seen in years. Almost…
Rails Foundation Executive Director Amanda Perino joins David to preview Rails World 2026, the conference’s first year in the United States.
Amanda shares how the team is bringing Austin’s personality into the event through live music, barbecue, sponsor experiences, a mechanical bull, the returning Buzzsprout podcast booth, and Rails World’s biggest lightning-talk stage yet. She also discusses the opening keynote livestream, the lightning-talk CFP, ticket availability, and what attendees should expect as the conference approaches.
The conversation then turns to the Rails Foundation itself. Amanda explains how the rapid growth of AI has forced the organization to reconsider how it…
A year ago I had my first day at 37signals (the people behind Basecamp, HEY and Fizzy).
This was a dream come true for me.
I wanted to work there ever since I read Rework over a decade ago. The books, podcasts and talks that followed showed me that we also share a similar philosophy towards work and the craft of coding. That just cemented my resolve.
Not to mention that it's the birthplace of Rails! The single piece of software that made me decide to turn my programming hobby into my career.
I had an incredible year, so I want to share how I got here and what I learned that might not be obvious when looking from the outside-in.
Getting the job
I'm not sure how many times I applied for a job…
Finally, Netflix you can chill.
RubyGems 4.0.18 includes enhancements, bug fixes and documentation and Bundler 4.0.18 includes enhancements, bug fixes, security and documentation.
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.18
RubyGems Release Notes
Enhancements:
- Check the resolved parent directory before extracting old format gems. Pull request #9755 by hsbt
- Installs bundler 4.0.18 as a default gem.
Bug fixes:
- Call Kernel.format explicitly in Gem::Deprecate wrapper. Pull request #9714 by hsbt
Documentation:
- Point bundler.io URLs at guides.rubygems.org. Pull request #…
You saw the advisory for CVE-2026-66066, the Active Storage vulnerability in the way Rails processes image variants with libvips. You bumped activestorage to the patched version, ran your tests, deployed, and moved on. That is the responsible thing to do, and for most Ruby vulnerabilities it would be the whole job.
This one is different. The patched version of Active Storage will not run on an old copy of libvips. It raises an exception during boot and refuses to start:
/usr/local/bundle/gems/activestorage-8.1.3.1/lib/active_storage/vips.rb:36:in '<compiled>': libvips's unfuzzed operations are not safe to use with untrusted content, and Active Storage cannot disable them. Disabling them r…
libvips is a system library that lives…

This is part of an ongoing series of Ruby Runway Spotlights, celebrating the founders who took part in the inaugural Ruby Runway Showcase at RubyConf 2026. Each spotlight is a chance to hear directly from the builders turning Ruby into real, live businesses, and to cheer them on as they keep going.

Tell us your name, your startup, and what it does in one or two sentences.
I'm Joe Masilotti, and I help Rails developers deploy to the mobile app stores. Ruby Native builds real iOS and Android apps from the HTML and ERB you already have, without writing Swift or Kotlin.
What problem are you solving, and who feels it most? How does your Ruby-powered solution change things for them?
Your customers…
Authors: Gleb Stroganov, Product Designer, Rita Klubochkina, Sr. Frontend Engineer, Varya Nekhina, Account Manager, and Travis Turner, Tech Editor
Topics: Case Study, Design, Developer Products, Design for devtools, Product development, Developer marketing, Agentic development

We designed and shipped a fresh AppSignal homepage in code, then validated it in an A/B test with a 14% lift in activated users.
AppSignal is an established APM platform used by thousands of engineering teams that combines error tracking, logs, and uptime in one product. For its 2026 homepage, Evil Martians imagined a bold creative direction, built it with LLMs, and shipped it straight into an A/B test. Early data shows…
In a previous post, AI Assistant for Our Blog Writing Process, I introduced the assistant we built to help with our blog writing. At the core of that assistant is an MCP server, which serves as the source of truth for both of our blogs. It exposes that knowledge through tools the client can call and documentation the client can read.
Getting an MCP server running is the easy part. Every quickstart, in every language, gives you a server that runs as a subprocess on your own machine and disappears when the client exits. That’s enough to experiment locally, but it’s a long way from something a team can rely on. Once you want to deploy it, questions about where it runs, state management,…
One block in CLAUDE.md and AGENTS.md that makes coding agents write throwaway scripts in Ruby instead of Python or bash, so you stay the reviewer instead of a rubber stamp
If your business runs a support chatbot, or if someone on your team uses an AI tool to draft marketing copy, you already have an AI system in scope of the EU AI Act’s transparency rules. You don’t need to be doing anything exotic or high-risk to be covered. As of August 2, 2026, these rules are binding, and the European Commission’s AI Office, together with national market surveillance authorities, can enforce them.
That catches a lot of businesses off guard, because most of the coverage of the AI Act so far has focused on high-risk systems: hiring tools, credit scoring, biometric surveillance. Those obligations are real, but they’re not due for a while yet, more on that below. The…
The HTTP protocol is one of the most important technologies behind the internet. Every time you open a website, watch a video online, use a mobile application, or interact with a REST API, HTTP is working behind the scenes. It acts as the communication bridge between clients, such as web browsers or mobile apps, and …
Continue reading Why HTTP Introduced the QUERY Method: Solving the Limitations of GET and POSTRSpec Expectations: You're Probably Using the Wrong Matcher August 3, 2026 If you've been writing Ruby tests for a while, chances are you've reached for eq more times than you can count. While it works for many scenarios, RSpec Expectations offers a much richer vocabulary for expressing intent. Choosing the right matcher isn't just about … Continue reading RSpec Expectations: You’re Probably Using the Wrong Matcher →
It’s possible to programmatically upload images to GitHub Issues, Pull Requests and Comments via automation. Finally, though maybe mistakenly, I dunno.
It’s fairly well known that for the longest time, GitHub has not had a programmatic interface for uploading images and attachments. It’s possible in the browser, by dragging-and-dropping your image, but not via something you can script or curl. That’s been a bummer for lots of GitHub Action-powered systems you might imagine, like: automatically attaching demo screenshots or videos on PRs for new features, or attaching failure screenshots or visual diffs from browser tests.
Until now, I guess. Here’s the unofficial,…
In this episode of On Rails, Robby is joined by Aaron Patterson, better known online as Tenderlove, a senior staff engineer on Shopify’s Ruby infrastructure team and a longtime contributor to both Ruby and Rails Core. Aaron and Robby chat about how Ractors are finally bringing true multi-core parallelism to Ruby, the proposal Aaron has pitched to RubyGems.org for content addressable gems that could make bundle install dramatically faster, and the real reasons gems reach for native C extensions in the first place.
They also have a candid conversation about how Aaron actually uses AI day to day, from digging through unfamiliar code at Shopify's scale to building a JPEG encoder almost entirely…

From plausible to production-ready: schema-grounded code replaces hallucinated props with verified, type-safe components.
In our previous post, we treated Zod schemas as agent-readable contracts. But a schema is just a hypothesis; without tests, you’re shipping vibes. This post dives into how we operationalized these schemas, set up a testing suite on Braintrust, and started scoring AI output against our design system.
We set up an experiment with 167 hand-written prompts across 25 components, plus a second dataset built from real engineer requests. Each prompt is a plain-English UI request (e.g., “a primary action button that confirms saving”). The model receives the component’s schema and…
I’m almost back to normal weeks again. A few important life things have continued to impose on my ordinary OSS time, but I’ve been pressing forward with as much as I can.
I merged a nice little improvement to how the hanami CLI invokes the psql CLI. Another great improvement from mddelk — thank you!
Reviewed this internal hanami-cli improvement that switches to throws to allow commands to halt CLI execution, rather than direct exit statements. This should improve some CI flakes, but is also a much nicer approach overall. Thanks Paweł!
More in Katafrakt korner: I reviewed Paweł’s work to make our database tooling work with JRuby, which is looking promising. Paweł also merged a bunch of d…
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.
Atlantic City 🔗
I just got my hands on the Expanded Edition of Nebraska. Easily a top 5 Springsteen album for me. I’m not sure the Expanded Edition added much for me though.
Full Lyrics
Down here, it’s just winners and losers
And don’t get caught on the wrong side of that line
Free 🔗
This is still, I think, the most important song released this decade to me.
Full Lyrics
The feeling comes so fast and I cannot control it
I’m on fire, but I’m trying not to show it
In this episode, we look at adding function calling or tool use to our Rails application when making generative text LLM requests.
An account upgrade starts with an ordinary assignment:
account = Account.find(42)
account.plan = "growth"
account.changes_to_save
# => {
# "plan" => ["starter", "growth"]
# }
The object has the right value. Dirty tracking has the right transition, but the save fails:
account.save
# => false
account.errors.full_messages
# => []
The row remains on the starter plan. The SQL log contains no UPDATE.
That missing UPDATE is useful evidence: save stopped before the adapter attempted the row write. It does not yet tell us what stopped it.
The cause lives in a concern included by Account:
module BillingMigrationGuard
extend ActiveSupport::Concern
included do
before_update…
Dr. Claude Watson investigates why a readable TLS socket could still be a dead HTTP/1 connection, and how a layered non-blocking peek exposed the truth.
After attending Big Sky Dev Con 2024, a couple years ago, and meeting some of the htmx team, I became interested in the conference and was eager to return as a speaker. In 2025, I submitted my Milestones talk but, sadly, wasn’t accepted. This is a shame because Milestoner is used to fully generate all versions and corresponding release notes for all projects. The UI uses htmx which is perfect for statically generated content. Can’t live without it! …but I digress.
This year, thankfully, my htmx View Transitions talk was accepted and glad it was because I had a great time presenting, talking to folks, and enjoying the conference. The conference organizers have…
Hi, it’s Vipul. Let’s explore this week’s
changes in the Rails codebase.
Nominations are open for the 2026 Rails Luminary Awards
The Rails Foundation announced that nominations are open through August 21.
The awards recognize people who have significantly advanced Rails for the
benefit of the community.
Rails versions 7.2.3.2, 8.0.5.1, and 8.1.3.1 have been released
These security releases address a possible arbitrary file read and remote code
execution vulnerability in Active Storage variant processing. Please upgrade
as soon as possible.
Stop filtering i18n paths on initialize
Removes redundant path-globbing work during i18n initialization, cutting the
load time from 400 ms to about…
An Open Source Progress Report about predictable failure handling, lower-memory MIME lookup, and load-aware Falcon clusters.
I was recently part of a Mastodon discussion about the best way to run code in a Rails application before Puma boots. The need for this is that sometimes you want some code that only runs within a webserver, not when running rake tasks or rails commands or opening the console.
Here we go…
Via server do blocks
Rails 6.1 added a Railtie#server hook that can be invoked in application.rb or a gem’s engine.rb. It’s invoked when the config.ru file is evaluated.
Warning: the invocation of the hook in config.ru is missing from a lot of Rails projects. I once lackadaisically tried to address this upstream, but doublecheck your config.ru actually contains Rails.application.l…
In your config.ru
The Rackup configuration file…
### Summary
`Pagy::I18n.locale=` did not validate its argument before using it as a
path component to load the matching dictionary file (`.yml`). An
application that assigns untrusted input to the locale — e.g. the common
pattern `Pagy::I18n.locale = params[:locale]` — let that input influence
which file Pagy attempted to load.
### Impact
Information disclosure (CWE-22 / CWE-200): a file-existence / readability
oracle for `.yml` paths on the host, plus a server-side read of
attacker-chosen files into the process. The file contents are not
returned in the response.
Only applications that pass **unsanitized end-user input** into
`Pagy::I18n.locale=` are affected. Applications that set the…
### Summary
Active Record Tenanted's override of Active Storage's `DiskService#path_for`
does not validate that the resolved filesystem path remains within
the storage root directory. If a blob key containing path traversal
sequences (e.g. `../`) is used, it could allow reading, writing, or
deleting arbitrary files on the server. Blob keys are expected to be
trusted strings, but some applications could be passing user input
as keys and would be affected.
### Mitigation
Upgrade to Active Record Tenanted v0.7.0 or later.
As a workaround, do not use untrusted user input as blob keys. Blob
keys are expected to be trusted strings.
### Credit
This issue was responsibly reported by…
## Summary
AlchemyCMS registers its SVG sanitizer (SanitizeSvgJob, a Loofah-based
scrubber) only as an after_create_commit callback on Alchemy::Attachment /
Alchemy::Picture. This callback fires when a new attachment record is
created, but not when an existing attachment's file is replaced through
the admin "update" action. An authenticated user holding the editor
role (i.e. manage Alchemy::Attachment permission, a low-privilege,
non-admin role) can PATCH an existing attachment to replace its file
with a malicious SVG containing / onload= payloads. Because
the sanitizer never runs on this path, and because AlchemyCMS explicitly
configures SVG as an inline-servable content type on Active…
Big Wins For RubyConf and Grandma
Chris, Andrew, and David begin with summer heat, home cooling problems, and an IPv6 issue preventing Andrew from playing Battlefield 6. The conversation quickly heads down a Raspberry Pi rabbit hole, with projects ranging from smart-home automation and MagicMirror dashboards to local AI transcription. David then recaps RubyConf in Las Vegas before the group discusses design patterns, the changing conference landscape, and how AI is reshaping programming education, software development, and the economics of building products. Hit download now!
Links
HoneybadgerHoneybadger is an application health…
At conferences and meetups, and in conversations online, many Ruby developers have asked me about Ruby Central and my disagreement with them. This post is my attempt to answer the questions I’ve been getting over and over, covering: 1) what is Ruby Central doing now? 2) has the dispute over Bundler and RubyGems been resolved? 3) what has Ruby Central said about the dispute? and 4) what can Ruby developers do now?
What is Ruby Central doing now?
To talk about what Ruby Central is doing now, we need to start with a bit of historical context. What was Ruby Central doing before this saga began? About 18 months ago, Ruby Central:
- ran 2 conferences every year, RubyConf and RailsConf
- had an Open…
Understanding the Rails Middleware Stack July 31, 2026 Middleware is one of the core building blocks of every Ruby on Rails application, yet many developers never interact with it directly. Every incoming HTTP request passes through a chain of middleware before it reaches your routes and controllers, and every response travels back through the same … Continue reading Understanding the Rails Middleware Stack →
Camaleon CMS versions 2.1.1 through 2.9.1 contains an authenticated
remote code execution (RCE) vulnerability that allows users with
custom_fields manage permission to execute arbitrary Ruby code by
supplying a malicious expression through the select_eval custom field
type. Attackers can store an attacker-controlled Ruby expression in the
field options command parameter, which is evaluated via instance_eval
within an ERB view whenever a post edit page is rendered, achieving
server-side code execution with web server process privileges.
For those who have been coding CSS since the Internet Explorer 6 era, when aligning divs on the web was an art,
and there was no way to use partials or variables, the arrival of SCSS was a gift to life. At that moment,
creating partials and reusing variables for your primary colors was a delightful experience.
Now in 2026, for the real fans, it’s possible you’re still using sass-rails and you’re full of these files around your project.
So if you still want to keep using it like me, I recommend migrating to Dart Sass, which is, in fact, a simple migration,
to avoid headaches in the future and, most importantly, to start using the latest features.
Historical context
To give a bit of…
Our blog posts are written by the people who did the work. The process is simple: someone picks a topic, writes a draft, and opens a pull request. From there it goes through two passes, a review that looks for correctness issues, gaps, and overstated claims, followed by a QA pass that checks the final polish: that the whole thing ties together, there are no typos, images render correctly, and links go where they say they go.
Like a lot of teams, we started leaning on AI to help our authors get ideas onto the page. Posts get written faster and people get past their writer’s block quicker. It comes with its downsides though. Asked to fill in a gap, it will make an assumption. Asked to make a…

This is part of an ongoing series of Ruby Runway Spotlights, celebrating the founders who took part in the inaugural Ruby Runway Showcase at RubyConf 2026. Each spotlight is a chance to hear directly from the builders turning Ruby into real, live businesses, and to cheer them on as they keep going.

Tell us your name, your startup, and what it does in one or two sentences.
I'm Michael Carroll, founder of Coolhand Labs. Coolhand Labs is a COO for your AI agents. Whether they run on your computer or in prod, we use log traces and human feedback to keep an eye on them and optimize for efficiency and quality, often cutting costs over 50% in the process.
What problem are you solving, and who feels…
Every transactional email provider ships a Ruby SDK. Each one has its own client class, its own conventions, its own way of doing the same thing. I got tired of learning yet another API for every project. So I built Courrier.
About 14 months and 73 commits later, Courrier 1.0 is here. It covers 13 email providers and 7 newsletter platforms. There’s a companion gem for Rails apps that adds generators, ActiveJob support, browser-based inbox previews and more.
Star it on GitHub ✨
13 providers, one API
Courrier.configure do |config|
config.email = {
provider: :postmark,
api_key: "your_postmark_api_key"
}
config.from = "devs@railsdesigner.com"
end
#…
## Impact
In its default configuration, a Rails application that displays image
variants may allow an unauthenticated attacker to read arbitrary files
from the server, including the process environment. That environment
typically holds secret_key_base and often credentials for external
systems, which may in turn allow escalation to remote code execution
or lateral movement to those systems.
## Affected applications
An application is affected if it meets all of these requirements:
* Uses libvips for Active Storage image processing. This is
config.active_storage.variant_processor = :vips, which
load_defaults 7.0 set and no later default has changed.
* Allows image uploads from…
An authenticated user can create a malicious query that executes arbitrary
JavaScript when another user tries to edit the query. This can be used to
perform actions as the other user for resources on the same origin.
Hi friends!
Rails Versions 7.2.3.2, 8.0.5.1, and 8.1.3.1 have been released!
These are security patches addressing 1 security issues:
- A possible arbitrary file read and remote code execution in Active Storage variant processing
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 more information about the security issue that these releases address:
SHA-256
If you’d like to verify that your gems are the same as the…
Every year, Rails gets a little better. A little faster, a little safer, a little easier to work with. And none of that happens on its own.
The Rails Luminary Awards exist to celebrate those contributions, acknowledging those in the community who have significantly advanced Rails for the benefit of all, and the nominations for 2026 are now open.
If you know of someone who has consistently gone above and beyond to contribute to the framework, triaging bugs, improving performance, adding helpful features, etc. please nominate them below.
All nominations will be reviewed by Rails Core, and the final pick of Rails Luminaries will receive a trophy for their service, as well as a monetary…
Making new Ruby Friends is one of my favorite parts of attending conferences. Neha Abraham joins me to chat about RubyConf, Mental Health, Data Aggregation, and being my Nemesis
What stale reads, concurrent writes, association caches, and Rails' abandoned Identity Map reveal about live Active Record objects.
Authors: Andrey Sitnik, Author of PostCSS and Autoprefixer, Principal Frontend Engineer, and Travis Turner, Tech Editor
Topics: Open Source, Developer Community, DX, Performance & scale, JavaScript

How to protect your npm package from being stolen in a supply chain attack and improve its position in security ratings
Here's why you should care about how you release your npm package:
- Supply chain attacks that steal npm packages are now a real threat, with new attacks every month. If the TanStack, Axios, or ESLint teams were hacked, you can be hacked. These days, attackers steal packages automatically with LLMs, using previously stolen dependencies to reach the next ones.
- Taking care of…