r/ruby

Image 1 — 🎉 I released AREA 512, an operating system made exclusively for the Cardputer ADV!
Image 2 — 🎉 I released AREA 512, an operating system made exclusively for the Cardputer ADV!
Image 3 — 🎉 I released AREA 512, an operating system made exclusively for the Cardputer ADV!
Image 4 — 🎉 I released AREA 512, an operating system made exclusively for the Cardputer ADV!
▲ 127 r/ruby+3 crossposts

🎉 I released AREA 512, an operating system made exclusively for the Cardputer ADV!

Hi Reddit! 👋

I'm Hamachang, a software engineer from Japan. 😎

I've been working on a retro-inspired operating system for the Cardputer ADV called AREA 512.

It's built around FemtoRuby, a lightweight subset of Ruby designed for embedded systems.

With AREA 512, you can write Ruby code directly on the Cardputer, compile it, and run it—all on the device itself. That means you can build applications for the hardware without ever leaving the hardware.

It also comes with several built-in applications, including games and small productivity tools, so you can start exploring right away. 🤖

The project is open source on GitHub. If it looks interesting, even giving it a ⭐ would mean a lot to me!

https://github.com/engneer-hamachan/area512

AREA 512 aims to capture the spirit of classic operating systems, so I'd also love contributions from anyone who shares that passion.

Thanks for reading! ✨

See you around! 🚄

u/AssociationOne800 — 2 days ago
▲ 19 r/ruby+1 crossposts

Alexscript a Polish-syntax language written in Ruby. With fully implemented OOP, fiber based async and its own web framework.

Alexscript is a general purpose scripting language I've been working on for the last 1.5 years. With a goal in mind to combine Ruby's strongly object-oriented philosophy with some features borrowed from JS and syntax written in my native language.

modul Geometria {
    klasa Punkt {
        funkcja konstruktor(x, y) {
            niech @x = x
            niech @y = y
        }

        funkcja x() { zwroc @x  }
        funkcja y() { zwroc @y }
    }

    klasa Kolo {
        funkcja konstruktor(srodek, promien) {
            niech @srodek = srodek
            niech @promien = promien
        }
    }
}

niech p = Geometria::Punkt.nowy(3, 4)
niech k = Geometria::Kolo.nowy(p, 10)

It's a from-scratch language, with a hand written lexer, parser, AST and tree-walking interpreter. Not just a preprocessor or transpiler. Ruby works here as a host language.

Some key features:

  • Async runtime is fiber based with a cooperative scheduler: czekaj (await) parks the current fiber and hands control back to a custom reactor (ready-queue + timers + an IO.select loop). Concurrency comes from explicitly spawning work with uruchom_rownolegle (run_parallel) and joining with Obietnica.wszystkie (Promise.all).
  • Modules work both as namespaces, to avoid name pollution in larger projects and as mixins. A set of methods that can be injected into classes. They are also open, multiple modul Foo {} blocks across files merge into one definition. I've purposefully decided to keep classes closed though.
  • Classes have built-in reflection methods. E.g. to check a class's ancestors/descendants, if a given method exists, list of methods, etc. More broadly, every data type carries a rich set of built-in methods.
  • Exceptions are just special purpose classes that inherit from the base exception class. You can write your custom exception by simply defining a new class that inherits from already defined exception class: klasa MojWyjatek < WyjatekPodstawowy {}
  • Standard library is implemented natively in Ruby (Time, Math, JSON, Socket etc), but native methods aren't kept in a separate registry, they're injected into the same [:methods] / [:static_methods] hashes that user defined methods live in, flagged with :native_lambda
  • In addition to regular functions there are also anonymous ones/lambdas. They can be assigned to variables or passed into higher order functions as arguments:

​

niech arr = [10, 20, 30] 
niech wynik = arr.mapuj(fn(el, idx) { el + idx }) 
pokazl wynik        # [10, 21, 32]

