Pretty much any switch/case or multipronged if is dispatch in disguise. Sometimes the switch/case/if is the right choice, sometimes it's making the code more convoluted. Once you step up a degree in complexity, you get e.g. lookup tables and class hierarchies to emulate more dynamic dispatch. Complex dispatch is all over the place in most large systems.
Ruby is "an offender" in this to you because you hate the pattern that untangles the huge unholy mess that less dynamic languages use instead. E.g. hacky workarounds like whole class hierarchies or (marginally better) maps from values you dispatch on to first order functions/closures
I have worked in over a dozen languages, and I've never seen a medium to large sized project where some form of dispatch mechanism hasn't been part of the codebase somewhere.
And I'll take the simplicity of dynamic dispatch over hand rolling verbose mappings any day.
> All the most heinous bugs I've had to deal with in my life were about magic in ruby. I've worked in 3 of the biggest rails codebases in the world, and in the end we had build checks to deny code with magic.
I have no like for Rails, it encourages a lot of awful shit, but I also find this really curious, because the backtraces will clearly indicate you've passed through method_missing, you can breakpoint requests and attach remote debuggers to in flight requests, and execute code in-context in those requests.
If that's too complex, sure, maybe a large Rails code base isn't right for you. I don't want to work on Rails codebases either, but because of Rails, not Ruby, nor because the dynamism makes it any harder to debug.
> Software code should be optmised for reading and debugging, not looking nice for first time writes.
I agree,and it's exactly why I love Ruby.