At RubyConf 2026, anyone who buys a ticket before July 1st is entered into a raffle for an exclusive RubyConf VIP experience. What exactly is a RubyConf VIP experience?
Five lucky winners, drawn at random, will:
- Get a ticket for you and a plus-one to the world-famous RubyConf speakers' Dinner, where you'll meet your real-world Ruby Heroes. Get exclusive behind-the-scenes access to the people who make Ruby and make RubyConf while you eat like royalty.
- VIP reserved seating for all keynote talks so you won't miss a thing. No fighting for a free seat or squeezing in the middle of a row of strangers. Walk right up and take a load off.
- A personal "thank you" from the board and staff. Because we…
But that's not all, everyone who enters by buying a ticket by July 1st will receive a limited edition RubyConf 2026 pin! If you were on the fence before, don't let this chance of a lifetime pass you by. When the clock strikes midnight on July 1st (PST), this door will officially be closed. Anyone who buys a ticket after that will…
If you're heading to RubyConf this July, make sure to stop by and meet the team from SmartFinancial.
SmartFinancial is a technology-driven insurance marketplace that helps people find and compare insurance options across all 50 states. Their goal is simple: make buying insurance easier, more transparent, and less frustrating for consumers.
Ruby plays a major role in making that happen.
The SmartFinancial engineering team has been building and operating Ruby on Rails applications for years, and they're excited to be part of the RubyConf community in Las Vegas this July 14–16 at Red Rock Casino Resort. Like many of us, they're coming to learn, share ideas, meet fellow Rubyists, and stay…
The fifth obstacle is us. Our cynicism, our exhaustion, our tendency to scroll past the policy debate and doom-post about the inevitable robot apocalypse. Doomerism is a form of political paralysis. If you believe the future is already determined, you don’t organize, you don’t vote, you don’t fight. You wait for the catastrophe and feel validated when it arrives.
JA Westenberg: A Soft-Landing Manual for the Second Gilded Age
Writing effective test cases is as important as writing the business logic in your application. This blog post dives into the simple yet effective ways developers can use when crafting test cases.
Lack of assertions in the test cases
We all have written controller test cases in the past. It could be rspecs, minitests, or any other framework. Consider we have an UsersController and the code look like this:
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.save
# Sending welcome email
UserMailer.welcome_email(@user).deliver_later
# Creating default settings for user
Use…
Authors: Irina Nazarova, CEO, and Travis Turner, Tech Editor
Topics: Performance, Real-time, Open Source, Performance & scale, Frontend & real-time, Node.js, WebSocket

