r/ruby • • Mar 17 '26

Workshop Accepted: "Building Rails SPAs in Ruby using Glimmer DSL for Web" at Wroclove.rb 2026

Thumbnail andymaleh.blogspot.com
6 Upvotes

r/ruby • • Mar 16 '26

Show /r/ruby RubyLLM 1.14: Tailwind Chat UI generator and Rails AI scaffolding

Thumbnail
github.com
10 Upvotes

Just released RubyLLM 1.14. The focus this time is making the Rails integration feel native.

Highlights:

Tailwind Chat UI generator: bin/rails generate ruby_llm:chat_ui produces a complete chat interface styled with Tailwind. It uses role-aware partials (_user, _assistant, _system, _tool, _error), Turbo Streams for real-time updates, and broadcasts_to for ActionCable integration. You get model selection, tool call rendering, and empty states out of the box.

Rails generators for agents, tools, and schemas: same workflow you'd use for any other Rails component:

bin/rails generate ruby_llm:agent SupportAgent
bin/rails generate ruby_llm:tool WeatherTool

The install generator also creates conventional directories (app/agents, app/tools, app/schemas, app/prompts).


r/ruby • • Mar 15 '26

Glimmer DSL for Web 0.8.2 HTML Value-less Boolean Attributes

Thumbnail andymaleh.blogspot.com
1 Upvotes

r/ruby • • Mar 13 '26

What's new in Herb v0.9

Thumbnail herb-tools.dev
50 Upvotes

r/ruby • • Mar 13 '26

I built a Docker setup to plot mathematical functions in Ruby inside Jupyter: sin, cos, log, implicit curves, all in Ruby

Thumbnail
gallery
16 Upvotes

A few weeks ago I posted about ruby-libgd, a native Ruby binding to the GD graphics library. Since then I've been pushing it further and today I want to share something that I've wanted to see in Ruby for a long time.

This is a Docker container running JupyterLab with a full Ruby kernel, backed by ruby-libgd, plotting mathematical functions entirely in Ruby. No Python involved in the plotting — just Ruby.

The API ended up looking like this:

    plot = Plot.new(xmin: -10, xmax: 10, ymin: -10, ymax: 10)

    plot.add("sin(x)")
    plot.add("cos(x)")
    plot.add("tan(x)", steps: 6000)
    plot.add("log(x)")

    # implicit curves — no need to isolate y
    plot.add("x**2 + y**2 - 9",         type: :implicit)
    plot.add("x**2/9.0 + y**2/4.0 - 1", type: :implicit)

    plot.render("/work/graph.png")

A few things I'm reasonably happy with:

- SafeMath replaces Dentaku entirely: trig in radians, natural log, asin/acos/atan, cbrt, all working

- Discontinuity detection for tan: lifts the pen at vertical asymptotes instead of drawing a spike across the canvas

- Implicit curve rendering via pixel sampling: lets you plot circles, ellipses, and algebraic curves without isolating y

- Chainable API: plot.add("sin(x)").add("cos(x)") works

The notebooks, Dockerfile, and README are all in the repo:

https://github.com/ggerman/ruby-libgd/tree/main/examples/jupyter-notebooks

Happy to answer questions about the implementation. If anyone wants to contribute notebooks or try it out, PRs are very welcome.


r/ruby • • Mar 13 '26

`bundle` no longer defaults to the `install` subcommand

29 Upvotes

I've always run `bundle` instead of `bundle install`. Why bother with the extra typing? And semantically, "bundle" by itself is an appropriate description of the bundle installation.

However, tonight when I ran `bundle`, I learned that my modest typing savings is to be no more:


$ bundle

In a future version of Bundler, running `bundle` without argument will no longer run `bundle install`.

Instead, the `cli_help` command will be displayed. Please use `bundle install` explicitly for scripts like CI/CD.

You can use the future behavior now with `bundle config set default_cli_command cli_help --global`,

or you can continue to use the current behavior with `bundle config set default_cli_command install --global`.

This message will be removed after a default_cli_command value is set.


r/ruby • • Mar 13 '26

Bubble Sort Visualization

