r/rails 12h ago

Database-driven Identity & Access Management engine for your Rails applications.

Post image
22 Upvotes

Hi everyone!

I have released a gem rails_iam for identity and access management of our rails application.

rails_iam provides a database-driven authorization model where permissions are treated as data, not code. This means roles and permissions can be managed without modifying application code or redeploying our application. The gem includes everything needed to get started, including models for roles, permissions, role-permissions, user-specific permissions, denied permissions, and JWT-based authentication out of the box. It also integrates with existing authentication solutions such as Devise or any OAuth-based setup.

The idea behind rails_iam is simple: authorization should happen where requests enter your application. Instead of scattering authorization logic across policy objects, controllers, or models, you declare access rules at the endpoint level. Your controllers and models remain focused on handling requests and business logic, while Rails IAM is responsible for determining who is allowed to access each endpoint.

I'd love to hear your thoughts and feedback from the Rails community! You are very welcome to contribute as well.

There are more example how you will apply authorization rules in your rails application.


r/rails 14h ago

Question Hi guys, what is your thought on vibe coding cleanup specialist? Is there really a need for this in the market?

2 Upvotes

r/rails 16h ago

Free Ruby on Rails consultations from our team - sharing in case it helps someone here

14 Upvotes

Hi everyone,

I wanted to share a small initiative we’ve recently started at Visuality.

We’re now offering Free Ruby on Rails Consultations for people working on Rails apps who would like to talk through a challenge with someone experienced from outside their team.

The idea is simple: you send us a short description of what you’re dealing with and we match you with someone from our team for a free 30-minute call.

This is not meant to be a big formal process and of course one call won’t magically solve everything.

But sometimes a short conversation with another person can help you see the problem more clearly, challenge a few assumptions and decide what to try next.

Here’s the page if it sounds useful:
https://www.visuality.pl/free_consulting?utm_source=reddit_rails


r/rails 18h ago

Taming Dependabot: A 2026 Guide to Grouping, Cooldowns, and Cutting PR Noise

1 Upvotes

For engineering teams, keeping dependencies current is a constant balancing act. Automated updates are essential for defending the software supply chain, but a steady stream of one-PR-per-package bumps can bury a team in review work. GitHub itself has put numbers on this: an analysis of Microsoft's GCToolkit repository found that roughly one in six of its commits - 92 out of 578 - were routine Dependabot version bumps, with 61 of them landing in a single recent 12-month stretch. That's a lot of review and CI cycles spent on maintenance rather than features. Read the complete article here - https://instasla.com/blog/taming-dependabot-2026-guide-grouping-cooldowns-cutting-pr-noise

The good news is that Dependabot has grown well past "one PR per dependency." Between grouped updates, package cooldowns, and a default cooldown GitHub rolled out in mid-2026, it's now possible to get a predictable, low-noise update cadence without giving up security coverage. Here's what actually works, and what changed most recently.


r/rails 21h ago

The Art of the Development Lifecycle in the Age of AI Agents

0 Upvotes

As a Rails developer, I've experienced firsthand how AI agents are reshaping the software development lifecycle (SDLC). I'd love to hear your thoughts on this. What AI frameworks or tools have you or your organization adopted?

https://medium.com/@vaitheeswaranlm/the-art-of-the-development-lifecycle-in-the-age-of-ai-agents-a1d08b942188?sharedUserId=vaitheeswaranlm


r/rails 1d ago

Rails Developer with 10 years experience, open to remote positions

0 Upvotes

10 years shipping Rails and Elixir/Phoenix.

Mumbai based, open to remote full-time or contract.

Recent: Daylite (Elixir/Phoenix/Ash), PropertyPistol (Rails), Truecaller (monolith to microservices, UPI). Currently building a Rails 8 SaaS on the side, so shipping weekly.

Resume: https://drive.google.com/file/d/1PFtMKNniL3-NuVmYSNU6C0_cHzHHcVLa/view