Evil Martians benchmarked five WebSocket servers for Node.js: Socket.io, uWebSockets.js, and AnyCable (OSS and Pro). How we caught our own load generator lying, and how to make WebSocket benchmark numbers honest.
I compared five ways to run WebSockets on Node.js: default Socket.io, Socket.io with Connection State Recovery, uWebSockets.js, AnyCable OSS, and AnyCable Pro. In this post, I share how a banned laptop, a lying load generator, and a stubborn throughput disparity taught me that the hardest part of benchmarking is getting…
## Summary
The protected copy helper behind Node#dup and #clone unwrapped its
source argument as an xmlNode without a type check.
Supplying a non-Node (e.g. a Namespace) made it read an xmlNs
out of bounds, crashing the process.
Nokogiri 1.19.4 performs a type check and raises TypeError when an
argument of invalid type is passed.
Only CRuby is affected. JRuby is not affected.
## Severity
The Nokogiri maintainers have evaluated this as low severity.
This is only triggered by a programming error. It requires application
code to call the protected internal initialize_copy_with_args method
with an argument that is not a Nokogiri::XML::Node.
Nokogiri 1.19.4 now raises TypeError instead of…
Blue Ridge Ruby made a comeback in 2026 and Jeremy Smith joins the podcast to talk about how it went
Show Notes
Sponsors
Lots of teams out there are still overpaying for their hosting and getting tripped up by traffic spikes. If you’re on one of those teams, you need a better autoscaler. Judoscale uses better metrics, gives you more control, and reacts faster than any other autoscaler. Learn more at https://judoscale.com/
I started founding my second company in Germany in late January. It is now late June.
In that time, the state, two courts, a notary, a law firm, a tax firm, and software vendors have all found a way to bill me. Every single one of them, on time.
I have spent more than 9,600 euros to start a company: a little over 7,600 in fees and bills, plus 2,000 in share capital frozen in an account I am not allowed to touch. And after five months, here is what I have to show for it:
I have not been able to send a single invoice of my own.
Not one.
The work is happening. The clients are real. The one thing the state exists to let me do, bill them cleanly, is the one thing I still can’t.
The timeline
…
Some time ago, we migrated our work application from Rails 6 to Rails 8 in one big jump and adopted several new features that came with this version. One of those was a Procfile that defined the necessary processes to run the application in local environments, which is executed when you run bin/dev. If you look at the code of this file, you will find the real responsible party for executing all these processes: foreman (unless you modified the original file).
The first problem we started encountering was that all process outputs were mixed into a single stream, making it take us a long time to realize that, for example, JavaScript compilation had failed, which is why we weren’t seeing the…
How Ruby Itself Uses Dependabot: A Look Behind MRI's Dependency Management June 23, 2026 When people think about Dependabot, they usually picture a Rails application keeping its gems up to date. But Ruby itself—the MRI interpreter—also relies on Dependabot to automate dependency updates. Its configuration offers an interesting glimpse into how the Ruby core team … Continue reading How Ruby Itself Uses Dependabot: A Look Behind MRI’s Dependency Management →
This week I made a refactor to remove a job (ActiveJob::Base) that was used only in recurring.yml, and call a class method directly instead.
Sometimes it is ok to have a job, but sometimes using the method can help you write a little less code. And these days it is just a prompt away.
The example
I was working on a follow-up flow for users who had not updated their profile in over a year. The recurring task only needed to fan out work: find eligible users and enqueue one job per user.
Instead of scheduling a job in recurring.yml, like this…
follow_up_main_info_review:
class: "User::ScheduleMainInfoReviewFollowUpsJob"
schedule: "every day at 09:00"
With a thin wrapper job like this…
…
RubyGems 4.0.15 includes enhancements and bug fixes and Bundler 4.0.15 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.15
RubyGems Release Notes
Enhancements:
- Rubygems: Fix Gem::Request for PQC support, adding integration connection tests. Pull request #9615 by junaruga
- Reduce peak memory usage of full index loading and bundle install. Pull request #9618 by hsbt
- Installs bundler 4.0.15 as a default gem.
Bug fixes:
- Forward security policy to old-format gems. Pull request #9611 by hsbt
Bundler Release Notes
…
Getting acquired is exciting, but the technical story of your acquisition gets told after the deal closes.
Continue Reading
We have been spending time teaching Claude Code how to help us upgrade Rails applications. Along the way we learned that the most reusable piece of that effort is not the prompt we type, it is the skill we wrote once and now load on demand.
If you keep pasting the same checklist or procedure into a chat, a skill is probably what you want. This post walks through writing your first skill from scratch and keeping it lean, so it triggers when you want and costs almost nothing when you don’t.
What Is a Skill?
A skill is a folder with a SKILL.md file inside it. The file has two parts: YAML front matter that tells Claude when to use the skill, and Markdown instructions that tell Claude what…
Somewhere in the mid-aughts eXtreme Programming (XP) practices became widely-discussed in software. From that time forward, a strange chasm emerged in the discourse.
I would stumble across large pockets of programmers discussing—with full confidence—the fact that “nobody is actually doing TDD”, “pairing all the time is a myth”, “no one can actually succeed with those practices, it’s just hype”. Meanwhile, I was writing all my code test-first, spending nearly all of my time pair-programming, and by all accounts succeeding greatly. Not to mention enjoying coding more than ever.
It was like living in parallel universes. In my universe, XP practices were a welcome way of life, making…
This is a short post to show the compatibility between JRuby and
Ruby on Rails across different versions. JRuby is an implementation
of Ruby that runs on the JVM, so picking a version means lining up four things at once:
- JRuby release
- Ruby version
- Minimum Java version
- Rails version
JRuby tracks a specific CRuby (MRI) language level per release, and Rails support on JRuby is delivered
through the activerecord-jdbc-adapter gem,
whose version number mirrors the Rails version it targets. The Rails versions listed below are the
ones that both run on that JRuby line’s Ruby language level and have a matching adapter release.
JRuby Version
Ruby Compatibility
…
Aji and Joël join forces to discuss graph and tree structures, and their connection to the emergent properties, attributes and qualities you can find from a largely connected group of data.
Joël dives into their recent graphs and tree work through a contracting system, whilst Aji looks back at when he previously tried to serialise a graph or tree to a database.
—
Watch Joël’s Blue Ridge Ruby talk here, or Matheus’ Ruby Internal talk from last year here.
There’s still time to secure your place at thoughtbot’s upcoming UK meet ups over the next month.
London Tech Leader Meetup - Tuesday June 23rd
Brighton Tech Leader Meetup - Wednesday June 24th
Brighton Ruby - Thursday June 25th…
Your hosts for this episode have…
### Summary
`Concurrent::AtomicReference#update` can enter a permanent busy retry
loop when the current value is `Float::NAN`.
The issue is caused by the interaction between:
- `AtomicReference#update`, which retries until `compare_and_set(old_value,
new_value)` succeeds.
- Numeric `compare_and_set`, which checks `old == old_value` before
attempting the underlying atomic swap.
- Ruby NaN semantics, where `Float::NAN == Float::NAN` is always `false`.
As a result, once an `AtomicReference` contains `Float::NAN`, calling
`#update` repeatedly evaluates the caller's block and never returns.
In services that store externally derived numeric values in an
`AtomicReference`, this can cause…
### Summary
`Concurrent::ReentrantReadWriteLock` can incorrectly grant a write lock
after one thread acquires the read lock 32,768 times.
The lock stores a thread's local read and write hold counts in one
integer. The low 15 bits are used for the read hold count, and bit 15
is used as `WRITE_LOCK_HELD`. After 32,768 reentrant read acquisitions,
the local read count crosses into the write-lock bit. `try_write_lock`
then treats the thread as already holding a write lock and returns
`true` without setting the global `RUNNING_WRITER` bit.
This breaks the core mutual-exclusion guarantee: the caller is told
it has a write lock, but other threads can still hold or acquire
read locks at the same…
### Summary
`Concurrent::ReadWriteLock#release_write_lock` does not verify that the
calling thread acquired the write lock. Any thread with access to the
lock object can release an active write lock held by another thread. A
second writer can then enter its critical section while the first writer
is still running.
`Concurrent::ReadWriteLock#release_read_lock` also decrements the shared
counter even when no read lock is held. Calling it on a fresh lock
changes the counter from `0` to `-1`, after which normal read acquisition
raises `Concurrent::ResourceLimitError`.
This is a synchronization correctness issue in the public
`Concurrent::ReadWriteLock` API. It should not be framed as…
### Summary
`Oj.load` in `:object` mode reads uninitialized stack memory (and,
for long keys, reads out of bounds) when parsing a JSON object whose
key is 254 bytes or longer. The interned bytes can surface to the
caller, disclosing process stack memory.
### Impact
Information disclosure of process stack memory to a caller that parses
untrusted JSON with `Oj.load(..., mode: :object)`. For keys >= 256
bytes it is also an out-of-bounds read (CWE-125).
Severity is bounded by several preconditions: it requires `:object`
mode (which is already discouraged for untrusted input), the leaked
bytes are uncontrolled (the attacker cannot choose what is disclosed),
and the data only reaches an…
### Summary
`Oj.dump` is vulnerable to a stack-based buffer overflow when a large
`:indent` value is provided by the developer. `fill_indent` in `dump.h`
calls `memset(indent_str, ' ', (size_t)opts->indent)` without validating
the size. When `opts->indent` is set to `INT_MAX` (2,147,483,647), the
`(size_t)` cast preserves the large value and `memset` writes 2 GB into
the stack-allocated `out` buffer (4,184 bytes), corrupting the stack
and crashing the process.
### Summary
`Oj::Doc#each_child`, when invoked recursively over a deeply nested JSON
document, overflows a fixed-size stack buffer and aborts the process. This is a
denial of service reachable from untrusted JSON.
### Impact
Reliable denial of service: any endpoint that calls
`Oj::Doc.open(untrusted) { |d| d.each_child ... }` recursively can be
crashed with a small deeply-nested payload. On builds with a stack
protector (the default, `-fstack-protector-strong`) the canary aborts
the process before the saved return address is used. The Step-1 heap
OOB writes into `struct _doc` fields do occur, but are masked in
practice because the Step-2 stack overflow crashes first; turning them
into…
Every seven weeks or so, each Aha! engineer takes a week of support rotation. I caught myself doing something dumb during my last one. A ticket came in. I clicked over to our production log viewer, narrowed the time range, and started piecing togeth
Certain shifts in software history feel like freedom because they remove familiar signals of control. In reality, they relocate rigor closer to where truth lives. They make it harder to fake progress.
leaflet.pub: Relocating Rigor
The fourth edition of Rails World is fast approaching with just over three months to go, so it’s time to meet the speakers who will join us this year in Austin, TX.
But first: Thank you to everyone who applied this year. When we opened the CFP, three of the nine topics were AI-related, but in the end half of all submissions were in these three categories. Not at all surprising considering the year we are having, but there are only 20 speaking slots, and still a lot happening in Rails outside of (or maybe adjacent to) AI, so finding the right balance took a little more work this year. (Big shout out to the content committee for their patience, discernment, and endless review cycles!)
With…
# Uncontrolled Recursion in NestedParamsEncoder Allows Stack
Exhaustion DoS via Deeply Nested Query Parameters
## Summary
`Faraday::NestedParamsEncoder`, the default nested query parameter
encoder/decoder in Faraday, decodes nested query strings without
enforcing a maximum nesting depth.
A crafted query string such as:
```text
a[x][x][x][x]...[x]=1
```
causes Faraday to build a deeply nested Ruby `Hash` structure. The
internal `dehash` routine then recursively walks this attacker-controlled
structure without a depth limit. At sufficient depth, Ruby raises an
uncaught `SystemStackError` (`stack level too deep`), crashing the
calling thread or worker.
This can lead to denial of…
# Unauthenticated nested page API leaks restricted & unpublished content
- **Location:** `app/controllers/alchemy/api/pages_controller.rb:28`
(`Api::PagesController#nested`)
- **Affected version:** Alchemy CMS 8.3.0.dev (Rails 8.1.3)
## Description
The unauthenticated `GET /api/pages/nested` endpoint returns the full
page tree to any anonymous caller, including restricted (member-only)
pages and unpublished/draft pages that should be hidden.
Appending `?elements=true` additionally dumps the element/ingredient
**content** of restricted pages, fully bypassing the access control
the sibling `show` and `index` actions enforce.
## Root cause
`Api::PagesController#nested` calls no…
Can Ruby Next Help You Upgrade an Application Gradually? June 21, 2026 Upgrading a Ruby application is rarely as simple as changing the version number. Dependencies, deployment pipelines, CI environments, and legacy code often mean that a runtime upgrade becomes a project of its own. As a result, many teams postpone adopting newer Ruby language … Continue reading Can Ruby Next Help You Upgrade an Application Gradually? →
Join me, won't you, on a thought experiment as I test my approach to test-driven development in Rails, using (mostly) the default testing stack. Early release available now on Leanpub!
### Summary
`Nokogiri::XML::NodeSet#[]` (and its alias `#slice`) checked the requested
index against the node set's bounds using a 32-bit-truncated copy of the
index. A large negative index could pass the check and then be used at full
width, reading outside the node set's storage. On CRuby this is an
out-of-bounds read that typically crashes the process; on JRuby it is not
memory-unsafe but returns an incorrect node.
Nokogiri 1.19.4 performs the bounds check against the full-width index.
### Severity
The Nokogiri maintainers have evaluated this as medium severity.
Exploitation requires an application to pass an attacker-controlled integer to
`NodeSet#[]`. The primary impact is a…
### Summary
Calling `Document#encoding=` with an invalid encoding (e.g., a non-string, or
a string containing a null byte) raises an exception, but only after freeing
the document's current encoding string without replacing it. The document is
left referencing freed memory, so the next call to `Document#encoding` reads
invalid memory, which can cause a segfault or leak freed bytes into a Ruby
`String`.
Affects the CRuby (libxml2) implementation only; JRuby is not affected.
### Severity
The Nokogiri maintainers have evaluated this as low severity. Reaching it
requires an unusual API-usage pattern that does not arise during normal use.
The application must pass an invalid encoding to…
### Summary
The `NONET` parse option, which Nokogiri turns on by default for
`Nokogiri::XML::Schema` (see
[CVE-2020-26247](https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-vr8q-g5c7-m54m)),
was not correctly enforced on the JRuby implementation. As a result, a schema
parsed with default options could still cause external resources to be fetched
over the network, potentially enabling SSRF or XXE attacks.
Nokogiri 1.19.4 replaces the scheme denylist with an allowlist. When `NONET`
is enabled, only local resources (a `file:` scheme, or a relative or absolute
path with no scheme) are resolved, and every network scheme is blocked,
case-insensitively. This brings the JRuby…
### Summary
Nokogiri contains a bug when calling certain methods on
allocated-but-uninitialized native wrapper classes that inherit from
`Nokogiri::XML::Node`. This caused a NULL pointer dereference that could crash
the process.
Nokogiri 1.19.4 checks for missing native data pointers and raises a
`RuntimeError`.
JRuby is not affected.
### Severity
The Nokogiri maintainers have evaluated this as low severity. This is only
triggered by a programming error. It requires application code to call
`.allocate` directly on a native-backed class and then invoke methods on the
resulting uninitialized object. It cannot be triggered by untrusted input or
through normal use of the public API.
###…
### Summary
`Nokogiri::XML::XPathContext` did not keep its source document alive for
garbage collection. If an `XPathContext` outlived its document and the
document was collected, evaluating an XPath expression could read invalid
memory and potentially segfault.
This is only reachable when application code constructs an `XPathContext`
directly and lets the document become unreachable while continuing to use the
context. The normal `Document#xpath`, `#css`, and related search methods are
not affected, and it is not triggerable by malicious document input.
Nokogiri 1.19.4 makes `XPathContext` keep its source document alive for as
long as the context exists.
Only the CRuby implementation…
### Summary
Nokogiri's CRuby native extension could leave a Ruby wrapper pointing to freed
memory when replacing the value of an XML attribute. If Ruby code had already
accessed an attribute child node, `Nokogiri::XML::Attr#value=` could free the
underlying native child node while the wrapper remained reachable through the
document node cache. A later use of the freed child node or a Ruby GC mark
could dereference an invalid pointer, causing an invalid read and a possible
segfault.
Nokogiri 1.19.4 preserves any already-wrapped attribute child nodes before
replacing the attribute value.
JRuby is not affected.
### Severity
The Nokogiri maintainers have evaluated this as low severity.…
### Summary
XInclude substitution performed by `Nokogiri::XML::Node#do_xinclude` replaced
each `` in place, freeing the include node along with its children
(such as `` and its descendants) and any namespaces declared on
them. If an application had already exposed one of those nodes or namespaces
to Ruby, the corresponding Ruby object was left pointing at freed memory.
Using the object could result in invalid reads or writes to memory.
Nokogiri 1.19.4 substitutes each `` on a defensive copy by
default, so the structures libxml2 frees are never the ones bound to live Ruby
objects.
Only the CRuby implementation is affected; JRuby is not affected.
### Severity
The Nokogiri maintainers…
### Summary
`Nokogiri::XML::Document#root=` validated only that the new root was a
`Nokogiri::XML::Node`, allowing a DTD node to be set as the document root. The
result is a heap use-after-free during garbage collection or finalization,
leading to an invalid memory read or potentially a segfault.
Nokogiri 1.19.4 restricts `Document#root=` to element nodes, raising
`TypeError` for any other node type.
This memory-safety issue affects only the CRuby implementation (libxml2). The
JRuby implementation was not affected; the same input validation was added
there for behavioral parity.
### Severity
The Nokogiri maintainers have evaluated this as low severity. This is only
triggered by a…
We organized around nouns, not verbs. Users, lists, tasks, comments, each owned by exactly one service. Operations were almost entirely CRUD. Communication happened through exactly two mechanisms: a standardized REST/JSON convention that every service spoke natively and exclusively, and a message bus that broadcast every mutation. That was it. No service-to-service RPC. No custom protocols. No internal APIs that only two services knew about.
We didn’t choose this approach because we loved distributed systems. We chose it because it enforced replaceability. When a service became too heavy—too much conceptual mass—we didn’t refactor it. We deleted it and replaced it with something simpler.…
A flaw was found in Katello's of Red Hat Satellite. A content upload
functionality where insufficient authorization checks in the
ContentUploadsController allowed users with the edit_products
permission to query content information for repositories outside
the products they were authorized to manage. An authenticated attacker
could exploit this issue to determine whether specific content
exists within repositories that should otherwise be inaccessible.
This issue does not allow unauthorized modification, import, or
publication of content.
## Summary
A critical missing authorization flaw exists in Avo's association attach
workflow. The UI and `GET /resources/:resource/:id/:related/new` path
can check `attach_?`, but the actual write endpoint,
`POST /resources/:resource/:id/:related`, does not run the same
authorization check before mutating the association.
As a result, an authenticated low-privileged Avo user can bypass
hidden/disabled attach controls and directly attach related records
to a parent record by sending a crafted POST request. In applications
where associations represent teams, tenants, roles, projects, users,
memberships, ownership, or other authorization-bearing relationships,
this can lead to privilege…
Hi, it’s zzak. This week was full of changes, so let’s pull into the station and take a look.
Last Rails World GA tickets available
Heads up: there are now just 100 General Admission tickets available for Rails World 2026. Don’t miss your chance to join the Rails community in Austin this September for two days of talks, code, connection and music.
Rails Foundation documentation guides
The documentation project reworked the Multiple Databases guide, now ready for community review, and reorganized the Internationalization guide from beginner-friendly setup through advanced topics.
Allow query log tags to be configured per connection pool
Database configurations can now override query log…
Navigating Subscription Overhauls and Payments
Chris, Andrew, and David catch up after a missed week of recording and quickly dive into the kind of deeply practical Rails work that only comes from real production pain. Andrew shares the massive subscription and billing migration happening at Podia, including Stripe edge cases, legacy plan preservation, and stress-test tooling built from live scenarios. Chris then goes deep on a Hatchbox email cancellation flow that turns into a Rails internals rabbit hole around Action Mailer callbacks, mail delivery cancellation, and a tiny Rails PR born from production debugging. Hit download now to hear more!
Links
I wrote recently about
Syntropy, a new Ruby web framework
I’m working on (it runs this
site). Syntropy’s design is based
around the idea of file-based routing, which means that the source files for
route handlers (i.e. controllers) that make up the app are organized and named
according to the app’s URL namespace. I also discussed the way Syntropy loads
the different source files (referred to as modules), and I’d like to discuss
this a bit more in detail.
Code Organization in Ruby on Rails
Now, if you’re a Rails developer, you know that Rails’ approach to code
organization is based on auto-loading of the different source files that make up
the app, performed by the Zeitwerk gem.…
Herb and ReActionView: A Glimpse Into the Future of Rails Views June 18, 2026 For years, Rails developers have enjoyed one of the simplest and most productive ways to build web applications: write HTML with ERB, let Action View render the templates, and move on. While the Ruby language, the parser, and the tooling ecosystem … Continue reading Herb and ReActionView: A Glimpse Into the Future of Rails Views →
I’ve had a Comsol 3-in-1 wireless charger sitting on my desk for ages. It has a hardcore 2010s tech aesthetic, with its white plastic and chrome combination. I use it to charge my phone, watch and earbuds all at once. Or at least I did, until it stopped being able to charge the phone. It could still charge a watch and the earbuds, but I used it most for charging the phone.
The device still turned on, but it would flash a solid white light for about a second, then off again, then repeat. I didn’t know what caused this, and googling for the manual turned up no results. But I did find the support email! So I contacted them and asked what it meant and if they had the manual.
They then asked…
The Asset Pipeline has had many changes over the years, from not needing NodeJS when using Sprockets, to supporting NodeJS to manage JS dependencies through npm packages, to requiring NodeJS by default with Webpacker, and to not needing NodeJS by default again with ImportMaps.
ImportMaps is a good way to not have NodeJS as a dependency of the application, but it has many limitations (like the lack of TypeScript support) and it requires a lot of work to migrate to it when upgrading older applications.
In this blog post, we will see how to use Bun to remove the need to install NodeJS system-wide, how to use the standalone binary to not require an installation step, and at the same time keep…
Before and after (image) sliders are great for product showcases, before/after transformations, renovation projects or photo editing results. They’re engaging, interactive, and honestly just fun to use.
Ever thought of building one from scratch? Not complicated at all! In this article, I want to show how to build a simple, reusable Stimulus controller that does just all that. This is how the end result will look like:

As always, the code can be found on GitHub.
It is simple, really
The beauty of this controller is its simplicity. You need three things:
- a wrapper element;
- two images (before and after), and;
- a slider.
That’s it. Here’s it in HTML:
<div data-controller="compare">
<img da…
How SOLID changes when you read it through Ruby’s object model, duck typing, and preference for pragmatic design.
Generative AI dramatically lowers the cost of modification, which creates a dangerous illusion: that everything can change quickly, therefore everything should.
leaflet.pub: Pace Layers and AI Integration
#805 — June 18, 2026
Read on the Web
Ruby Weekly
The Plan for rv and a Progress Update — Inspired by Python’s uv, rv is a fast Ruby install, gem, and project manager built by several prominent Rubyists. v0.6 landed this week, and things are going well. This post shares some history, progress, and where the team is focusing next.
André Arko
⚡ "You can go straight from brew install rv to a Rails app from rvx rails new in 10 seconds flat." – André Arko
Hiring Rails Engineers Takes Months. We Start Next Week! — Since '17, teams have trusted us to upgrade Rails. The same engineers are now available for staff augmentation:…
It’s the **robber barons, rails, rents and defaults** of the next twenty years I worry about, not skynet, the singularity or misaligned paperclip optimizers.
Philipp Markolin, PhD: The AI Race to Reboot Feudalism
I’m mourning the future I grew up and came of age thinking we would have. Fascism, and overbearing type systems, was something my forebearers dealt with so that I wouldn’t have to.
okayfail.com: In Praise of DHH
90% utilization is causing more failure than you realize, not just in burn-out, but in productivity and output.
Jason Cohen: A Smart Bear » Your non-linear problem of 90% utilization
perhaps languages aren’t slowing down so much as *spreading sideways*. They are dissolving into domains like query languages, shader languages, build languages, DSLs for robotics or finance, etc. The langdev shift perhaps is less about one big new paradigm and more about fifty smaller ones, deeply integrated.
Fogus: The Long Season of Langdev
Before and after (image) sliders are great for product showcases, before/after transformations, renovation projects or photo editing results. They’re engaging, interactive, and honestly just fun to use.
Ever thought of building one from scratch? Not complicated at all! In this article, I want to show how to build a simple, reusable Stimulus controller that does just all that. This is how the end result will look like:

As always, the code can be found on GitHub.
It is simple, really
The beauty of this controller is its simplicity. You need three things:
- a wrapper element;
- two images (before and after), and;
- a slider.
That’s it. Here’s it in HTML:
<div data-controller="compare">
<img da…
Ingress is not the owner of the invariant
A polemic with Callbacks Are Not Invariants by Brandon Weaver.
A disclaimer: I’m a RailsEventStore maintainer and this article ends up on the Arkency blog — so cards are on the table. Despite this, I’m keeping the core of my argument in pure ActiveRecord: no step of the reasoning requires RES. I only show the RES version at the end, separately, as “and this is what it looks like when you’re not typing it in manually”. If you’re convinced by the bare-metal AR reasoning, not the library, that’s what matters.
We agree about the disease
I enjoy reading Brandon’s Rails: The Sharp Parts series and sending it to the team — it’s one of the better…
Ruby 4.0 Is Here. Why Is AI Still Writing Ruby 3.0? June 17, 2026 Artificial intelligence has become an indispensable tool for Ruby developers. We ask AI assistants to write methods, refactor services, generate RSpec tests, explain stack traces, and even architect new features. For many developers, AI is no longer an experiment—it's part of … Continue reading Ruby 4.0 Is Here. Why Is AI Still Writing Ruby 3.0? →
Brighton Ruby 2026 will take place in a few days and the thoughtbot team will be
there to meet you all in real life, learn from all the great talks, and enjoy a
day by the English coast.
We love Brighton Ruby and enjoyed it for many years. It is a single-day,
single-track conference packed with great energy and great people.
This year we will have 5 thoughtbotters attending:

Aji will be at Brighton Ruby for the first time! They are always happy to talk
about ruby game development, recent conversations on
The Bike Shed, tracking reading lists on
Storygraph, or (let’s see
what else… ::rummages through bag of hobbies::) linguistic anthropology.
Come say hello!

Chad is thoughtbot’s…

We’ve talked a lot lately about governance, sustainability, accountability, and the future of Ruby Central. Those conversations were necessary, but they were largely conversations about the past.
This year’s RubyConf feels different.
This RubyConf is going to be a conversation about the future.

For the first time, we will be inducting the inaugural class of Ruby Fellows. Leaders from Ruby Alliance companies will gather to discuss how they will be collectively investing in Ruby's future. We'll officially launch Steering Committees that create new opportunities for community members to get directly involved. We'll host Ruby Runway and showcase founders building exciting new businesses on Ruby.
No…
Every developer has tools they rely on daily. The workflows they’ve built around them, the ways they’ve learned to move faster, debug smarter, and write better code – that kind of hands-on experience can be hard to put into words.
We’re collaborating with LinkedIn to make it easier for you to showcase your expertise with JetBrains IDEs on the world’s largest professional network. You can now connect your IDE to LinkedIn and let your real tool usage speak for itself.
Connect your IDE
IntelliJ IDEA, PyCharm, WebStorm, PhpStorm, Rider, GoLand, CLion, RustRover, and RubyMine are already supported via a free plugin, while support for DataGrip is coming soon.
In this blog post, we’ll…
Authors: Camila Mirabal, Tech writer, Arthur Objartel, Product Designer, Anton Senkovskiy, Account Manager, and Travis Turner, Tech Editor
Topics: AI, DX, Design, Figma, LLMs

Coding without design guidelines can leave teams with an inconsistent UI design and a complex feature development process. Here's how we built a design system for Currents that's readable by engineers and AI agents.
AI-assisted coding allows technical founders and lean engineering teams to try new languages and frameworks, write more code, and ship new designs. It's the perfect solution for validating ideas, building PoCs and MVPs. However, as adoption grows, it's time to drastically elevate the UX and UI.
When code can be regenerated faster than it can be understood, preserving it for sentimental or historical reasons no longer makes sense. What matters instead is stewardship: maintaining the system’s behavior, boundaries, and intent over time, regardless of how many times its internals are replaced.
leaflet.pub: The Death and Rebirth of Programming
Travis Dockter wanted a Ruby conference closer to home, so he made one. Today we chat about the ups and downs of putting together a brand new conference.
Show Notes
Sponsors
Lots of teams out there are still overpaying for their hosting and getting tripped up by traffic spikes. If you’re on one of those teams, you need a better autoscaler. Judoscale uses better metrics, gives you more control, and reacts faster than any other autoscaler. Learn more at https://judoscale.com/
Waiting over an hour for a test suite to finish is a productivity killer.
On a recent project, that was our reality.
Running the full local RSpec suite took almost 2 hours, making it difficult to get quick feedback and confidently iterate on changes. While there are many ways to optimize test performance including fixtures, request stubbing, faster tooling, and more, most of these options require significant effort to implement.
Instead, we explored a simpler approach: bringing parallel test execution to local development. The result was a much faster feedback loop (down to 5 minutes) and a significantly better developer experience.
Although our primary goal was to improve the local…