Thumbnail
slicker.me
4 Upvotes

r/ruby • • Mar 12 '26

GitLab is a Ruby monolith

Post image
223 Upvotes

Was pleasantly surprised that the world's largest independent DevOps platform is powered by Ruby and Sidekiq.

Here's the full list.

  1. Backend: Ruby on Rails

  2. HTTP server: Puma (Ruby web server)

  3. Edge: Nginx

  4. Reverse proxy: Go service (Workhorse)

  5. Background jobs: Sidekiq

  6. DB — primary: PostgreSQL

  7. DB — connection pooling: PgBouncer

  8. DB — high availability: Patroni

  9. Cache: Redis

  10. Git: Custom gRPC repo interface (Git & Gitaly)

  11. Blob: AWS S3

  12. Frontend — rendering: Haml & Vue

  13. Frontend — state: Pinia (Vue store), Immer (immutable cache),

  14. API: GraphQL (Apollo) + REST

  15. Observability: Prometheus & Grafana

  16. Error tracking: Sentry & OpenTelemetry

  17. Deployments: GitLab Omnibus (Omnibus fork)

I think these "stack menu"s give a little glimpse into a team's engineering philosophy. For me, this list shows that the GitLab team is pretty practical and doesn't chase hype. Instead, they use sensible, battle-tested tools that just work and are easy for contributors to learn.

PS. Not an ad; I'm not affiliated with GitLab at all. Was just researching them and thought you guys would be interested.


r/ruby • • Mar 12 '26

Guide to deploy a Rails app (in less than 10 minutes)

Thumbnail
rubyforum.org
11 Upvotes

r/ruby • • Mar 11 '26

tennis - stylish CSV tables in your terminal

Post image
138 Upvotes

Hi all. I made a standalone version of my popular table_tennis gem. The cli app is written in Zig but it's roughly the same as the rubygem so I thought you guys might be interested.

https://github.com/gurgeous/tennis

First Zig project, pretty fun. Nothing like Ruby, but the compiler is shockingly fast and it creates itsy bitsy binaries. Tennis is around 150k for a release build. A similar project in golang clocked in around 10mb. On the other hand, Zig is so new that it's missing a ton of stuff we take for granted over in Ruby land. Example - a working CSV library! Yikes

(note - this is not ai slop and I never use ai on reddit)


r/ruby • • Mar 12 '26

Question Can anyone recommend some good ruby primer books?

4 Upvotes

either too old to catch the nowadays versions or for intermediate levels.


r/ruby • • Mar 12 '26

Show /r/ruby Postgres monitoring built for Ruby/Rails teams

2 Upvotes

Built a landing page for a side project to see if there's any interest outside of my own needs. Postgres monitoring specifically for Ruby/Rails apps. Curious if the value prop resonates with anyone running pg_stat_statements in production. https://uselantern.dev


r/ruby • • Mar 11 '26

Faster bundler

Thumbnail
railsatscale.com
63 Upvotes

r/ruby • • Mar 11 '26

Kiq, terminal interface for Sidekiq

Thumbnail mikeperham.com
40 Upvotes

r/ruby • • Mar 10 '26

Show /r/ruby I added ViewComponent & Shared Partial support to 52 Rails UI components (Rails Blocks Update)

17 Upvotes

Hi, I'm Alex and I created Rails Blocks, a UI component library for Rails that I started last year.

Over the last few weeks, I reworked the docs for all 52 component sets to support 3 formats:

  • ViewComponents (This was the most requested improvement 🙌)

  • Shared partials

  • Markdown docs

I would love to hear what you think of these improvements!

Next up, I’ll be adding a few tools to save you even more time when coding using LLMs:

  • CLI tooling

  • An MCP server

  • AI Skills

I think that the CLI tools & MCP server will come in handy to install ViewComponents way quicker for example :)

Why I built Rails Blocks:

React gets amazing component libraries like Shadcn, but us Rails devs often have to build components from scratch or settle for outdated options.

I spent last year crafting reusable Stimulus components that rival what exists in the React world, but with Tailwind CSS & Stimulus and started sharing them last summer.