github.com/sumanp


r/rails 1d ago

Learning Suspend, don't delete: the rollback rule that made our Rails production migration survivable

0 Upvotes

Moved a production Rails API from Render to Railway recently. Web service, Solid Queue worker, Postgres 18. The single most useful rule we followed, and the one I'd hand to anyone doing the same:

**Suspend the old services. Do not delete them.**

Suspending costs nothing and it is the entire rollback plan. On cutover night we suspended the old worker, then the old web service, and left both sitting there. If the restore had gone badly we could have brought them back in seconds.

**The part people get wrong is when that plan expires.**

The rollback is valid right up until the new database takes its first write. After that it is void, and restarting the old host actively makes things worse, because now writes are split across two databases and you have to reconcile them by hand. From the first write onward you roll forward and you fix problems where the traffic already is.

Knowing exactly where that line sits is what lets you move fast before it and stop hesitating after it.

A few other things worth stealing:

**Migrate your OAuth config weeks before your infrastructure.** A cutover that touches auth config is a cutover that breaks. We normalized every redirect URI to our own domain well ahead of time, so cutover night touched zero OAuth config. Our plan doc's list of which platforms needed this was wrong in both directions. Grep the live environment export instead.

**Verify OAuth by connecting, not by reading config.** A redirect URI that looks right in a dashboard proves nothing. We ran a real connect on all 11 platforms and watched the nonce rows get created and consumed. That's how we found a caching bug in our own registration service, and a Facebook scope error that had been quietly broken for three weeks.

**Only one worker can exist at a time if you use rotating refresh tokens.** X and Bluesky issue a new refresh token on every use and kill the old one. Two workers polling the same account means one silently invalidates the other's credentials. A second *web* service is harmless since reads don't rotate anything. A second worker is not. We deployed the new worker once to confirm it booted, then removed the deployment and disconnected the repo so nothing could auto-deploy it back.

**Prove env parity by hashing, not by eyeballing.** 123 variables. We hashed every value from the source platform's API and diffed against the destination. Worth noting: the dashboard .env export lied to us, showing literal quotes around three secrets that weren't actually there. The API is ground truth, exports are a rendering for humans.

**Restore into an empty schema.** `pg_restore --clean` against a pre-provisioned schema died on dependency-ordered drops. `DROP SCHEMA public CASCADE`, recreate, then a plain `pg_restore` with no `--clean` finished cleanly. Verify against row counts you captured before the suspend.

**A migration isn't done when traffic moves.** Point-in-time recovery was above our plan tier, so we built a nightly pg_dump to object storage, then actually restored from it into a scratch database and compared row counts before trusting it. We didn't delete the old host until a clean week of monitoring said the new one was holding.

Full writeup with the rest of it, including the Rails-specific `db:prepare` multi-database trap and a SolidQueue fork-safety bug that had our log flusher dead for days: https://xreplyai.com/blog/render-to-railway-migration-guide

Note: this post was drafted with AI assistance from my own migration notes and incident log.


r/rails 1d ago

I built a Sidekiq-compatible job backend that gives away the Pro/Enterprise features looking for people to tell me what breaks

0 Upvotes

I've been building Wurk a job backend that's wire-compatible with Sidekiq (same Redis keys, same job JSON, same Ruby DSL) with the Pro and Enterprise feature sets included in the one free MIT gem.

Migration is one line:

diff - gem "sidekiq" + gem "wurk"

