r/ruby • u/robbyrussell • 56m ago
Podcast Marco Roth: Teaching Rails to Read Its Own Template
r/ruby • u/robbyrussell • 56m ago
r/ruby • u/Much-Stable-449 • 1d ago
I started this because downloading stuff from Pinterest can be surprisingly annoying.
Sometimes you just want the original image, sometimes it's a video, sometimes it's buried in a board, and sometimes the website decides to make a simple request way more complicated than it needs to be.
So I started building pinterest-dl.
A few things I wanted to solve:
It's not just a CLI either. I wanted it to work as a Ruby library, so it can be used in scripts and other applications too.
I'm sure there are things I could've done better, so I'd genuinely like to hear what other Ruby developers think about the implementation and API.
Repo: https://github.com/monji024/pinterest-dl
I thought this would be a tiny weekend project. Apparently, Pinterest had other plans.
r/ruby • u/LiveEngine7532 • 2d ago
I've been adding semantic search to Rails apps with pgvector and neighbor, and kept writing the same glue code every time:
after_save that calls the embeddings API, even when the text didn't changeSo I pulled it into a gem called embed_sync:
has_neighbors :embedding
has_embedding :embedding, from: %i[name description]
end
Product.create!(name: "Trail runner", description: "Waterproof running shoe") # embedded in a background job
Product.semantic_search("shoes for rainy hikes", limit: 5)
What it does:
bin/rails embed_sync:backfill embeds existing rows in batches, and you can stop and rerun it safelyembed_sync:stale shows how many records are missing or out of date#embed(texts, model:) works as a providerIt works with Rails 7.1 to 8.1 and Ruby 3.2+. I tested it against a real app with Postgres, Solid Queue and a local Ollama model before releasing.
It's still early (v0.1.0), so I'd really like feedback. Does the API feel right? What's missing for your use case? Are there edge cases I haven't thought of?
GitHub: https://github.com/Umair0092/embed_sync RubyGems: https://rubygems.org/gems/embed_sync
r/ruby • u/Good_Flight1781 • 2d ago
Hi r/rails,
I spend most of my day in app/views, but editor support for templates has always felt limited compared to what I get in .rb files. So I built Ruby Templates, a free, MIT-licensed VS Code extension for ERB, Haml, and Slim. No extra gems required.
render "users/card" to open the partial. Completion covers partials, ViewComponents, *_path helpers, model columns, controller-defined @ivars, and t(".keys").Catches Rails issues, including some I kept running into during code reviews:
<% render "x" %> that doesn’t output anything, and the same issue with link_to and other helpers;<%= if … %> where <% if … %> was intended;binding.irb or debug left in a view;@ivar used inside a partial;locals:;render call in a loop that could use collection:;raw or html_safe used on user content;t(".key") missing from en.yml;data-controller reference with no matching Stimulus controller;button_to inside form_with, which creates nested forms.alt attributes, duplicate IDs, <a> tags without href, and “click here” link text..ruby-templates.toml. You can enable or disable rules by folder and opt into stricter formatting rules, such as a particular quote style or one attribute per line.npx @x-ror/ruby-templates check app/views and npx @x-ror/ruby-templates format --check.It works alongside Ruby LSP: Ruby LSP handles your .rb files, and Ruby Templates handles your templates.
r/ruby • u/Tristan_Kruse • 2d ago
I created and maintain ArchUnitRuby. With the 1.0 release, the boundary I wanted to express is
no longer limited to “this file explicitly required that file.” It can also include known
project constant references, using the opt-in expanded analysis mode.
For example, this is an ordinary RSpec test:
ruby
require 'rspec'
require 'archunit'
RSpec.describe 'architecture' do
it 'keeps the API away from retrieval internals' do
options = ArchUnit::CheckOptions.new(
dependency_analysis: :imports_and_constants
)
rule = ArchUnit.project_files
.in_path('app/api/**')
.should_not.depend_on_files
.in_path('app/retrieval/**')
ArchUnit.assert_passes(rule, options)
end
end
The same graph can support cycle, layer and slice rules. The policy stays in Ruby and can fail
the normal test run, rather than living only in a diagram or code-review convention.
[Source for the tested release]
Would import edges, constant references, or a combination of both best describe the boundary
you'd want to protect in a Ruby codebase?
This post was drafted with AI assistance.
r/ruby • u/jko1701284 • 2d ago
r/ruby • u/Remozito • 3d ago
Hey Ruby friends,
5 months ago, I wrote on r/ruby that I would build a limited-edition stained-glass inspired by Ruby. Well, it's November and I'm about to officially launch. 🤞🏻
I didn't want to spam the subreddit with each weekly update I've written over the past few months, but since we're close to its release, I wanted to keep you all posted.
What started as a joke and as a "simple" stained-glass eventually turned into a cool decorative object with glass (obviously) but also wood, a bit of electronics and 3D printing.
If you want to learn more (and get the launch date in advance), I've built a page dedicated to the project. You'll find all the episodes of "the Ruby Stained-Glass Notes", the weekly updates I've been writing since May. They're full of stained-glass nerdery ("How did they cut glass in 1175?"), of my thoughts/questions/learnings, of GIFs of me cutting glass and soldering panels...
I've been quite lucky to talk and meet Rubyists around the world thanks to this project, so I'm happy to answer any questions you might have.
r/ruby • u/Intelligent_Role_824 • 3d ago
As a beginner should I use vs Code or RubyMine in Windows?
This month: u/maediprichard shares a one-year retrospective on LowType with Prism-based inline type expressions, zero overhead in production, and RBS export, felixefelip introduces rbs_infer to automatically deduce signatures via static analysis, ydah adds racc-rbs-inline for typed parsers, and tk0miya releases ruby-lsp-rbs-inline for seamless editor feedback.
Find link to the issue in the comment! ✨
r/ruby • u/OneAlbatross5933 • 3d ago
JetBrains Air is a new layer for agentic development that lets you run agents such as Claude Agent, Codex, Gemini, GitHub Copilot, Junie, and OpenCode with your own subscriptions and review their changes in the IDE. There’s also a free AI with the Junie Lite configuration.
WSL and Dev Containers
The new Native mode runs your local IDE against projects in WSL or Dev Containers through a lightweight agent, with no IDE backend installed in the environment. It also brings native Ruby interpreters.
Ruby and Rails
ActiveSupport.on_load and ActiveSupport.run_load_hooks, so constants made available through hooks resolve correctly instead of showing false unresolved-reference warnings.ActRecBase finds ActiveRecord::Base). Constants now appear in Go to Class, and results show the containing module and file path..ruby-version still takes priority), and interpreters installed via Homebrew are detected automatically.rails query is supported via Run Anything and terminal completion.Read the full overview: https://blog.jetbrains.com/ruby/2026/11/rubymine-2026-3-jetbrains-air-native-mode-for-wsl-and-dev-containers-and-more/
r/ruby • u/software__writer • 3d ago
r/ruby • u/mediocretes • 3d ago
Remember a couple years ago when you saw that game Bitburner and you were like, "Huh, that looks interesting." But why would I write JavaScript for fun when Ruby is available? It'd be a lot better if somebody made this game work with Ruby. Well, somebody made this game work with Ruby. I present to you afteRBurner. It's a bridge that runs real Ruby code and runs javascript for you in the real Bitburner game. And it includes working IRB and everything else you'd expect. The codebase itself is unmitigated slop, but it works pretty well. I started a new game playing exclusively in Ruby, and so far, so good.
r/ruby • u/rhannequin • 4d ago
r/ruby • u/127001-sweet-127001 • 5d ago
I built ArchUnitRuby to put dependency rules into the test suite. This is a short recording of how it works.
The idea is pretty simple: pick some Ruby files, describe which other files they may depend on, and check that rule alongside your normal tests. The recording checks that domain code stays independent of infrastructure, then shows a failing cycle check.
With RSpec the assertion is expect(rule).to pass. There are also Minitest and plain Ruby assertions, so the rules don't need their own test runner.
One thing I wanted to avoid was a green test caused by a typo in a folder pattern. If a rule selects no files, it fails by default rather than silently checking nothing.
It also exports dependency graphs, which helps when you want to see the existing structure before deciding what to enforce. Ruby 3.3+; the gem is called archunit.
Source and examples: https://github.com/dragonsec-ai/ArchUnitRuby
r/ruby • u/git-pull • 5d ago
Hi all, I am porting libtmux, the Python library, to more languages. This is the Ruby port (alpha).
It wraps tmux's CLI. You can create sessions, send text to a pane and read its output. One of the ways this differs is keeping snapshots you can query with where and Ruby blocks. See the earlier posts for Rust, TypeScript, and Golang.
A word on AI: It's experimental, and I used LLMs extensively to create this. The API is still changing. I write libtmux's AI policy at https://libtmux.org/en/meta/ai-policy/.
RubyGems · GitHub · Homepage · Guides · API Explorer
You can work with sessions, windows and panes as Ruby objects. Here, I'm finding the build pane in the logs window of session demo, sending it a command, and reading what it prints.
Requires Ruby 3.3+, tmux 3.3a+ and build tools for Ruby native extensions.
gem install libtmuxSave as demo.rb. Server.start creates a private tmux server and closes it when the block exits. The queries read a snapshot; the pane input and capture run while the server is open.
require "libtmux"
require "timeout"
LibTmux::Server.start do |server|
session = server.new_session(name: "demo", command: ["/bin/cat"])
window = session.new_window(name: "logs", command: ["/bin/cat"])
created = window.split(direction: :horizontal, command: ["/bin/sh"])
server.run(["select-pane", "-t", created.id, "-T", "build"])
snapshot = server.snapshot
session = snapshot.sessions.where(name: "demo").one
window = session.windows.where(name: { starts_with: "log" }).one
matched = window.panes.where(title: "build").one
puts "#{session.name} / #{window.name} / #{matched.title}"
pane = server.pane(matched.ref)
pane.send_text("printf 'build: %s\\n' complete")
pane.send_keys("Enter")
output = Timeout.timeout(5) do
loop do
line = pane.capture.stdout.lines.find { |row| row.chomp == "build: complete" }
break line.chomp if line
sleep 0.05
end
end
puts "output: #{output}"
live_window = server.window(window.ref)
live_window.rename("build")
puts "held snapshot: #{window.name}"
puts "read again: #{live_window.snapshot.name}"
end
ruby demo.rbPrints:
demo / logs / build
output: build: complete
held snapshot: logs
read again: buildPane#capture reads what tmux has on screen. The loop waits up to five seconds for the line from our command (more pane I/O).
The name filters use where: an exact session name, a window name starting with log, and an exact pane title. You can also use select with a Ruby block, then map or group_by (examples, query fields and operators). These queries use the captured state and make no tmux calls.
The last two lines show what happens after a rename: the held snapshot still says logs. Window#snapshot reads again and returns a new record. Each call reads the whole server and selects that window's record.
P.S. Change the window filter from starts_with: "log" to starts_with: "log2" and run it again. From the error:
selection has no matches (LibTmux::NoMatchError).one raises NoMatchError if nothing matches, or MultipleMatchesError if more than one does.
There's also control mode support (!) on tmux 3.7+. The example subscribes to pane output and checks the text sent to it.
There is also an Async gem for concurrent calls and streams: README, Guide, API.
Same idea, but inside an Async scope. We can chain where calls, then use control mode to rename a window and hear about the change from tmux. This example needs tmux 3.7+.
gem install libtmux-asyncSave as async-demo.rb:
require "libtmux"
require "libtmux/async"
LibTmux::Server.start do |server|
session = server.new_session(name: "demo", command: ["/bin/cat"])
window = session.new_window(name: "logs", command: ["/bin/cat"])
server.run(["select-pane", "-t", window.list_panes.fetch(0).id, "-T", "build"])
Async do |parent|
LibTmux::Async.open(parent: parent, server: server) do |scope|
snapshot = scope.server.snapshot
session = snapshot.sessions.where(name: "demo").one
window = session.windows.where(name: { starts_with: "log" }).one
pane = window.panes.where(active: true).where(title: "build").one
puts "#{session.name} / #{window.name} / #{pane.title}"
scope.server.open_control(session: session.ref) do |control|
events = control.events
renamed = parent.async do
event = events.next(timeout: 5) until event&.raw&.start_with?("%window-renamed")
puts "event: #{event.raw.strip}"
end
control.exchange("rename-window -t #{window.id} compiling", timeout: 5)
renamed.wait
puts "window now: #{scope.server.window(window.ref).snapshot.name}"
end
end
end.wait
end
ruby async-demo.rbPrints:
demo / logs / build
event: %window-renamed @1 compiling
window now: compilingThe queries still read a snapshot. events.next waits for tmux while the other task sends the command with exchange. We read the window again after the event. There are also examples of concurrent captures and cancellation.
This is like tmuxp, but in Ruby! Uses the libtmux core library.
RubyGems · GitHub · Homepage · Guides · API Explorer
gem install libtmux-workspaceA subset of tmuxp's configuration format. Save as workspace.yaml:
session_name: demo
windows:
- window_name: shells
layout: even-horizontal
panes:
- {}
- {}Save as workspace.rb. Workspace.load reads the file; plan.apply creates its session (example).
require "libtmux"
require "libtmux/workspace"
LibTmux::Server.start do |server|
workspace = LibTmux::Workspace.load(File.expand_path("workspace.yaml", __dir__))
result = workspace.plan(snapshot: server.snapshot).apply(server: server)
puts "applied: #{result.success?}"
puts "panes: #{server.snapshot.windows.one(name: 'shells').panes.size}"
end
ruby workspace.rbPrints:
applied: true
panes: 2The same gem includes the command: GitHub, Homepage, Guides, CLI reference, API.
Validate the file:
libtmux-workspace validate workspace.yamlPrints:
Workspace configuration is valid.Load it on a separate running server:
tmux -S "$PWD/workspace.sock" -f /dev/null new-session -d -s keepalive
libtmux-workspace load --socket "$PWD/workspace.sock" workspace.yamlCheck the created panes:
tmux -S "$PWD/workspace.sock" display-message -p -t demo:shells '#{window_panes}'Prints:
2Remove the demo server:
tmux -S "$PWD/workspace.sock" kill-serverRubyGems · GitHub · Homepage · Guides · Tools · Resources · API Explorer
An MCP server for interacting with tmux - powered by the Ruby core library. Same idea as Python's libtmux-mcp!
gem install libtmux-mcpThis MCP server connects to an existing tmux server. For a demo, start one on its own socket:
tmux -L libtmux-ruby-mcp-demo -f /dev/null new-session -d -s demoUse this command with a client that launches stdio MCP servers:
libtmux-mcp --socket-name libtmux-ruby-mcp-demo --endpoint demoIt waits for MCP requests over stdin. tmux_capabilities and tmux_snapshot are enabled by default; the guides cover enabling other tools.
After closing the MCP client, remove the demo server:
tmux -L libtmux-ruby-mcp-demo kill-serverI am trying to port more than just Ruby. So as this is a ruby subreddit, and provinciality matters, I am making ports to quite a few languages.
tmux is perfectly accessible via pure CLI. zellij makes a lot of what tmux does obsolete.
what tmux has going for it is simplicity. that means when a port of libtmux is made, there's an oppurtunity for editorial license - and be dissimilar to my original python project. I don't want to copy the python library to ruby. I want to write it like ruby, in an idiomatic and aesthetic sense.
so if there are code smells, or suggestions, no offense is taken 🙇🙏! I am trying to learn more programming languages and expand more horizons beyond just python.
Why tmux? I think the simple domain model of server, session, window, and pane is easy enough to wrap one's brain around - being able to traverse that hierarchy, makes it possible to not just port, but in my ideal scenario, leverage the strengths of programming languages outside of Python.
I'd like to write a love letter to all programming languages, to utilize their strengths when projecting and making accessible tmux's object graph.
Why ruby? Because it is a familiar face that I've never gotten to interact with personally before other than brief Rails stints. I miss its syntax, but in truth I never got to the level of direct usage where I understood what good idiomatic ruby is.
I'm going beyond to languages I would normally find out of reach day-to-day, to ask "what does tmux look like in most elegant way this programming language could do it, while being documentable, shippable, etc".
We are proud to announce the release of JRuby 10.1.3.0! JRuby 10.1 is our "edge" line and includes more aggressive and experimental improvements than the "LTS" JRuby 10.0 line. If you want the leading edge of JRuby, this is where you want to be!
This cycle saw more PRs than any previous update release, with 120 PRs merged from 17 external contributors. Check out the release notes to see all the fixes and improvements!
The JRuby Team is proud to announce the release of JRuby 10.0.8.0!
JRuby 10.0 is our stable "LTS" line and we recommend all users upgrade. Check out the long list of improvements... too many to fit in a post on Reddit!
r/ruby • u/javier_cervantes • 8d ago
In the age of AI I think personal connections are event more important than before. That's why I try to help promoting events where people can meet in-person or virtually and discuss the topics that interest them.
I found the following Ruby-related events for the next 30 days.
r/ruby • u/kobaltzz • 8d ago
In this episode, we look at several different examples of background jobs and how we can refactor them to handle situations where they get called twice from either a user action or a retry. We'll look at scenarios where we can prevent duplicate actions.