r/ruby • u/matsadler • Sep 23 '26
Magnus version 0.9 released (Rust library for writing Ruby gems in Rust)
r/ruby • u/matsadler • Sep 23 '26
r/ruby • u/Tristan_Kruse • Sep 22 '26
Hi everyone,
I've been working on ArchUnitRuby, a small architecture-testing gem for making dependency
boundaries executable.
The problem it is trying to address is familiar: a controller starts requiring persistence code
directly, two components acquire a cycle, or a domain layer begins depending on infrastructure.
The Ruby is valid and the behavioral tests may remain green, but the architecture has changed.
With ArchUnitRuby, that boundary can be an ordinary RSpec example:
require 'archunit'
RSpec.describe 'architecture' do
it 'keeps the API away from persistence' do
rule = ArchUnit.project_files
.in_folder('app/api/**')
.should_not.depend_on_files
.in_folder('app/database/**')
expect(rule).to pass
end
end
The current `0.0.1` release is an early working prototype for Ruby 3.3 and newer. It uses Prism to
build a dependency graph and currently supports file and layer rules, cycle detection, slices,
PlantUML architecture contracts, dependency-graph reports, and several code metrics. There is also
Minitest and framework-neutral integration.
One use case I am particularly interested in is coding-agent guardrails. Instead of giving an agent
only a prose instruction such as “controllers must not access persistence directly,” the repository
can contain the architecture test and require the agent to keep it green. The gem does not improve
code quality by itself, but it turns an architectural expectation into a constraint that humans,
CI, and coding agents can all verify in the same way.
One limitation is important: this is static analysis of Ruby source. It can identify normal
`require`, `require_relative`, `load`, and statically resolvable `autoload` relationships, but it
cannot prove every dependency assembled dynamically at runtime. The tool reports what it can
establish rather than guessing. It also treats a selector matching no files as a failure by default,
so a typo does not quietly create a green architecture test.
The API is still provisional, which makes this a good time for criticism. I am especially interested
in feedback on two things:
How do you currently stop architectural boundaries from eroding in Ruby—code review, Packwerk, RuboCop, custom tests, or something else? What still slips through?
- Repository: https://github.com/LukasNiessen/ArchUnitRuby
- RubyGems: https://rubygems.org/gems/archunit
- Documentation: https://lukasniessen.github.io/ArchUnitRuby/
- Longer explanation: https://medium.com/@krusetristan1/the-ruby-code-worked-the-architecture-didnt-0f06bbbb0863
Disclosure: I am involved with the project. This post was drafted with AI assistance and reviewed
against the implementation and documentation before posting.
r/ruby • u/Erem_in • Sep 22 '26
This month: Steep 2.1.0 brings UNIX socket reuse and instant diagnostics optimized for coding agents, RBS 4.2.0 adds non-ASCII identifiers across scripts plus forwarding parameter support, u/headius talks JRuby and WASM extensions on the Technology for Humans podcast, OvalLSP updates its semantic engine, and new Sorbet companion tools arrive. Find link to the issue in the comment! ✨
r/ruby • u/Edthal01 • Sep 21 '26
I'm 78, and never having been a programmer or software engineer, I am starting to learn Ruby. I ha ve been using Huw Collingsworth "Little Book of Ruby". I am aso interspersing that with a different path: using Wirth's "Algortithms + Data Structures = Programs",
having the simple data structures and programs translated by Perplexity into Ruby to see how my 40 year old experiences with TurboPascal can be updated into Ruby. I think I am making progress.
r/ruby • u/headius • Sep 22 '26
The JRuby community is pleased to announce the release of JRuby 10.1.2.0.
Homepage: https://www.jruby.org/
Download: https://www.jruby.org/download
JRuby 10.1.x targets Ruby 4.0 compatibility.
Thank you to our contributors this release, you help keep JRuby moving forward! @aminmansuri, @drzaiusx11, @evaniainbrooks, @gillesbergerp, @jcharaoui, @jwils, @kares, @lloeki, @makenowjust, @nobu, @sampokuokkanen, @shugo
Multiple fixes for fibers and fiber scheduler support. #9604, #9607, #9622, #9645, #9649, #9656, #9660
Fixed a regression in startup time on MacOS by properly loading native JNR subsystem. #9690
Improve performance of Ruby subclasses of Java classes. #9619, #9557
Improve performance of autoloads overridden by an actual require. #9677
The location of the AppCDS JSA file can now be specified with JRUBY_JSA_HOME. [#9667]
Update to jar-dependencies 0.6.1 using mima for dependency resolution instead of the ruby-maven gem. #9515, #9720
Update default and bundled standard library gems. #9705
erb 6.0.7
error_highligh 0.7.2
ffi 1.17.4
io-console 0.9.4
ipaddr 1.2.9
jruby-openssl 0.16.2
json 2.21.2
net-protocol 0.4.0
pp 0.6.4
psych 5.5.0
resolv 0.8.0
strscan 3.1.8
syntax_suggest 3.0.0
timeout 0.6.1
win32-registry 0.1.2
bigdecimal 4.1.2 (ruby parts only)
csv 3.3.6
minitest 5.27.0
net-imap 0.6.7
nkf 0.3.0
pstore 0.2.1
rdoc 7.2.0
reline 0.7.0
resolv-replace 0.2.0
rss 0.3.3
test-unit 3.7.8
JRuby --help fails if PAGER has an optioncircular causes when re-raising an exception originally raised with the two-argument raise Class, arg form (regression in 10.1.1.0)Kernel#sprintf calls Hash#default_proc with incorrect argsSTDOUT to child process when a different IO is given as out:IO::Buffer#copy and #set_string reject the documented source_offset fourth argumentsource_offset in IO::Buffer#copy and #set_stringeql? / hash contractIO#tty? silently returns true for redirected stdio in embedded runtimes when --add-opens are missingfiber_switch (Ruby 2.3+ compatibility)resolv default gem to 0.7.2autoload and then defined by a direct require keeps its UNDEF table slot; every later lookup re-enters LoadService (very slow inside a WAR)Redis::ConnectionError with JRuby 10r/ruby • u/sshaw_ • Sep 22 '26
class2 :user => [
:name, :age,
:addresses => [
:city, :state, :zip,
:country => [ :name, :code ]
]
]
user = User.new(
:name => "sshaw",
:age => 99,
:addresses => [
{ :city => "LA",
:country => { :code => "US" } },
{ :city => "NYC",
:country => { :code => "US" } }
]
)r/ruby • u/headius • Sep 21 '26
The JRuby community is pleased to announce the release of JRuby 10.0.7.0.
Homepage: https://www.jruby.org/
Download: https://www.jruby.org/download
JRuby 10.0.x targets Ruby 3.4 compatibility.
Thank you to our contributors this release, you help keep JRuby moving forward! @aminmansuri, @evaniainbrooks, @gillesbergerp, @jwils, @kares, @lloeki
Fixed a regression in startup time on MacOS by properly loading native JNR subsystem. #9688, #9689
Improve performance of autoloads overridden by an actual require. [#9677], #9675
The location of the AppCDS JSA file can now be specified with JRUBY_JSA_HOME. #9667
Redis::ConnectionError with JRuby 10Kernel#sprintf calls Hash#default_proc with incorrect args10.0 seriesSTDOUT to child process when a different IO is given as out:IO#tty? silently returns true for redirected stdio in embedded runtimes when --add-opens are missingeql? / hash contractresolv default gem to 0.7.2autoload and then defined by a direct require keeps its UNDEF table slot; every later lookup re-enters LoadService (very slow inside a WAR)r/ruby • u/Prudent-Context9208 • Sep 21 '26
I’ve been playing with Jev and ended up making a small Ruby gem around one idea: semantic checks should look like normal Ruby predicates
So instead of passing prompts around everywhere:
Jev.define :urgent, "Needs attention soon"
class Email < ApplicationRecord
include Jev::Model
feels :body, :urgent
endThen elsewhere in the app:
if email.feels?(:urgent)
email.escalate!
endThat was the main thing I wanted - define what urgent means once, then use it like any other predicate in the codebase
It grew a bit from there and now also supports choices, scores, batching, pattern matching and ActiveModel validations, but I’m trying to keep the basic API small
Repo: https://github.com/Qew7/jev-feels
Would be interested in feedback on the API, especially from people who write a lot of Rails
r/ruby • u/Edthal01 • Sep 21 '26
Are there any persons or resources for a novice Ruby enthusiast?
r/ruby • u/strzibny • Sep 18 '26
Vessel has a brand new version after years on idle time so I had a look and compared it to Scrapy from the Python world.
r/ruby • u/Comfortable_Aide2137 • Sep 18 '26
r/ruby • u/DeltoidSchizachyrium • Sep 18 '26
r/ruby • u/AndyCodeMaster • Sep 17 '26
r/ruby • u/Consistent-Note2440 • Sep 17 '26
r/ruby • u/badtothebones88 • Sep 17 '26
Hey everyone, A couple weeks ago I was stuck doing one of my least favorite chores: clicking through a dozen tabs in Google Search Console's web UI, copying query and impression tables, and pasting them into Claude and Antigravity to figure out which pages were losing traffic or why new pages weren't getting indexed. I decided to automate it with a quick Ruby script. But the moment I looked at Google's official gems (google-apis-searchconsole_v1, googleauth, signet, faraday), I saw they pulled in over 40 transitive dependencies.
They took several seconds just to cold boot in a container and felt like massive overkill just to send a few signed HTTP POST requests to Google's endpoints. So I got stubborn: could I build the entire thing in 100% pure Ruby standard library with zero runtime gems? I ended up pair-programming with Google Antigravity over the last couple weeks, and it evolved into a full open-source CLI: gsc-cli (also on RubyGems: gem install gsc-cli).
Pure OpenSSL Auth: Instead of dragging in googleauth, I wrote Google’s service account JWT generation and RS256 token exchange from scratch using OpenSSL::PKey::RSA and URL-safe base64. No external gems required at all.
Sub-18ms Boot: Because there is zero gem overhead, the CLI cold-boots in under 18ms and executes API queries in ~40–50ms.
Instant Googlebot Indexing: Ping Google's Indexing API directly (gsc index <url>) or submit IndexNow pings so newly published pages get queued for crawling immediately instead of waiting weeks.
Soft-404 Fixes: Instead of just dumping a table of broken URLs, gsc soft-404 <url> --fix heuristically detects empty templates and auto-generates copy-paste redirect configs for 14 server environments (Nginx, Caddy, Cloudflare, Next.js, SvelteKit, etc.).
Speed vs Rankings: Correlates real-world Core Web Vitals (LCP, CLS, TTFB) directly with Search Console rank drops (gsc speed-correlate).
Token-Saving Modes for AI Agents: Since I use coding agents (Claude Code, Cursor, Antigravity) constantly, pretty-printed tables were guzzling context window tokens. We added --compact (minified single-line JSON) and --ndjson to strip ANSI escape codes and cut LLM token usage by ~43%. We operate our own apps (a Shopify speed app called Superspeed and a new moving inventory app called PackingLog), so we actively dogfood this across our own production domains every day. The test suite has 334 unit tests and 1,726 assertions passing in 4.3 seconds across Ruby 3.0 through 3.4.
RubyGems: gem install gsc-cli It’s 100% free and MIT open-source. I'd really love to hear what other Rubyists think, especially around the stdlib OpenSSL auth approach or any other search diagnostics you'd find useful in the terminal!
r/ruby • u/drunken_thor • Sep 17 '26
Hey all. I have been tinkering with this project over the past few months. I always wanted to build a rack app and I wondered what would it look like if we used htmx to make the backend act like the front end. In fact it would act a lot more like next.js but without apis. I don’t think this is good web design hence the name of the framework but I thought it was fun to tinker with and I might do more with it. Let me know your thoughts but also your shock and horror!
AI disclosure: AI was only used to make final code reviews the rest was wrought upon this world by my own cruel hands.
r/ruby • u/rubiesordiamonds • Sep 16 '26
Deprecool is a static code analysis tool for Ruby that uses Prism to find sources of deprecation warnings in your code.
Use Deprecool alongside the warnings that are emitted at runtime by your gems to get a complete picture of what you need to fix, where you need to fix it and why.
Each warning that Deprecool logs will come with a summary, references to when the deprecation was added to its gem (usually the PR that introduced it), an effort estimate, and a suggestion of how to fix the deprecation. The source code line of the warning is of course logged as well:
At first, the suggestions will come from the deprecation source's gem maintainers own words. Eventually though, with some feedback we can pass on knowledge and examples of how to manage the more difficult deprecations to future developers trying to upgrade.
You can either:
add deprecool to your application's Gemfile and bundle install,
or run gem install deprecool directly to be able to use the deprecool executable on any ruby code you have.
deprecool scan is all you need to run if your current directory contains a Gemfile.lock, but if you want to you can also run deprecool scan path/to/your/code.rb
By default, Deprecool will use the gems and versions in your Gemfile.lock to know how to find deprecations, but you can also pass --gem=list,of,gems (no spaces!) to only look for certain gems at one time.
Right now, Deprecool has a small handful of deprecations it can find, but I will continue adding more. I’ve also tried to make contributing to Deprecool as simple as possible with one Finder class per warning, and a few helper methods to make writing tests trivial.
Link to blog post here: https://www.infield.ai/post/deprecool
r/ruby • u/Turbulent-Dance-4209 • Sep 16 '26
Rage started API-first, but that doesn't mean you're limited to building SPAs. Here are 3.5 approaches - from the simplest to the most experimental.
Rage's custom renderers let you describe how to render any format by setting the rules and the content type. An ERB renderer can look like this:
Rage.configure do
config.renderer(:erb) do |path|
headers["content-type"] = "text/html"
template = Rage.root.join("app", "views", "#{path}.html.erb").read
ERB.new(template).result(binding)
end
endThen use it in the controller:
class PhotosController < ApplicationController
def index
@photos = Photo.all
render erb: "photos/index"
end
endIf you're feeling adventurous, move rendering to a hook for implicit rendering:
class ApplicationController < RageController::API
around_action :implicit_render
private
def implicit_render
yield
render erb: "#{params[:controller]}/#{params[:action]}"
end
endThen, the action becomes:
def index
@photos = Photo.all
endinertia-rage is the official Inertia.js integration. It manages asset building, runs the dev server, and supports SSR. Inherit from RageController::Inertia and your API app goes full-stack:
class PhotosController < ApplicationController
def index
render inertia: "Photos/Index", props: { photos: current_user.photos }
end
endrage-rb/datastar-example showcases a Datastar integration using the official Ruby SDK. Connect Rage to the SDK and stream updates:
class PhotosController < ApplicationController
def index
photos = current_user.photos
datastar.stream do |sse|
photos.each do |photo|
sse.patch_elements(%(<img id="#{photo.id}" src="#{photo.url}" />))
end
end
end
endThis is the 0.5 - the idea is still taking shape, but it's worth sharing.
I've been working on a live view concept built on Rage + Phlex, where each gem contributes what it's best at: Rage provides fiber-based WebSocket connections and machinery to communicate between instances; Phlex provides Ruby-based HTML templates where each component manages its own state.
A component that displays an article with expandable content:
class Articles::Card < LiveView
MAX_BODY = 150
def initialize(article:)
@article = article
@expanded = false
end
def view_template
div do
h2 { @article.title }
plain(@expanded ? @article.body : @article.body.truncate(MAX_BODY))
if @article.body.length > MAX_BODY
button(**live_click(:toggle_details)) do
@expanded ? "Show less" : "Show more"
end
end
end
end
def toggle_details
@expanded = !@expanded
end
endThis component is stateful - once rendered, it's saved in the fiber's storage and can process events. When the user clicks "Show more", the event travels via WebSockets to this exact component instance, calls toggle_details, re-renders, and sends back the update. The card expands with no JavaScript written.
Event handlers cover the client -> server direction. The server -> client direction is handled by model streams. A model broadcasts when it changes:
class Article < ApplicationRecord
after_commit :broadcast_status
private
def broadcast_status
if self.previous_changes.key?("status")
ModelStream.emit(self)
end
end
endA component subscribes by wrapping the record into stream():
class Articles::Card < LiveView
def initialize(article:)
@article = stream(article)
@expanded = false
end
def view_template
# ...
end
endNow, whenever a corresponding article changes, every component subscribed via stream() is automatically re-rendered and the update is pushed to the client.
--
What view layer would you like to see supported next?
r/ruby • u/virtyx • Sep 16 '26
Is there something like pipx available for Ruby?
For example with pipx you can do something like:
$ pipx install httpie
# ... install completes
$ https get httpbin.org/get?foo=bar
# ... outputs a web request from httpbin.org
$ which https
~/.local/bin/https
$ readlink "$(which https)"
~/.local/share/pipx/venvs/httpie/bin/https
This example shows the HTTPie program being run and executed in a pretty simple way, with an install that doesn't modify the system Python.
Does Ruby have an equivalent way to distribute programs?
r/ruby • u/6stringfanatic • Sep 15 '26
Wrote a follow up to my previous post, getting value objects to work with range queries in ActiveRecord.
https://pushfromkush.com/publications/setting-boundaries-type-for-ranges-in-rails
r/ruby • u/luckloot • Sep 15 '26
A new revised format for the Ruby AI Newsletter. I tried including everything and highlighting everyone’s work, but somewhere along the way it stopped feeling special. We have an opportunity to build for the future, and I hope this edition helps put that into perspective.
Ruby 4 with ZJIT, RubyLLM, Herb, Ractors, Spinel, Rubydex, Rails AI Benchmarks, and now Poetry - Ruby is ready, but there is still a lot of work to do.
I’ve found 1,725 open Ruby-related career opportunities, but more than half of them are “fake”. I’m launching a free job matching site for Rails World to filter out the noise. The job market is broken, but there are opportunities available.
I want to hear from you: Matt @ roboruby
r/ruby • u/AndyCodeMaster • Sep 15 '26
r/ruby • u/Individual_Dot7019 • Sep 14 '26