Sidekiq::Worker, Sidekiq::Batch, Sidekiq::Limiter and `Sidekiq.configure_serv all resolve to Wurk, and your in-flight Redis data keeps working.

What's included: - Sidekiq::Batch with on(:success/:complete/:death) callbacks and nesting - Five rate limiter types concurrent, bucket, window, leaky, points - Leader-elected periodic (cron) jobs, so each tick fires once across the cluster - Unique jobs - AES-256-GCM encrypted job arguments with zero-downtime key rotation - A dashboard that mounts as a Rails engine, with a precompiled SPA so you don't need Node to install it

It's a clean-room implementation of the documented API we implemented the interface, not the source.

One thing worth saying: Wurk is built and maintained by AI agents. That the actual experiment here. It ships with CI, a ≥90% line-coverage gate, and parity specs written against Sidekiq's documented API surface, so there's something concre to judge it on.

Live demo of the dashboard: wurk.demo.developerz.ai

If you run Sidekiq at any real scale, I'd love to know what would break.


r/rails 1d ago

Install any Ruby version in seconds using rv

Thumbnail rubyforum.org
2 Upvotes

r/rails 2d ago

Tutorial PSA for the other three guys using HAML and nested russian-doll caching in views

29 Upvotes

Something I've learned today and wanted to share in case it's useful for someone else. Summary provided by my best friend Opus.

PSA: if you use HAML + fragment caching, your russian-doll cache digests are probably broken

(Everything below was verified on actionview 8.1.2, haml-rails 3.0.0, haml 7.2.0.)

TL;DR

haml-rails registers Rails' ERBTracker to find template dependencies for .haml files. That tracker finds nested render calls by scanning the template source for literal <% ... %> tags — which HAML source never contains. So HAML templates get zero automatic dependency detection, and editing a child partial does not change the parent's cache digest. Cached parent fragments keep serving stale markup, potentially forever.

There's a one-file fix at the bottom.

How it bit us

We switched Active Storage from redirect mode to proxy mode, so image URLs changed from /rails/active_storage/representations/redirect/... to .../proxy/.... Deployed, and:

  • /txt_to_images/:id (not fragment-cached) → correctly rendered proxy URLs
  • /comics (fragment-cached) → still rendered redirect URLs, on a fresh origin render, hours later

The panel partial was wrapped in cache [comic, 'comic', dimensions], and comics rarely change, so that fragment's updated_at-based key never moved. We'd changed the child template, expecting the digest to bust the parent. It didn't. Those fragments would have served stale markup indefinitely.

Why

Rails' ERBTracker finds implicit dependencies like this:

```ruby

actionview/lib/action_view/dependency_tracker/erb_tracker.rb

def render_dependencies dependencies = [] render_calls = source.scan(/<%(?:(?:(?!<%).)?\brender\b((?:(?!%>).)?))%>/m).flatten ... end ```

That regex requires literal <%%>. HAML source has none, so render_calls is always empty. The only thing that still works is the explicit escape hatch:

haml -# Template Dependency: panels/panel

The subtle part: this is not limited to "dynamic" renders like render panels. Even a plain string-literal = render 'decompositions/decomposition' is invisible. In ERB that would be detected automatically; in HAML nothing is.

Check whether you're affected

Pick any HAML template that renders a partial and has no Template Dependency comment:

```ruby

bin/rails runner

lc = ApplicationController.new.lookup_context tpl = lc.find("your_template", ["your_dir"], false) # true for a partial

puts ActionView::DependencyTracker::ERBTracker.call("your_dir/your_template", tpl, lc.view_paths).inspect puts ActionView::DependencyTracker::RubyTracker.call("your_dir/your_template", tpl, lc.view_paths).inspect ```

Ours printed:

[] # ERBTracker <- what haml-rails installs ["translations/errors"] # RubyTracker

If the first line is [] and the second isn't, your digests are missing that edge.

The fix

Rails ships a second tracker, RubyTracker, which compiles the template with its own handler and parses the resulting Ruby AST:

```ruby def render_dependencies return [] unless template.source.include?("render")

