The point of a dynamic language is to be dynamic, ie you can do those things at runtime.
With Rails you have the option of pry-rails, and you can get a list of descendants of important parent classes like ActiveRecord with this: https://apidock.com/rails/Class/descendants
With the combination of vim, rspec, pry, fzf, and ripgrep, it's possible to become quite comfortable refactoring pure Ruby and Ruby+Rails code. But it does take some time to learn how to navigate the Rails runtime code generation magic. The more magic the code, the more you might have to use a debugger to break on method definition, but Ruby's dynamicism lets you do that.
On the topic of frameworks with a lot of magic, having used both Rails and Spring Boot (with Java and Kotlin), I'll take Rails any day. It was way easier to introspect Rails codegen magic with Pry, than Spring's codegen magic with IntelliJ. With Spring Boot, even with Kotlin, we had the burden of semi-manual typing, but lost a lot of the benefits because a lot of DB interaction and API payload handling was still only runtime checked.
With Rails you have the option of pry-rails, and you can get a list of descendants of important parent classes like ActiveRecord with this: https://apidock.com/rails/Class/descendants
With the combination of vim, rspec, pry, fzf, and ripgrep, it's possible to become quite comfortable refactoring pure Ruby and Ruby+Rails code. But it does take some time to learn how to navigate the Rails runtime code generation magic. The more magic the code, the more you might have to use a debugger to break on method definition, but Ruby's dynamicism lets you do that.
On the topic of frameworks with a lot of magic, having used both Rails and Spring Boot (with Java and Kotlin), I'll take Rails any day. It was way easier to introspect Rails codegen magic with Pry, than Spring's codegen magic with IntelliJ. With Spring Boot, even with Kotlin, we had the burden of semi-manual typing, but lost a lot of the benefits because a lot of DB interaction and API payload handling was still only runtime checked.