My experience is exactly the same as Milch's. I've tried to fix stuff in Gitlab but given up when I couldn't even find where it things are defined.
That can happen in other languages, e.g. Rust or C where macros are used. But it's pretty much the exception there whereas in Rails it seems to be done by default.
Discoverability is much worse, LSPs aren't super helpful. Using Dash (documentation app) helps a ton. Still some names are confusing after switch (took a minute to recall that 'filter' is actually 'select' in Ruby).
I won't say that dev experience is bad but it's definitely different.
Weird that searching for it didn't yield any results, though I stand corrected. However it seems that select is the actual "root" of documentation. Filter sends to find_all, find_all sends to filter or select.
People often miss the difference between simple and easy. Yes, Ruby is easy, but it's not simple, and it will make you suffer a lot if you get to a complex app. The debugging sessions in Rails are a nightmare. Meanwhile Ruby community is acting like religion, it's almost impossible to convert people from Ruby to other languages, they don't see the language as tool, but as part of their identity
Happiness doesn't always translate into performance, e.g. famous Twitter logo until they moved into JVM and Scala.
While Ruby on Rails took the fame, we already had similar experiences with AOLServer and Vignette, using Tcl.
We had our own variant at a Portuguese startup, and eventually the founders created OutSystems, one of the first graphical RAD tools for Websites and distributed systems development in low code/no code, targeting JVM or CLR infrastructure.
Now having said all of this, it is great to finally see CRuby getting a JIT in the box.
On any sufficiently large and old app, something will always break in a way that isn't caught by your tests or manual testing, and only shows up after it goes out live.
While it is deprecated, you can do a File=>New Project for Web Forms in 2026.
In Rails my tests are mostly to ensure that a request to a controller returns the expected response and the expected changes in the database. Unit tests are often on validations and the errors they return for invalid data. Then there are functional tests that drive a headless browser.
Not fun in production.
Dynamic languages with optional typing like BASIC or Common Lisp is another matter.
I have taken applications from 2-to-3, 3-to-4, and so on, through 8.X.
If anything it has gotten better/easier over time. The most challenging upgrades were 2.X to 3.X (for reasons I can't recall), and then 6.X to 7.X (for an application that had issues adopting zeitwerk). In both of those situations, there was a lot of rote legwork, but once tests were passing, the application was working reliably. The other upgrades (3-to-4, 4-to-5, 5-to-6, 7-to-8) weren't happy-fun-rainbows-and-unicorns, but they weren't catastrophically complicated? Not even in fairly large codebases.
For each of these, a strong test suite was the best tool, which it sounds like you already know?
In my experience, the other impactful factors were:
(1) Reading the CHANGELOGs and knowing enough about Rails to know what they meant for the application.
(2) Using test fixtures (or fixtures with only some factories) for a quicker feedback loop for engineers.
(3) Having a true QA function in the company that isn't just engineers testing their own code.
Many big structural changes, IIRC bundler integration, plugins became engines, etc...
It was the big Rails+MERB merge.
I have my criticisms of Rails, but that definitely set it on a better path.
For web, I can't really offer any useful positive input, I was never satisfied with any framework for Python or Node. I see people praise RoR and Phoenix quite a lot tho!
Rails? Depends on the project.