funkcja zastosuj(f, val) { zwroc f(val) } 
pokazl zastosuj(fn (x) { x * 3 }, 7)  # 21 
pokazl zastosuj(fn (s) { s.duzymi() }, "alex") # ALEX
  • built-in debugger which is intended to work similarly to byebug

you can check full documentation (in English) here: www.alexscript.pl/docs

you can also try it online on your own: https://www.alexscript.pl/try

or simply download it on your local machine via homebrew:

brew tap N3BCKN/alexscript
brew install alexscript

As a proof of concept I've built a couple of real life projects:

  • Zubr - a micro web framework. With routing, static files serving, middleware chain, body request parsing, sessions and streaming of larger files. With 50 open connections it can handle up to 1,590 req/s, and streams large files at ~1.97 GB
  • ASBasic - an interpreter of classic BASIC language written from scratch in Alexscript.
  • Posel - HTTP client inspired by Axios and HTTParty

Any feedback is more than welcome!

github.com
u/green_bisonstd — 3 days ago
▲ 71 r/ruby+2 crossposts

Final step in the Learn Rails tutorial series: Product Reviews

My latest tutorial for the Rails Getting Started guide series is now published! It's been fun to work on for the past couple years to showcase all the built-in functionality that Rails has.

rubyonrails.org
u/excid3 — 3 days ago
▲ 9 r/ruby+1 crossposts

Ozymandias on Rails. Cartography of a Ruin

When everything is on fire, nothing is on fire. Where do you start when every problem seems intractable? By drawing a map.

baweaver.com
u/keyslemur — 3 days ago
▲ 32 r/ruby+39 crossposts

Made a free iOS app to open and read raw Markdown (.md) files on iPhone/iPad — handy for peeking at Logseq pages outside the app

Logseq stores everything as plain .md files, but if you ever open one of those files directly on iOS (from Files, iCloud, Dropbox, a backup, etc.) you just get raw text. I built a small viewer to read them rendered on a phone.

Md Preview:

• Renders GitHub-Flavored Markdown — headings, tables, task lists, footnotes

• Code blocks with syntax highlighting, plus LaTeX math and Mermaid diagrams

• Opens .md / .markdown / .mdx / .rmd / .qmd from Files or the Share Sheet

• 100% on-device — no account, no uploads, no ads, no subscriptions

Free on the App Store: https://apps.apple.com/app/id6760341080

Details: https://markdown.cybergame.ai/

Not a Logseq replacement at all — just a quick way to read loose .md files when you're away from the desktop app. Curious how you all read your graph on the go.

u/Fujima4Kenji — 5 days ago
▲ 20 r/ruby+1 crossposts

New jemalloc gem (jemalloc_rb)

Do you use the jemalloc gem?

The original project on GitHub seems to be abandoned for around 12 years, and some incompatibilities with recent Ruby versions have begun to emerge. Additionally, the underlying jemalloc library hasn't been updated during all this time. Because of that, I created a fork and launched a new gem (jemalloc_rb) to keep the project functional, updated, and actively accepting pull requests.

https://github.com/henrique-ft/jemalloc_rb

u/Illustrious-Topic-50 — 5 days ago
▲ 0 r/ruby+1 crossposts

The N+1 Query Problem

You ship a /posts index page. It renders 50 posts, and for each one it shows the author's name with post.author.name. QA says the page is slow, and the logs are full of repetitive SQL.

  1. What is this problem called, and why is it happening?
  2. How would you detect it, in dev and in a running app?
  3. How do you fix it, and what's the difference between the main fixing strategies?

Answer: N+1 queries

What it is and why it happens

This is the N+1 query problem. One query loads the 50 posts, then Active Record fires one more query per post to load post.author. That's 1 + N queries (1 for posts, 50 for authors) when it could be 2, or even 1. Active Record associations are lazy by default, so the author isn't loaded until you call post.author. Do that inside a loop and you get a round trip per record.