Gusto, like most companies building with LLMs, is amassing a LOT of software: one-off projects, Claude Artifacts, HTML visualizations, dashboards, and my own growing fleet of personal tools.
The agent loop made building 100 times easier, but deployment and operations still assume the old world. Your choices are weirdly binary:
- Static sites with data in the HTML
- A whole app with Dockerfile, Postgres, secrets, CVE mitigation, deploy pipeline, PagerDuty, and sharp edges.
When software was hard, most things were #2. Now, most things sit in the middle: stuff that’s real enough to need a database, but not real enough to deserve an app stack.
Neither fits, and this isn’t about engineers vs.…
Aji and Sally are back together again, this time to discuss the different apps they use to make their workflows and To Do lists easier and quicker to achieve.
Sally dives into the Notion calendar system which she uses to coordinate her many Google calendars, Aji looks back on using Jira to co-ordinate their international move, before they both reminisce about the benefits of using Alfred as people with ADHD.
—
There’s still time to secure your place at thoughtbot’s upcoming UK meet ups over the next month.
London Tech Leader Meetup - Tuesday June 23rd
Brighton Tech Leader Meetup - Wednesday June 24th
Brighton Ruby - Thursday June 25th
Evolve - Friday June 26th
Your hosts for…
Today we’re sharing the release candidate for Hanami 3.0, feature-complete and ready for testing. We’d love your help to give it a good workout before our final release—which, all going well, will be in just a couple of weeks!
What’s coming in 3.0
There’s a lot I’m excited for in 3.0, but I’ll save the full announcement for when it ships. For now, here’s where we’d love your help with testing.
Built-in i18n
Internationalization is now a built-in feature. Bundle the i18n gem and Hanami loads your translations and makes translation and localization helpers available across your views and actions. See Previewing i18n integration in Hanami 3.0 for details.
First-class mailers
We’ve…
We’ve been working to a pretty tight deadline as a team recently. We had a period of relative stability with a few concurrent projects on the go, and then we had this new elephant-sized project dropped on us. The entire team has rallied around it and everyone’s contributing exceedingly well to their own parts.
During the last few months of this project, I’ve been taking a look at how we can get to the point of verifying our changes faster after reading Accelerate for the second time. Trying to find answers for how we from “push” to knowing something works, and then shipping that with less time passing between all of those points.
A few things that our team has worked on to fix this has…
Quizzes are a fun! Well… I do think they are. Always up to learn new things. So how can you create one in with your favorite frameworks? In this article, I want to show how you can build a quiz witg Stimulus. It can be a good starting point for learn about a new customer in your SaaS or as a smart, little marketing tool (keep readers engaged/on your page). 💡
The quiz loads questions from a Rails endpoint, tracks answers in real-time, calculates results and submits them to your server. As always, the code can be found on GitHub.