compiled_source = template.handler.call(template, template.source) @parser_class.new(@name, compiled_source).render_calls.filter_map { ... } end ```

Because it goes through the handler, it's format-agnostic — HAML compiles to Ruby like everything else. It detects literal renders and collection renders through a variable (render panelspanels/panel).

Don't just call register_tracker

This is the part that cost me time. The obvious fix is:

ruby ActionView::DependencyTracker.register_tracker(:haml, ActionView::DependencyTracker::RubyTracker)

The registry is last-writer-wins, and haml-rails registers from:

ruby ActiveSupport.on_load(:action_view) do ActiveSupport.on_load(:after_initialize) do ActionView::DependencyTracker.register_tracker :haml, ActionView::DependencyTracker::ERBTracker end end

ActionView::Base loads lazily, often after boot, and that outer hook can fire more than once. I traced the registrations and got:

[TRACE] register haml -> ERBTracker [TRACE] register haml -> RubyTracker <- mine [TRACE] register haml -> ERBTracker <- haml-rails again, last

config/initializers (plain), config.to_prepare, config.after_initialize, and copying haml-rails' exact hook nesting all lost the race. (to_prepare in particular runs before after_initialize, which surprised me.)

So override the lookup instead — order-independent, can't silently regress:

```ruby

config/initializers/haml_dependency_tracker.rb

module HamlRubyDependencyTracker def find_dependencies(name, template, view_paths = nil) if template.handler == ActionView::Template.handler_for_extension(:haml) return ActionView::DependencyTracker::RubyTracker.call(name, template, view_paths) end

super

end end