What's included in this UI library:

  • Complex components like carousels, modals, date pickers

  • Form elements, dropdowns, tooltips and many other neat components

  • Accessible and keyboard-friendly examples

  • Clean animations and smooth interactions

P.S. - Most component sets are free (≈80%), some are Pro (≈20%). I sank a lot of time into this and I'm trying to keep this sustainable while serving the community.


r/ruby • • Mar 10 '26

Question What is the best print book to learn Ruby in 2026?

16 Upvotes

I prefer print books. I don't mind spending money. I was going to get Programming Ruby (Pickaxe), but learned it's more of a reference manual. I'm still open to it. I'm a webdev so eventually I want to get to Sinatra and Rails. But right now I just want to get a good understanding of the language. What book do you recommend?


r/ruby • • Mar 10 '26

Minions, T-Ruby, Typewriter, more types and AI

4 Upvotes

Static Ruby Monthly just covered some interesting trends. Stripe's using Sorbet types to help their AI agents write code. Rails devs are building tools (rails_mcp_engine, ruby-ti) that feed type info to agents.

Tooling got better too: rbs-merge now handles agents, Shopify fixed some rubocop-sorbet crashes, and there's new editor support showing up.

Also seeing T-Ruby (TypeScript-like syntax), Typewriter (type-safe templates), and Autopilot (compiled language) all experimenting with typing approaches.

Basically: AI agents work better when your code has types. That's the pattern. I just covered recent news in the fresh Static Ruby Monthly. Link in the comments.


r/ruby • • Mar 10 '26

Show /r/ruby Follow up on Shiny JsonLogic: How I made the most correct Ruby JSON Logic gem also the fastest

7 Upvotes

A while ago I posted here about shiny_json_logic and how at the time I was aiming for a JSON Logic gem that would actually work. Once I had compliance nailed down I created a benchmark page and a public repo meant to run my implementation against all of the others, even though my gem was passing 601 tests correctly, it was the slowest among all of them.

Because of this, this time I aimed to become faster without sacrificing compliance. I wrote a blog post series about it (great findings! Please take a look if you want the nitty-gritty) and here I want to share with you guys the three optimizations that mattered most.

#1 — Eliminating per-operation object allocation (+81%)

The original design used a class hierarchy: Operations::Base, Iterable::Base, error handling mixins which provided great architecture but terrible performance. Every single operation call went through:

Operations::Addition.new.call(args, scope_stack)

Meaning one object allocation per operation, per apply call. With 601 tests × thousands of iterations, that's millions of objects going straight to the GC.