This will be the result. Time to dust off that good ol’ computer science knowledge… 🤓
Building the data class
Here’s the QuizData class that handles the quiz…
jj’s whole deal is that it collapses many Git concepts (stashes, staging, fixups, in-progress rebases, conflicts) into a single unified model of working with history, which then lets you use the same tools to do all of those things. For example, to fix up an old commit you jump to it, edit it, and jump back to where you were; to fix a rebase conflict you jump to the conflicting commit, edit it, and jump back to where you were, using the same commands.
– Understanding Jujutsu bookmarks
This is such a good summary, I’m probably going to steal it when I try to explain jj in the future.
We’re excited to share that Shopify has joined the Ruby Alliance.
Shopify is a leader in the Ruby ecosystem, powering millions of businesses around the world and demonstrating what is possible when Ruby is trusted at global scale.
For years, Shopify has invested in Ruby through engineering leadership, open source contributions, performance improvements, and a deep commitment to the technologies that help power the community. Their work has benefited not only Shopify, but Ruby developers everywhere.
Their participation in the Ruby Alliance represents a meaningful investment in the long-term health, resilience, and sustainability of the Ruby ecosystem and the critical infrastructure it depends…
Some people are drawn to software engineering, and not everyone is like that. But a common characteristic among engineers (myself included) is the thrill of building something and seeing it work. Maybe it is not the whole system, but some piece of i
A recent Rails addition lets in_order_of group several values into one sort position. Build a support queue that floats active work to the top and sinks finished tickets, all in one query.
This is episode #02 of the Ruby Stained Glass Notes, a pop-up newsletter in which I write about the process of building a stained-glass panel celebrating Ruby. Today, we talk about how to choose glass, and how stained glass windows should follow the open-closed principle too.
This post was originally given as a talk at Rubycon IT 2026. The slides and video are also available.
It’s been a while since I first talked about rv, a Ruby manager for the future. I’d like give an update on what we’ve done since then, but I’m going to recap some of that earlier post first to give context for the updates. If you still remember what I said back then, you can jump to the new stuff right away. Either way, I’m excited to update you about the work that we’ve been doing, and show exactly how far we’ve gotten.
bundler isn’t enough
For the last ten years or so of working on Bundler, I’ve had a wish rattling around: I want a bigger, better dependency manager. It doesn’t just…
I’ve always been interested in coding as a craft - a thing to do with your
hands, your eyes and your mind. In many ways, I feel that a lot of the
satisfaction and accomplishment I get from making software comes from the
process itself, the doing of it, and not necessarily the end result. To quote
one of my favorite musicians:
Most vagabonds I knowed don’t ever want to find the culprit
That remains the object of their long relentless quest,
The obsession’s in the chasing and not the apprehending,
The pursuit you see and never the arrest.
This is also one of the reasons why the recent AI “revolution” doesn’t really
resonate with me. They say…
Several Net::IMAP commands accept a "raw data" argument that is sent
verbatim after validation to prevent command injection. However,
if a server does not support non-synchronizing literals, it may
still be possible to inject arbitrary IMAP commands inside
non-synchronizing literals.
### Details
Raw data arguments support embedded literal values, both synchronizing
and non-synchronizing. Non-synchronizing literals can only be safely
sent when the server advertises any of the `LITERAL+`, `LITERAL-`, or
`IMAP4rev2` capabilities. But raw data arguments do not verify server
support for non-synchronizing literals prior to sending.
Servers without support for non-synchronizing literals…
### Summary
Several Net::IMAP commands accept a raw string argument which is only
validated to prevent CRLF injection and then sent verbatim. If this
string is derived from user-controlled input, an attacker can force
the next command to be absorbed as a continuation of the first command.
This will cause the first command to eventually fail, but also prevents
it from returning until another command is sent (from another thread).
That other command will not return until the connection is closed.
### Details
`Net::IMAP::RawData` was hardened in v0.6.4, v0.5.14, and v0.4.24 to
reject string arguments that would smuggle an invalid literal-continuation
marker onto the wire (CVE-2026-42257,…
### Summary
Two `Net::IMAP` commands, `#id` and `#enable`, do not validate their
arguments. Arguments to either command could be used by an attacker
to inject arbitrary IMAP commands.
Please note that passing untrusted inputs to these commands is usually
inappropriate and expected to be uncommon.
### Details
When `Net::IMAP#id` is called with a hash argument, although the ID
field value strings are correctly quoted (escaping quoted specials),
they were not validated to prohibit CRLF sequences.
While `Net::IMAP#enable` does process its arguments for aliases, it
does not validate them as valid atoms (or as a list of valid atoms).
The `#to_s` value is sent verbatim.
### Impact
This is…
Hi, it’s Greg, bringing you this week’s changes in the Rails codebase.
Fix increment! with explicit query constraints
This pull request fix increment! / decrement! on models with query
constraints to include every query constraint column in the counter update.
self.class.update_counters(id, attribute => change, touch: touch)
Support a single composite primary key id in delete
This change aligns the class level delete method with destroy and now they both accept a single ID of a composite primary key.
Return an empty array from find([]) on a composite primary key
With this fix, Model.find([]) returns [] for a model with a composite primary key, the same as it does with a single primary…
Introduce a new mechanism for applications to prepare for ractor safety
…
[The lost episode 259] All Right, Rant Time - Debugging
[This episode from February 2024 was never published and recently discovered]
In today’s episode, Andrew kicks things off with a rant about tackling developer experience tasks at Podia, wrestling with GitHub actions, and Heroku deployment woes. Then the conversation takes a turn to the importance of debugging, the power of bash scripting, and the challenges of naming in programming, with Chris mentioning DHH’s insights from a live stream. They discuss Chris’s travel plans for RubyConf in Australia, other conferences coming up, and reminisce about their childhood love for trains and Thomas the Tank Engine. The episode wraps up with Chris and Andrew sharing advice and tips on writing…
It’s common for Rails applications to serve massive CSS files filled with unused Bootstrap, Tailwind, or custom utility classes as projects grow. This bloat isn’t just a developer annoyance—it has a real impact on your users. Every unused kilobyte adds milliseconds to page load time. In this post, we’ll explore what PurgeCSS is and how your Rails project can benefit from it.
What Is PurgeCSS and Why Should You Care?
PurgeCSS is a tool that analyzes your content and CSS, then removes unused CSS selectors, stripping away dead weight to leave you with lean, optimized stylesheets.
For example, if you’re using the full Bootstrap CSS framework (approximately 200KB) but only utilizing 30% of…
"How many yoga classes are booked today?"
Neeti answered straight away: 23.
It was confident. And it was wrong.
The real number was 62.
This gap is a good place to start, because it says a lot about what it takes toput an AI assistant on top of real production data. Everyone is worried about AImaking things up, and that's a real worry. In this case, 23 was a real count ofreal bookings in some sense. Neeti had simply counted the number of bookings ofthe first page.
Neeti is an AI assistant we built into NeetoCal.NeetoCal is the most affordable Calendly alternative. This blog is about howNeeti works, how we fixed the above-mentioned bug, and how we made it fast. Youdon't need to know anything…
The JRuby community is pleased to announce the release of JRuby 10.0.6.0.
JRuby 10.0.6.x targets Ruby 3.4 compatibility.
Thank you to our contributors this release, you help keep JRuby moving forward! @chadlwilson, @kares, @sampokuokkanen
Notable Changes:
Standard Library
- erb has been updated to 4.0.4.1 to address CVE-2026-41316. (#9389)
- jruby-openssl has been updated to 0.16.0, fixing many long-standing issues with SSLSocket. (#6455, #8935, #9390)
Java Integration
- Performance and consistency improvements for passing a block or proc as the implementation of a Java interface. (#1401, #9401, #9424)
…
23 Issues and PRs resolved for 10.0.6.0
#804 — June 11, 2026
Read on the Web
Ruby Weekly
📈 Small PRs, Big Speedups: The Ruby Performance Work You Almost Missed — A roundup of recent Ruby performance PRs covering strings, file handling, GC, concurrency, Prism, JITs, and more. It’s a neat snapshot of how much incremental performance work has landed in CRuby in the past year.
Maciej Mensfeld
Stop Juggling 5 Tools to Monitor One Rails App — Errors, performance, logs, uptime, host metrics — AppSignal covers your whole Rails stack. Auto-instruments Active Record, Sidekiq, Puma, and ActionView out of the box. Request-based pricing, unlimited seats. Free 30-day…
AppSignal sponsor
…
Performance problems in Rails applications are sneaky. Generally speaking, nobody opens tickets that say “my application is slower than it was last month (about 20%)”. What you do get instead are vague complaints from team members about a p95 latency that is climbing every week or a background job that used to take 2 seconds now taking 40 seconds to finish.
Nine times out of ten, the problem is going to be a query that used to be fast, and now it’s not. When that query was first written, it had 500 records in the table. Now, it’s got 500K records, and it’s running a full table scan on every page load. Each new row means slightly more scan time and latency. This increase in time continues…
To get from Zagreb, where I live, to Vienna, where RubyConf Austria was happening: drive 173km to Graz, take a right and go for another 198km. Sure, I’ve glossed over two country borders and some other details, but that’s mostly it. It’s pretty straightforward, unlike how the conference got me thinking about the future of Ruby conferences. But I’ll get to that. Day 1: The Vienna Ruby Meetup ...
Quizzes are a fun! Well… I do think they are. Always up to learn new things. So how can you create one in with your favorite frameworks? In this article, I want to show how you can build a quiz witg Stimulus. It can be a good starting point for learn about a new customer in your SaaS or as a smart, little marketing tool (keep readers engaged/on your page). 💡
The quiz loads questions from a Rails endpoint, tracks answers in real-time, calculates results and submits them to your server. As always, the code can be found on GitHub.

This will be the result. Time to dust off that good ol’ computer science knowledge… 🤓
Building the data class
Here’s the QuizData class that handles the quiz…
Recently, we had a crash in our NeetoCRMapplication.

As we can see in the screenshot, it looks like the error happened inneeto-widget-replay.js file.
At Neeto we have built an internal tool called NeetoReplaywhich captures users' activities in the browser. This helps us in debugging whenusers contact us for support or in investigating bugs. This is built on top ofrrweb. Just want to add that admins of theworkspace can completely opt out of NeetoReplay.
We had not changed anything in NeetoReplay for a while, so the error happeningin NeetoReplay was perplexing. Upon investigation, I found that the consoleindeed pointed to the neeto-widget-replay.js file. But I also knew that thefilename only…

We’re excited to announce that Ruby Central has been awarded a grant from Alpha-Omega to help improve the security of the Ruby open source ecosystem. With this support, Ruby Central is funding a team of Security Engineers in Residence to find real vulnerabilities in the gems the community depends on most, verify them, and bring maintainers reports worth their time.
The same AI tooling that helps developers ship faster has made finding vulnerabilities cheap. An attacker can act on a raw signal the moment a tool surfaces it. A responsible reporter cannot. Someone has to confirm the vulnerability is real, work out what it means in practice, and decide it is worth a maintainer's time. That work…

As part of our recent bylaw modernization, the Ruby Central Board has been exploring new ways to increase participation across the Ruby ecosystem while maintaining the accountability required to effectively operate a nonprofit organization.
Our goal in 2026 is to create more opportunities for contributors, community members, sponsors, and ecosystem leaders to help shape Ruby Central's future while preserving the Board's responsibility for stewarding the organization. And to do this as quickly as possible.
Ruby Central governs its own suite of voluntary programs, infrastructure, education, and initiatives that support the Ruby ecosystem. It does not govern the Ruby language itself.
Guiding…
Our Rails developer, Jaison Coelho, shares some of his favorite talks from the Tropical on Rails conference this year and why he keeps going back.
Continue Reading
How ActiveModel::Attributes gives tableless Rails objects type casting, defaults, and a Rails-native attribute system, and where the API still needs more support.
There's a moment at every RubyConf that we quietly look forward to: the smell of fresh coffee drifting through the venue as attendees start their mornings, and the sight of a room full of name badges swaying from lanyards as people connect, collaborate, and find their people. For years, that moment has been made possible by GitLab.
GitLab has been a steadfast supporter of the Ruby community as both our coffee sponsor and name badge lanyard sponsor, and we don't take that for granted. Sponsorships like these are easy to overlook; they don't come with a keynote slot or a giant booth, but they are woven into the fabric of the conference experience in ways that matter deeply.
Every cup of coffee…
Rachael interviews the new host of the show, David Hill, to discuss his history with Ruby, his love for podcasting, and how much he loves meetups and conferences.
Show Notes
Sponsors
Lots of teams out there are still overpaying for their hosting and getting tripped up by traffic spikes. If you’re on one of those teams, you need a better autoscaler. Judoscale uses better metrics, gives you more control, and reacts faster than any other autoscaler. Learn more at https://judoscale.com/
The Hidden DSL Inside Every Rails Model June 10, 2026 Most Rails developers use belongs_to, has_many, scope, and validates every day. We type them almost without thinking. class User < ApplicationRecord belongs_to :company validates :email, presence: true scope :active, -> { where(active: true) } end But here's something interesting: None of those are Ruby keywords. … Continue reading The Hidden DSL Inside Every Rails Model →
RubyGems 4.0.14 includes enhancements and Bundler 4.0.14 includes 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.14
RubyGems Release Notes
Enhancements:
- Add executables and bindir validation to the gem installer. Pull request #9595 by hsbt
- Strip C1 control characters from displayed gem text. Pull request #9597 by hsbt
- Installs bundler 4.0.14 as a default gem.
Bundler Release Notes
Bug fixes:
- Preserve per-source cooldown when converging sources from the lockfile. Pull request #9601 by bryanwoods
- Don’t exclude the locked version…
Manual Installation
To install RubyGems…
## Summary
When an application uses OAuth2::Client (typically via an
OAuth2::AccessToken) and the configured authorization server returns
a redirect whose Location header is a protocol-relative URI of the
form //attacker.example/leak, OAuth2::Client#request resolves the
redirect with response.response.env.url.merge(location). Per
RFC 3986 §5.2, an input that starts with // is a network-path reference
and replaces the authority of the base URL:
URI("http://idp.trusted/userinfo").merge("//attacker.example/leak")
returns http://attacker.example/leak. The recursive request(verb,
full_location, req_opts) call then re-sends the request to the attacker
host while preserving the Authorization:…
## Summary
When an application uses OAuth::Consumer to request OAuth 1.0 request
tokens or access tokens, the token request helper follows 300..399
redirects returned by the OAuth server. In affected versions,
OAuth::Consumer#token_request parses the raw Location header, follows
the redirect recursively, and can mutate the consumer's configured
site when the redirect points to a different host with the same path.
The result is a cross-origin signed-request disclosure primitive: if an OAuth
server token endpoint returns a redirect whose target an attacker controls,
the client can re-sign the token request and send OAuth 1.0 request metadata,
including the OAuth signature, nonce, timestamp,…

Version 6.1.5 of the Passenger application server has been released. This release contains no changes and addresses an ABI break in Ubuntu's Nginx packages.
Installing 6.1.5
Please see the installation guide for advice on getting started with Passenger. Coming from a language other than Ruby, Python, Meteor or Node? Even if we didn't write a specific tutorial for your language, we made a generic guide that shows you the steps.
Upgrading to 6.1.5
We strongly advise staying up to date with the latest version.
Check out our upgrade guides for the different platforms:
Please be aware that you can enjoy enterprise features and sponsor the open…
When you first reach for an LLM library, the only question is whether it works. Can it call the model, parse the response, run a tool. Once your app is actually in production, the questions change. Is it fast? Can I see what it’s doing when something goes wrong? Can I send its traffic through my own infrastructure instead of straight out to the provider?
I released RubyLLM 1.16 today. It answers these production questions.
The three headline features are about speed, visibility, and control: tools that run concurrently, structured events for everything RubyLLM does, and a configurable base URL for every native provider. None of them change how you write your app. All of them matter the…
Authors: Gleb Stroganov, Product Designer, Varya Nekhina, Account Manager, and Travis Turner, Tech Editor
Topics: Case Study, Developer Products, Product development, Developer marketing, Google Analytics

A designer and an engineer shipped a production MVP in four weeks on Rails + Inertia. In this post, we share our agentic coding stack, the skills we built, and why it clicked.
We shipped a full production MVP in 4 weeks with a team of two Martians: a designer and an engineer. In this post, we're sharing the experience, lessons learned, the open source skills we developed, and why Rails + Inertia is now our go-to stack for agentic coding.
This is episode #01 of the Ruby Stained Glass Notes, a pop-up newsletter in which I write about the process of building a stained-glass panel celebrating Ruby.
It’s common for Rails applications to serve massive CSS files filled with unused Bootstrap, Tailwind, or custom utility classes as projects grow. This bloat isn’t just a developer annoyance—it has a real impact on your users. Every unused kilobyte adds milliseconds to page load time. In this post, we’ll explore what PurgeCSS is and how your Rails project can benefit from it.
What Is PurgeCSS and Why Should You Care?
PurgeCSS is a tool that analyzes your content and CSS, then removes unused CSS selectors, stripping away dead weight to leave you with lean, optimized stylesheets.
For example, if you’re using the full Bootstrap CSS framework (approximately 200KB) but only utilizing 30% of…
If you’ve ever written a test for your code, you’re probably familiar with
typical test framework methods: test/it to define test cases, and
assert/expect to make assertions about the behavior of your code.
However, I want to highlight a less commonly used method: in other languages or
frameworks it goes by other names, but in Ruby’s minitest it’s called skip.
In this post, I’ll cover what skip does, when it may be useful, and, most
importantly, when you should probably use something else.
Just skip to the good stuff
Okay, so what does skip do? Put simply, it allows you to not run a test.
More concretely: in minitest, none of the test code after skip is run, an
S will be printed…
The JRuby community is pleased to announce the release of JRuby 9.4.15.0.
JRuby 9.4.15.x targets Ruby 3.1 compatibility.
Thank you to our contributors this release, you help keep JRuby moving forward!
With this release, JRuby 9.4 moves into end-of-life (“EOL”). This means that future releases of 9.4.x will only be provided as needed by commercial JRuby users.
Get in touch with us if you require long-term support options for the JRuby 9.4.x series.
38 Issues and PRs resolved for 9.4.15.0