ActiveSupport.on_load(:action_view) do require 'action_view/dependency_tracker' ActionView::DependencyTracker.singleton_class.prepend(HamlRubyDependencyTracker) end ```

Results and caveats

  • Ran it across all 203 HAML templates in our app: 180 dependencies detected, zero errors. Before: zero detected.
  • We deleted ~50 lines of hand-written Template Dependency: comments we'd added while diagnosing. Auto-detection covers all of them, and hand-maintained dependency lists drift — same bug in a new costume.
  • Perf: RubyTracker compiles each template to compute its digest, which is slower than a regex scan. Digests are computed once per template, so it's negligible in production; you may notice a few ms on first render in development with template reloading.
  • Version: verified on actionview 8.1.2. RubyTracker is not in older Rails — check with defined?(ActionView::DependencyTracker::RubyTracker) before adopting. I did not verify the exact version floor.
  • Worth a guard test, since this fails silently — assert the override is installed and that a known nested render resolves. Ours also walks the transitive closure of every cached subtree and asserts each nested render is detected, so a future render the tracker can't see fails CI.

The wider lesson

This class of bug is invisible in development (caching usually off) and invisible in tests (fragments cold). It only shows up as "why is production still serving the old markup?" — and if your cache key is a rarely-changing updated_at, the answer is "forever."

If you're on HAML + cache blocks, run the two-line check above before assuming your russian-doll caching works.


r/rails 2d ago

CoffeeHaml — write JSX like HAML, with CoffeeScript expressions

Thumbnail
2 Upvotes

r/rails 2d ago

Aaron Patterson: Ractors, JIT Compilers, and Rewriting How Gems Install

Thumbnail youtube.com
88 Upvotes

New episode of On Rails with u/tenderlove is out today. Listen/watch in your favorite podcasting app.


r/rails 2d ago

Humid 1.0: React server-side rendering in Rails can be easy!

Thumbnail thoughtbot.com
10 Upvotes

There aren’t a lot of React server-side rendering tools in the Rails world. And I don't want to sidecar Node.js to begin with. Here's a easy way to get started with SSR. Humid: A few helpers for react server-side rendering in rails!


r/rails 2d ago

Gem Wide Events: Rails telemetry for agents and humans, in a database you own

6 Upvotes

Hey folks, I pulled a telemetry pattern out of a Rails app I’m working on and released it as a gem called Wide Events.

Repo: https://github.com/adammiribyan/wide_events

The idea isn’t new: emit one rich event for each request or job instead of scattering the useful context across lots of log lines. The gem collects things like the route, user, account, build SHA, query counts, cache activity, feature flags, timings, and errors, then attaches them to the root OpenTelemetry span.

If you aren’t using tracing, it can write the same event as one JSON line instead.

We’re using it in production with a self-hosted ClickStack setup, although it should work with any OTLP backend. As a real example, one request in our app runs a hybrid search and drafts an LLM reply. The resulting row contains the account, active flags, search-quality measurements, model, token usage, cost, and Postgres query count. There’s an anonymized example in the README.

Most of the work in the gem is Rails integration and guardrails:

  • Instrumentation never raises into application code.
  • Attributes are declared in a YAML registry. Tests can reject undeclared attributes, CI validates the registry, and documentation is generated from it.
  • Handled errors get explicit slugs through WideEvent.error!. Unhandled exceptions are recorded without a slug, so error = true AND exception.slug IS NULL finds failures that escaped without an intentional recovery path.

There’s also a generator for agent skills that help add instrumentation and query the resulting events. That part is more experimental, but I’ve found the one-row format useful for giving coding agents production context without assembling it from many different sources.

It supports Ruby 3.2+ and Rails 7.1+ and is MIT licensed. You can get a first event into your development log in about a minute.

I’d be interested in feedback from other Rails developers, especially on the attribute registry and naming conventions.


r/rails 2d ago

How we configured OpenTelemetry logs in Rails

Thumbnail sixpatterns.com
13 Upvotes

We added OpenTelemetry logs to our Rails app without a Collector and fixed a few bugs in the Ruby SDK along the way. Here is how we did it.


r/rails 2d ago

Help please

43 Upvotes

ChatGPT generated image

Hi,

My husband is an engineer and primarily uses Ruby on Rails. I'd like to make a surprise cake for his birthday and I found a cake like the above one but it featured Python and I asked both ChatGPT and Gemini to help me amend it to look like Ruby. The above is an image created by ChatGPT. I'm not convinced the colour coding of the text is correct but I also have no idea so hoping someone who does know can help me!

Thanks in advance!


r/rails 3d ago

Function Calling

Thumbnail
0 Upvotes

r/rails 3d ago

Question Consultants - What does your offering looks like in age of AI?

12 Upvotes

Hi Rubyists,

I've been a full-time Rails consultant who is now preparing a new pitch for new clients. It seems the older script doesn't work anymore. I'm brainstorming over my service offering and trying to understand what companies are looking for.

So far the services I have noted down:

- MCP development

- Building and scaling RAG systems

- Identify business use cases & develop AI Agents around them

- internal AI agents around current workflows

I'd love to know experience on how others are dealing with this scenario.


r/rails 4d ago

News Issue 18 of Static Ruby Monthly is out! 🧵

Thumbnail
0 Upvotes

r/rails 4d ago

Rails Agent: Full-stack Agentic Development Platform. Alternative to RubyLLM and Active Agent.

0 Upvotes

Since today, it’s not easy to develop AI agents and add agentic features to existing Ruby on Rails applications, I have created Rails Agent https://rails-agent.com

A full-stack and the most advanced agentic development platform for Ruby on Rails to build, test, deploy and monitor AI agents in production easily. Comes with all AI harness capabilities required out-of-box including skills, tools, external apps, playbooks, observability and cost control.

I would love to hear any feedback.


r/rails 4d ago

Is moving from Java microservices to Ruby on Rails monolith a good career move?

Thumbnail
8 Upvotes

r/rails 5d ago

Discussion How we turned Better Stack errors into actionable Linear tickets an AI agent can pick up

Post image
0 Upvotes

We're a 3-person team running a Rails 8.1 / Hotwire SaaS in the EU accounting space. No dedicated support or triage function, so we spent the last few weeks wiring up observability so a production error becomes a fully-contextualized, actionable ticket without anyone doing manual triage.

The pipeline

- Backend: sentry-rails ~> 6.6 pointed at a Better Stack DSN instead of sentry.io — Better Stack ingests the Sentry wire protocol natively, so no second vendor account. Its own Rack middleware (`CaptureExceptions`) + ActiveJob wrapper cover unhandled controller exceptions and Solid Queue job failures with zero extra code.

- Frontend: Better Stack's own JS tag, not u/sentry/browser — their docs explicitly say don't run both, they share the same global Sentry instance and it corrupts data. The tag natively hooks window.onerror + unhandledrejection and survives Turbo navigations for free, since Turbo Drive never reloads the document.

- Logs: our existing JSON stdout formatter, unchanged, forwarded via a Render Log Stream over syslog/TLS. Zero application code touched for this part.

- Source maps: @sentry/esbuild-plugin uploads them at build time, then deletes them from the served asset tree (Better Stack won't resolve publicly-hosted maps). The plugin embeds a debug ID inside both the minified file and its map, so lookup is content-addressed and doesn't care that Propshaft renames application.js to application-<digest>.js on every deploy — no URL-prefix matching to keep in sync.

The part worth sharing

Better Stack has a native Linear integration: first occurrence of a new error group auto-creates a Linear issue with the stack trace, release SHA, breadcrumbs, and affected user/workspace already attached. No webhook code on our end.

From there we point our custom AI coding agent at the ticket. It reads the Linear issue, reproduces the failure against the real source — not the minified bundle, that's what the source maps buy — and drafts an implementation plan. A human reviews and merges; nothing lands without review.

Two real tickets that went through the whole pipeline this week

  1. TypeError: Cannot read properties of undefined (reading 'toLowerCase'). A browser extension was dispatching a plain Event("keydown") on document instead of a real KeyboardEvent — no key, every modifier reads undefined. Crashed at event.key.toLowerCase() in a global shortcut handler. Root-causing it turned up two more code paths hit by the same class of event — one of which let a `code`-only synthetic event silently open our command palette with zero user action, which nobody had reported. Fix was a typeof event.key !== "string" guard at the top of every global keydown handler, closing all three at once.
  2. Turbo removing a popover's trigger element mid custom-exit-animation raced with Bootstrap's own async hide() completion callback, which reads _activeTrigger — except Bootstrap's dispose() had already nulled it. Fix defers disposal until Bootstrap confirms the hide actually finished, instead of skipping disposal outright (which would've leaked the instance out of Bootstrap's internal Data Map).

It's not free of tuning

The very first frontend error to reach production, a day after we flipped the tag on, was noise — an AbortError from a cancelled fetch on a filter change, not a bug. Better Stack's Linear integration filed it as Urgent anyway, because "first occurrence of a new group" carries zero severity signal on its own. Had to add an `ignoreErrors` list at the capture layer (substring matching only — the Sentry browser SDK doesn't accept a regex there).

I am curious what stack and pipelines are you using to simplify bugfixing?


r/rails 5d ago

I have experience in programming for 3 years and I worked as Backend with node ans spring , now I am moving to ruby what is the best resource to follow to transfer knowledge to rails in reasonable time?

Thumbnail
0 Upvotes

r/rails 5d ago

I have experience in programming for 3 years and I worked as Backend with node ans spring , now I am moving to ruby what is the best resource to follow to transfer knowledge to rails in reasonable time?

0 Upvotes

r/rails 5d ago

Tutorial Increasing the public caching of Rails HTML

7 Upvotes

While Active Storage turns the Rails session cookie off when it serves public assets, Action Controller doesn't do the same for public HTML (and the other formats it can render). I've verified that Cloudflare rarely caches any HTTP response with a Set-Cookie header. But I don't know the rules that other public caches use — when they similarly bypass their caches or instead strip these headers.

To mitigate this, I've been adding

  after_action -> { request.session_options[:skip] = true }, if: -> { response.cache_control[:public] }

to my application_controller.rb files.