How to detect it

  • Dev logs: you'll see the same SELECT ... FROM authors WHERE id = ? over and over with different IDs. That repetition is the tell.
  • The Bullet gem: built for this. It warns you in dev when you should add eager loading, and also when you're eager-loading something you don't need.
  • An APM in production (Sentry, New Relic, Scout): flags endpoints firing a lot of queries.
  • Tests: assert on query count with something like assert_queries or an RSpec matcher so CI catches a regression before it ships.

How to fix it

Eager-load the association:

# N+1
@posts = Post.all
@posts.each { |p| puts p.author.name }   # 1 + 50 queries

# Fixed
@posts = Post.includes(:author)
@posts.each { |p| puts p.author.name }   # 2 queries

There are four tools, and they don't do the same thing:

Method What it does When to use it
preload Loads the association in a separate query and matches it in memory You just need the data and aren't filtering or ordering by the association
eager_load One LEFT OUTER JOIN that loads everything in a single query You need to filter or order by the association and read its attributes
includes Defaults to preload, but switches to eager_load if you reference the association in a where or order Your usual default. Let Rails decide
joins INNER JOIN for filtering or sorting. Does not load the association into memory You need to filter by the association but don't read its attributes

The trap: joins alone does not preload. If you joins(:author) and then call p.author.name in the loop, you're right back to N+1. Reach for includes or eager_load when you actually read the association's attributes.

u/hasan-dev — 6 days ago
▲ 1 r/ruby

Ruby on Rails in Manjaro

Hello Reddit. I am new to Manjaro, and was hoping to set up a development environment in RoR. I was following the directions on the Arch wiki, and I noticed my gems are being installed to usr/lib/ruby/gems. When running a bundle install, it now seems to want to write to usr/bin, and fails because it doesnt have permissions. Should I go ahead and grant permissions, or is this not advisable?

reddit.com
u/Fletcher_Gilstrap — 8 days ago
▲ 6 r/ruby+1 crossposts

Live-updating comments with Turbo in Rails A Comment model pushes its own creates, updates, and deletes to subscribers over Turbo Streams.

highlit.co
u/Environmental-Yak328 — 8 days ago
▲ 18 r/ruby+1 crossposts

Ozymandias on Rails. The Pedestal Inscription

Shelley wrote about a king whose monument outlived everything it was built on. I've spent 15 years inside Rails monoliths that did the same thing. This is the first post about what to do when you're standing in the ruins.

baweaver.com
u/keyslemur — 7 days ago
▲ 14 r/ruby+1 crossposts

I built a saga orchestrator for Ruby — DAG execution, async Sidekiq, automatic rollback

After wrestling with distributed transactions across microservices and watching Sidekiq job chains grow into unmaintainable spaghetti, I built Ruby Reactor — a saga pattern implementation for Ruby that handles the hard parts of workflow orchestration.

What it does:

  • Builds a DAG (directed acyclic graph) from your step definitions, so independent steps run in parallel
  • Runs async via Sidekiq with back-pressure and batching
  • Automatically rolls back completed steps when something fails (compensation)
  • Supports interrupts — pause a workflow mid-flight and resume it later via webhook or manual trigger
  • Includes a built-in web dashboard to inspect every execution
  • Has locks, semaphores, and rate limits built in (Redis-backed)
  • Ships with RSpec test helperstest_reactor, mock_step, chainable matchers

Why I built it:

I kept hitting the same wall: complex business transactions that span multiple services need coordination. dry-transaction handles linear pipelines well, but when you need parallel execution, async processing, automatic rollback on failure, or the ability to pause and wait for external events, you're on your own. Trailblazer operations can do some of this, but the undo logic and parallelism are manual.

Ruby Reactor fills the gap — it's the only Ruby library that combines DAG planning + async execution + compensation + interrupts + a dashboard in one package.

