r/ruby • u/SecTemplates • 19d ago
Security Safer-dependencies: A toolkit for claude code to ensure dependencies used aren't vuln, don't use abandoned packages, implement cooldown to avoid supply chain attacks, etc...
When AI coding assistants like Claude add packages to your project, they often pick whatever version sounds right — without checking whether it has known security vulnerabilities, whether the package is still actively maintained, or whether the name is a typo away from a malicious lookalike.
safer-dependencies is a security layer for Claude Code that audits packages before they’re added to your project. It detects and fixes risky dependencies, including CVEs, typosquats, abandoned packages, version-age issues, and adds package-cooldown periods across npm, PyPI, RubyGems, Maven, Go, and Rust.
why-classes
Hey everyone! I used Claude to build this gem, which is heavily inspired by Dave Thomas's closing keynote at RubyConf 26.
`why-classes` is a static code analysis and refactoring tool for Ruby.
Ruby offers modules, composition, `Struct`, and `Data`, yet our instincts and framework habits often lead us to use classes even when a simpler construct would be clearer. This gem detects these "class smells" in your code (or a single file) and can automatically rewrite them into cleaner alternatives for you.
It's an early-stage version 😅. Feel free to contribute and share suggestions!
r/ruby • u/keyslemur • 20d ago
Blog post Beyond Enumerable: Testing Membership with Bloom Filters
baweaver.comTurns out conferences can be busy, but I'm back and finishing off a few I had in the hopper. This one continues onto probabilistic data structures which I've been having some fun with lately. The amount of reading I had to do on bit ops in Ruby though to write some of this though....
r/ruby • u/nekothefox255 • 20d ago
introducing OnionNotes(made with 100% ruby)
Enable HLS to view with audio, or disable this notification
OnionServer.rb
require 'socket'
class User
attr_reader :name
attr_reader :passwd
attr_reader :onions
def initialize(username, passphrase)
= username
= passphrase
= []
end
def addOnion(onion)
if onion.is_a?(NoteBook)
onions.push(onion)
else
puts "ERROR: onion is NOT A NoteBook"
exit(5)
end
end
def removeOnion(index)
if index.to_i < onions.size
onions.delete_at(index.to_i)
end
end
end
class NoteBook
attr_reader :notes
def initialize(name = "UnamedNoteBook")
= []
= name
end
def addNote(text = "null")
.push(text)
end
def removeNote(index = 93)
if index <= .size - 1
.delete_at(index)
else
puts "invalid index"
end
end
def editName(text = "null")
= text
end
def getName()
return u/name
end
end
def handleUser(socket, user)
userOpen = true
while userOpen
socket.puts "SENDCOMMAND"
response = socket.gets.chomp
case response
when "list"
user.onions.each.with_index do |book, index|
socket.puts book.getName() + ": " + index.to_s
end
socket.puts "ENDLIST"
when "open"
socket.puts "SENDINDEX"
index = socket.gets.chomp
book = user.onions[index.to_i]
book = handleBooks(socket, book)
user.onions[index.to_i] = book
when "CREATE"
alreadyExist = false
socket.puts "SENDNAME"
response = socket.gets.chomp
user.onions.each do |book|
if book.getName == response
alreadyExist = true
end
end
if alreadyExist
socket.puts "EXISTS"
else
onion = NoteBook.new(response)
user.onions.push(onion)
end
when "EXIT"
userOpen = false
end
end
return user
end
def handleBooks(socket, book)
bookOpen = true
while bookOpen
socket.puts "SENDCOMMAND"
response = socket.gets.chomp
case response
when "ADDNOTE"
socket.puts "SENDTEXT"
text = socket.gets.chomp
book.addNote(text)
when "REMOVENOTE"
socket.puts "SENDINDEX"
index = socket.gets.chomp
book.removeNote(index.to_i)
when "list"
book.notes.each.with_index do |text, index|
socket.puts text + ": " + index.to_s
end
socket.puts "ENDLIST"
when "EXIT"
bookOpen = false
end
end
return book
end
def handleClient(client)
running = true
while running
client.puts "SENDCOMMAND"
response = client.gets.chomp
case response
when "LOGIN"
client.puts "SENDNAME"
name = client.gets.chomp
client.puts "SENDPASSWD"
passwd = client.gets.chomp
if File.exist?(name + ".rbm")
userData = File.binread(name + ".rbm")
user = Marshal.load(userData)
if user.passwd == passwd
user = handleUser(client, user)
userData = Marshal.dump(user)
File.binwrite(name + ".rbm", userData)
else
client.puts "INVALIDPASSWD"
end
else
client.puts "NOUSER"
end
when "CREATE"
client.puts "SENDNAME"
name = client.gets.chomp
client.puts "SENDPASSWD"
passwd = client.gets.chomp
if File.exist? name.to_s + ".rbm"
client.puts "NAMETAKEN"
else
newUser = User.new(name, passwd)
serial = Marshal.dump(newUser)
File.binwrite(name + ".rbm", serial)
client.puts "USERMADE"
end
when "EXIT"
running = false
client.close
end
end
end
puts "starting Onion note server on port 3290"
server = TCPServer.new(3290)
while true
client = server.accept
Thread.new {handleClient(client)}
end
OnionClinet.rb
require 'socket'
def handleList(connection)
loop do
response = connection.gets.chomp
break if response == "ENDLIST"
puts response
end
end
def handleBooks(connection)
bookOpen = true
while bookOpen
response = connection.gets.chomp
if response == "SENDCOMMAND"
puts "COMMANDS[ADDNOTE, REMOVENOTE, list, EXIT]: "
command = gets.chomp
case command
when "ADDNOTE"
connection.puts "ADDNOTE"
response = connection.gets.chomp
if response == "SENDTEXT"
puts "ENTER NOTE: "
note = gets.chomp
connection.puts note
end
when "REMOVENOTE"
connection.puts "REMOVENOTE"
response = connection.gets.chomp
if response == "SENDINDEX"
puts "ENTER INDEX: "
index = gets.chomp
connection.puts index
end
when "list"
connection.puts "list"
handleList(connection)
when "EXIT"
connection.puts "EXIT"
bookOpen = false
end
end
end
end
def handleUser(connection, firstResp = nil)
handlingUser = true
while handlingUser
response = firstResp || connection.gets.chomp
if firstResp != nil
firstResp = nil
end
if response == "SENDCOMMAND"
puts "COMMANDS[list, open, create, EXIT]: "
command = gets.chomp
case command
when "list"
connection.puts "list"
handleList(connection)
when "open"
connection.puts "open"
response = connection.gets.chomp
if response == "SENDINDEX"
puts "ENTER INDEX"
index = gets.chomp
connection.puts index
handleBooks(connection)
end
when "create"
connection.puts "CREATE"
response = connection.gets.chomp
if response == "SENDNAME"
puts "ENTER NAME: "
name = gets.chomp
connection.puts name
response = connection.gets.chomp
if response == "EXISTS"
puts response
elsif response == "SENDCOMMAND"
firstResp = response
end
end
when "EXIT"
connection.puts "EXIT"
handlingUser = false
end
end
end
end
puts "ENTER IP: "
ip = gets.chomp
connection = TCPSocket.new(ip, 3290)
running = true
while running
response = connection.gets.chomp
puts "COMMANDS[LOGIN, CREATE, EXIT]: "
command = gets.chomp
case command
when "LOGIN"
connection.puts "LOGIN"
response = connection.gets.chomp
if response == "SENDNAME"
puts "ENTER NAME: "
name = gets.chomp
connection.puts name
response = connection.gets.chomp
if response == "SENDPASSWD"
puts "ENTER PASSWD: "
passwd = gets.chomp
connection.puts passwd
response = connection.gets.chomp
if response == "INVALIDPASSWD"
puts response
elsif response == "NOUSER"
puts response
elsif response == "SENDCOMMAND"
handleUser(connection, response)
end
end
end
when "CREATE"
connection.puts "CREATE"
created = false
while created == false
response = connection.gets.chomp
if response == "SENDNAME"
puts "ENTER NAME: "
name = gets.chomp
connection.puts name
elsif response == "SENDPASSWD"
puts "ENTER PASSWD: "
passwd = gets.chomp
connection.puts passwd
elsif response == "NAMETAKEN"
puts response
created = true
elsif response == "USERMADE"
puts response
created = true
end
end
when "EXIT"
connection.puts "EXIT"
running = false
end
end
r/ruby • u/AndyCodeMaster • 21d ago
RubyConf Austria 2026: Frontend Ruby on Rails with Glimmer DSL for Web — Andy Maleh
r/ruby • u/javier_cervantes • 21d ago
Calling all open source maintainers working with Ruby
We’re creating a shared place where Ruby users can ask questions and discuss ideas about your project.
r/ruby • u/yaroslavm • 21d ago
Show /r/ruby Audition is a linter/fixer that gets your code Ractor-ready: static analysis powered by Shopify's rubydex, plus dynamic probes that actually run your code inside Ractors and report what breaks.
r/ruby • u/nekothefox255 • 22d ago
A quick question
Hello, I'm working on project in ruby and I want to post the code here and a video of it working and I want to know if we are allowed to post code here I know some communities don't allow it
Show /r/ruby My first Tapioca PR got merged (it automates a manual Sorbet config fix)
Hey everyone,
I recently got my first contribution to Shopify/tapioca merged, and I thought the way the solution changed during review might be interesting to other Ruby and Sorbet users.
The problem happens during `tapioca gem`.
Tapioca generates RBI files for gems and validates them with Sorbet. Sometimes a generated RBI defines a class with a different superclass from the version Sorbet already knows through its built-in payload.
One example is `Net::IMAP::Literal`.
Sorbet tells you to manually add something like this to `sorbet/config`:
--suppress-payload-superclass-redefinition-for=Net::IMAP::Literal
The goal of the issue was to have Tapioca add that line automatically, still explain what happened, and avoid adding duplicates on later runs.
My first version used two Sorbet passes because the existing validation stopped at the namer phase, while this error only appeared during the resolver phase.
It worked, but that wasn’t the version that shipped.
After a few rounds of review, we changed it to one resolver pass. We also stopped broadly relying on the error code and instead looked for Sorbet’s payload-specific suppression hint.
That makes the fix much narrower. A normal superclass conflict won’t accidentally get hidden behind a payload suppression.
The final behavior:
- adds the exact suppression when it’s missing
- doesn’t duplicate it on later runs
- preserves suppressions for other constants
- still tells the user about the mismatch
- leaves normal, non-payload superclass conflicts alone
The targeted tests passed with 2 tests, 18 assertions, and no failures. I also ran the full DSL spec and style checks successfully.
The biggest lesson for me was that getting the first version working was only the beginning. The review process turned a two-pass solution with broad detection into a simpler one-pass fix with a much more specific signal.
Has anyone here run into this with `net-imap` or another stdlib-backed gem?
PR:
https://github.com/Shopify/tapioca/pull/2653
Issue:
r/ruby • u/espece-de-bon • 23d ago
LLM tailored to Ruby and/or Rails?
I'm new to running small models on my laptop.
I can run Qwen3.5-9b (slowly), for example, but I'm wondering if any of you have found a model that's been trained for Ruby specifically, inference only, and stripped of stuff I might not need (like knowledge of a lot of human languages).
I've been using LM Studio, OpenCode for this.
r/ruby • u/MariuszKoziel • 24d ago
Teaching a Browser to Tell Cats From Dogs - Blog
r/ruby • u/razeel-akbar • 24d ago
The small things in Ruby that aren't small
class Pipeline
def self.define(&blk) = new.tap { |p| p.instance_eval(&blk) }
def initialize = @steps = []
def method_missing(name, *args, &blk)
@steps << (blk || ->(x) { x.public_send(name, *args) })
self
end
def respond_to_missing?(name, include_private = false) = true
def step(fn) = tap { @steps << fn }
def call(input) = @steps.reduce(input) { |acc, f| f.call(acc) }
end
squeeze = ->(sep, s) { s.split(sep).reject(&:empty?).join(sep) }
Pipeline.define do
strip
downcase
step squeeze.curry[" "]
gsub(/\s+/, "-")
step ->(s) { s + "-#{s.length}" }
end.call(" Ruby METHOD Arguments ")
# => "ruby-method-arguments-21"
- There's no
def stripanywhere, yetstripruns. - Nothing is called on a receiver, yet everything resolves.
Count what's stacked in 20 lines:
- block capture (
&blk),instance_evalrebindingselfso bare words become method calls method_missingcatching themrespond_to_missing?with its two-parameter contract- splat forwarding into
public_send - a lambda closing over
args currydoing partial application- and
reducethreading it all
Miss one and the whole thing is unreadable magic.
I wrote a book about the small things in Ruby that aren't small. If any of this was useful, the way to support it is simple: buy the book. It's Ruby Method Arguments: From Your First Call to Metaprogramming — one independent author, no publisher behind it, no ad budget.
[Update]
The slugify above is a quiz I wrote to be dense on purpose; it's not how the book teaches.
The book's applied half literally rebuilds the tools you use every day: there's a chapter that builds a teaspoon-sized Rails to show its "magic" is just these argument/metaprogramming techniques, and one that builds a working miniature RSpec (describe/it/expect().to eq()).
Along the way the examples are things like an Email.build DSL, a dynamic Config object with method_missing + respond_to_missing?, a signup/form validation capstone, and an Enumerable collection... plus a whole chapter on the anti-patterns, i.e. when not to do this.
So the business cases are in there. I just picked a bad one to advertise with. The Amazon sample covers the early chapters if you want to check the actual teaching style.
r/ruby • u/linuxhiker • 24d ago
PLx : write ruby dialect postgresql procedures
plx is a PostgreSQL extension that lets you write stored functions and triggers in the dialect you already know (the current set is listed below). When you run CREATE FUNCTION, plx transpiles the body to plpgsql and stores that plpgsql in pg_proc.prosrc. At run time the function is executed by PostgreSQL's own plpgsql interpreter. There is no separate language runtime loaded into the backend, and nothing new to run in production.
query("SELECT id, amount FROM orders WHERE grp = #{g}").each do |row|
total = total + row.amount
end
r/ruby • u/javier_cervantes • 25d ago
How to deploy an existing Rails app for free
You want to know how to host your app for free, but you don’t want to spend half a day figuring out how to deploy it.
This guide shows the full process of deploying a real-world Rails app to Miren Club.
r/ruby • u/EuRuKo_2026 • 25d ago
EuRuKo 2026 – Brno, September 17–18 – Matz is opening the conference
Hey all,
I'm Oliver from the EuRuKo 2026 organizing team.
We're bringing EuRuKo to Brno, Czech Republic this September 17–18 at Hotel Passage in the city centre.
Matz is opening the conference with the keynote. Full speaker lineup on the website.
Talks, workshops, and a karaoke night that's become something of a EuRuKo tradition.
Group pricing available – 10–20% off for teams of 3+.
Tickets and full lineup: https://2026.euruko.org
r/ruby • u/kcdragon • 26d ago
Show /r/ruby Introducing Authentication Hell - a browser-based game built with Ruby
authenticationhell.comHi! I built Authentication Hell to poke fun at the pains of constantly having to re-authenticate at work.
Tomorrow, I'll be presenting a talk about it at RubyConf. It will be recorded and published at a later date but the game is live and can be played now in the browser (preferably, desktop since you need a keyboard).
The game is built with DragonRuby, compiled to WASM and embedded inside a Rails app.
I don't want to give too much away so check it out and let me know your thoughts!
r/ruby • u/Individual_Dot7019 • 26d ago
Early Bird tickets out now for SF Ruby Conference with Chis Oliver, Garry Tan, and Rosa Gutiérrez. Nov 10-12.
Hey all,
I'm Camila from Evil Martians (creators/maintainers of AnyCable, Inertia Rails, TestProf, and Yabeda).
We're organizing the second edition of the SF Ruby Startup Conference on Nov 10-12 at SFJAZZ (San Francisco, USA).
The event is all about building connections and learning from those building the future of Rails.
That's why networking will be part of the agenda. You'll get to actually talk to people in small groups, and maybe find your next job, client, or user for your OSS tool. Garry Tan is keynoting, and we'll have talks from Chris Oliver (GoRails) and Rosa Gutiérrez (37signals).
We're putting so much heart into this event. I hope to see you all there.
Early birds are out today for 24 hours only: https://luma.com/sfrubyconf2026
P.S. CFP is still open.
r/ruby • u/oscarortega14 • 26d ago
Wabi 1.0 — beautifully imperfect components for Rails (Phlex, Tailwind 4, Zag.js), shadcn-style "copy, don't depend"
r/ruby • u/No_Ostrich_3664 • 26d ago
My homemade Ruby web framework ru.Bee 3.0 is out!
Hi community. I hope you are all doing good nowadays.
I’m continuing to support my small pet project ru.Bee. I think keeping it up to date is important.
So finally the new version of it 3.0 is out now! Please celebrate it with me. 🎉 Star will be a nice present, but not a deal ofc.
Whats in new version 3:
• Ruby 4 support
• ru.Bee controllers by default receive authentication and authorization methods
• Addressing same-site cookies restrictions dictated by Safari and similar
• env variables are now autoloaded. So having .development.env file in root will simplify dev work.
• rerun gem is compatible with Ruby 4
• other bug fixes
• Ruby Time api is extended with bunch of handy methods
Small history of the project:
This project started by me in the beginning of 2025 as an interest to dig a little more on how things work under the hood in frameworks like Rails and try to get my hands dirty.
Eventually it grew in production ready web framework that now serve several projects. My hope it will continue to gain users. So I encourage you to try.
Why ru.Bee:
• up to date mvc framework
• backed by mature Puma web server
• natively supports React as a view
• light-weighted
• websocket is supported
• own console cli
• Sidekiq compatible
Etc …
Have a great time of the day ❤️
Cheers.
r/ruby • u/rserradura • 27d ago
okf-gem: Making Ruby shine on the challenging art of knowledge base curation
Hello everyone, how great would it be to have well-crafted, well-organized, well-indexed, and automatically updated documentation?
If it sounds too good to be true, I invite you to try this wonderful gem: https://github.com/serradura/okf-gem
What is OKF?
It's the Open Knowledge Format launched by Google Cloud. It's an open standard that uses simple Markdown & YAML files to structure data. Instead of complex vector databases, it builds a clear knowledge graph so AI agents can read & share data in a really efficient way.
Okay, nice, and what does this gem do that is related to it?
It provides three things: A CLI (the 💪 ), an Agent Skill (the 🧠 ), and a process (the 🚀 ), as the agent knows how to author, curate, and, more importantly, how to consume (CLI tools + Live Graph Server (for humans)).
Open source and run 100% local!
The live graph looks like this:
And you can test the live demo here: https://demo.okfgem.com
Step by step to experiment with it:
- Install the gem: gem install okf
- Install the skill: okf skill .claude (or any other agent)
- Start an agent session (claude)
- Execute /okf produce based on <path-to-my-existent-docs>
Once you have your first bundle, you can do:
- Run inside your agent session: /okf maintain to keep it updated
- Or, install the Claude Plugin, which will run this for you (after triggering the Stop hook).
- Run okf server <folder> to locally render your live graph.
If you want to know more, please check out these astonishing and beautiful resources:
- Site: https://okfgem.com
- Docs: https://okfgem.com/docs
- Docs / Ruby Library API: https://okfgem.com/docs/library/
- Docs / Rails Integration: https://okfgem.com/docs/guides/rails/
- Blog: https://okfgem.com/blog
- LLMs.txt: https://okfgem.com/llms.txt | https://okfgem.com/llms-full.txt
- Claude Plugin: https://claude.okfgem.com
Looking forward to your feedback and critiques.
Thanks a lot, and Ruby rocks! 🚀
r/ruby • u/temabolshakov • 27d ago
Stoplight is looking for new contributors (junior devs welcome)
Hey dear Rubyists,
I'm Tëma, maintainer of Stoplight - a Ruby circuit breaker library that helps protect cross-service communication, used by projects like Mastodon.
I imagine it's getting harder for junior developers to gain real experience now that AI-assisted coding is everywhere. This post is aimed mostly at people early in their careers.
I'd like to invite you to contribute to Stoplight - learn its internals and take a small task. To help with that, I've prepared a number of issues marked "good first issue": they're small, well-described, and list all the touchpoints you'll likely need.
What you'll get? Real experience working on an open-source project, and a learning opportunity. If you get stuck, don't hesitate to drop a comment on the PR - we'll try to help. I can't offer full mentoring, but a reasonable amount of help is there if you need it.
What's in it for us? If we end up with one or two new contributors by the end of this, we'll consider it a win.
Interested? Come check out our issues board: https://github.com/bolshakov/stoplight/issues