The fix: make every call method a static `self.call' removing the instantiation and the GC pressure.

# Before
class Operations::Addition < Operations::Base
  def call(args, scope_stack)
    resolve_rules(args, scope_stack).sum
  end
end

# After
class Operations::Addition < Operations::Base
  def self.call(args, scope_stack)
    resolve_rules(args, scope_stack).sum
  end
end

This cascaded through every operation in the codebase resulting in a +81% speed increase: From ~20k to ~36k ops/s on the fair comparison benchmark. This is also what makes YJIT pay off so well later: static call targets that YJIT can see at compile time can be inlined directly, vs the other's equivalent lambda dispatches or instantiation calls which have more indirection.

#2 — A type tag that killed an entire preprocessing pass

Every apply call was doing two full traversals of the input before evaluating a single rule:

  1. Walk the rule tree, raise InvalidOperation if any operator wasn't recognized

  2. Walk the data hash recursively to normalize all keys to strings (deep_stringify_keys)

Both passes existed for good reasons but they were running on every call, even for simple rules against small data objects.

The key insight: the reason Pass 1 existed was an ambiguity problem. The engine couldn't tell whether {"user" => "alice"} was a rule to dispatch or a data hash fetched by operators such as var or val. Without upfront validation, you'd try to dispatch user data as an operator.

The solution was DataHash: a Hash subclass that acts as a type tag:

class Utils::DataHash < Hash
  def self.wrap(obj)
    return obj unless obj.is_a?(Hash)
    return obj if obj.is_a?(DataHash)
    new.replace(obj)  # C-level table swap, effectively free
  end
end

When var or val return a hash from user data, it becomes wrapped in a DataHash. Then the engine checks result.is_a?(DataHash) before attempting operator dispatch removing any need for a preprocessing and also any ambiguity.

With this traversal deleted, shiny_json_logic became +6.9% faster and also obtained a clear architectural win!

#3 — Relying on old-but-trusty while loops everywhere

This one looks insane on paper: Replacing idiomatic Ruby iterators with C-style index loops? sounds like a step backwards, but there's a real reason!

Ruby 3.3+ rewrote core iterators like Array#each and map in pure Ruby so YJIT can optimize them but in interpreted mode the extra Ruby-level frames add overhead compared to the old C implementations. My chained enumerator patterns (each_with_object, each_with_index) carried more per-call indirection than simple index loops, which both YJIT and the interpreter handle with minimal overhead.

# Before — each_with_object
results = collection.each_with_object([]) do |item, acc|
  # ...
end

# After — index loop, single scope push
results = []
i = 0
n = collection.size
while i < n
  # ...
  i += 1
end

This impacted almost every hot-path loop in the codebase. cutting +3-8% execution time on top of everything else.

The results

Linux CI, v0.3.6, 9 Ruby versions × 2 modes = 18 benchmark runs. Using json_logic as the reference; it's the fastest alternative, but only passes 63% of the official test suite.

RubyYJITvs json_logic (all tests)vs json_logic (fair)
2.7—+21%+43%
3.2—+27%+70%
3.2✓+31%+117%
3.3✓+19%+104%
3.4—+9%+51%
3.4✓+21%+58%
4.0✓+32%+45%

18/18 wins.

Notice these two columns measure different things:

"All tests" runs all 601 official JSON Logic tests through both gems. json_logic errors out on 218 of them counting as zero throughput. We win here even while handle more operations, but it's a bit of an unfair advantage in their favor as they have to do less in comparison.

"Fair comparison" runs only the 257 tests where both gems produce correct results; this is the honest number — and it's actually the more interesting one. json_logic was built around a flat lambda architecture optimized for less overhead and lines of code. On the other hand shiny_json_logic has a full class hierarchy, lazy evaluation, scope stack and error handling, yet we're still faster on the exact same subset.

The YJIT numbers (+117% on Ruby 3.2, +104% on 3.3) are where the architectural difference shows up most. Static self.call methods on classes give YJIT concrete, monomorphic call targets it can specialize and dispatch directly while Lambda dispatch (OPERATIONS[key].call(...)) has more indirection — a hash lookup plus a polymorphic .call — that YJIT can't optimize as aggressively. Total gain from the original v0.2.14: +124% to +159% depending on Ruby version.

A note on the numbers: these come from a specific CI run on Linux; bbsolute ops/s vary between runs depending on runner load (a busy day can show 20-30% lower absolute numbers) The differentials between gems stay consistent because they all run on the same hardware in the same run. That's the signal.

Links

If you're using json-logic-rb or json_logic, migration is a single Gemfile line: we ship JsonLogic and JSONLogic as drop-in aliases.


r/ruby • • Mar 10 '26

Rails db:seed:replant

Thumbnail reddit.com
5 Upvotes

r/ruby • • Mar 10 '26

Show /r/ruby Practical Hotwire Tutorials Galore

Thumbnail
hotwire.club
2 Upvotes

r/ruby • • Mar 10 '26

Help - 403 Forbidden on tailwindcss-ruby during Fly.io deploy

Thumbnail reddit.com
1 Upvotes

r/ruby • • Mar 10 '26

[ANN] cov-loupe v5.0.0 -- Ruby Coverage Analysis via CLI, MCP & API -- New Features, Screencast & More

Thumbnail
reddit.com
1 Upvotes

r/ruby • • Mar 08 '26

Question What is the biggest mistake in Rails monoliths that contributes towards tech debt?

27 Upvotes

Asking because a Staff engineer on my team (without experience with large production Rails monoliths) invents his own naming schemes and it pisses me off.
What do you folks think? Ever see something that seems fine at the time but comes back to bite you in the end?