Quick example — an e-commerce checkout with fraud detection:

class CheckoutReactor < RubyReactor::Reactor
  input :order_id

  step :reserve_inventory do
    argument :order_id, input(:order_id)
    run { |args| Inventory.reserve(args[:order_id]) }
    undo { |_err, args| Inventory.release(args[:order_id]) }
  end

  step :charge_card do
    argument :order_id, input(:order_id)
    run { |args| Payment.charge(args[:order_id]) }
    undo { |_err, args| Payment.refund(args[:order_id]) }
  end

  # Pause here — wait for Stripe webhook
  interrupt :wait_for_fraud_check do
    wait_for :charge_card
    correlation_id { |ctx| "order-#{ctx.input(:order_id)}" }
    timeout 3600, strategy: :active
  end

  step :ship_order do
    argument :status, result(:wait_for_fraud_check, :status)
    run { |args| Shipping.create_label(args[:order_id]) }
    undo { |_err, args| Shipping.cancel(args[:order_id]) }
  end

  returns :ship_order
end

It's at v0.4.1 now with ~3,300 downloads on Rubygems. The v0.4.0 release just added interrupts, the web dashboard, RSpec helpers, and Redis-backed coordination primitives (locks, semaphores, rate limits, periods).

How it compares:

Feature Ruby Reactor dry-transaction Trailblazer Raw Sidekiq
DAG/Parallel execution Limited Manual
Auto compensation/undo Manual Manual
Interrupts (pause/resume) Manual
Built-in web dashboard
Locks / sem / rate limits Manual
Async with Sidekiq Limited

I'd love honest feedback — especially from people who've built complex workflows in production. What did I miss? What's over-engineered? What would make you actually use this instead of raw Sidekiq jobs?

Repo: https://github.com/arturictus/ruby_reactor Rubygems: gem 'ruby_reactor', '~> 0.5' Docs: Full guides for every feature in the repo's documentation/ directory

Thanks for reading! I'll be in the comments.

u/arturictus — 7 days ago
▲ 40 r/ruby+1 crossposts

Rails: The Sharp Parts. A Polymorphic Type Is Not a Foreign Key

I don't like to bury ledes, so when people ask me about polymorphic relationships my answer is simply:

Don't.

baweaver.com
u/keyslemur — 10 days ago
▲ 6 r/ruby+5 crossposts

Made a Claude Code plugin that learns your repo's conventions and feeds them to the model before every edit (TS / Ruby / Python)

Like a lot of you I use Claude Code daily. The code it writes usually works, but on our codebase it kept doing the small wrong things: importing axios when we standardized on our own http wrapper, rewriting a date helper that already existed, building a service that ignored the base class every other service extends. Caught in review, every time.

So I built chameleon. It parses your repo with real ASTs (the TypeScript compiler, Ruby's Prism, Python's libcst), learns the conventions for each kind of file, and then before Claude edits a file it injects a real example from your own codebase plus your team's idioms and the anti-pattern to avoid. The model copies how your repo actually does it instead of guessing.

Being honest about what it is:

- Advisory by default. It nudges; you opt into hard blocking.

- Hot path is offline. No telemetry, no repo-code execution by default.

- It costs extra tokens and a little latency per turn (it injects context and runs a turn-end review).

That is the tradeoff.

- TS/JS, Ruby, and Python only right now.

- I don't have a published "makes Claude X% better" number and won't invent one. The A/B eval harness ships with it; point it at your repo and see.

MIT licensed. Install is two lines:

/plugin marketplace add crisnahine/chameleon
/plugin install chameleon@chameleon

GitHub: https://github.com/crisnahine/chameleon
Claude Plugin Hub: https://www.claudepluginhub.com/plugins/crisnahine-chameleon

I'm the author. Genuinely after feedback, especially what breaks or annoys you. Roast it.

u/Tricky-Pilot-2570 — 10 days ago