How Arel Converts Ruby Queries into SQL Statements
blog.codeship.com
blog.codeship.com
Hm. Isn't that a (map)?
Again, Alan Kay is right -- computer programming is "half a field" that often forgets its own content. Ironically, programming patterns were actually forwarded as a form of technical literature for the programming field, not so much as an approved cookbook.
In a dynamically typed language where checking if an object is of a specific class, and where you can do if-then or switch(case/when) to discriminate the node types easily, the visitor pattern kind-of devolves into pretty much nothing, and hence the description doesn't "sound" right because it misses out on most of what makes the Visitor pattern worthwhile to discuss as a pattern in e.g. C++ or Java.
Instead of e.g. implementing an "accept" method for each node that calls "visit" on a visitor, and implementing a "Visitor" interface and inheriting from that, in Ruby you might instead just opt to use a case/when structure for the visitor, and wrap it in a single method or a lambda if you need to pass it around.
And of course you can have the equivalent in C++/Java and similar languages, but that would lose the main benefit of having the completeness of the visitor statically checked (In other words, you can write dynamically typed code in any language some way or the).
In a statically typed language, this was "clever" because if you put an accept() method on each class that calls visitor.visit(this|self|whatever) it makes the compiler enforce that your visitor classes implements a visit() method for each possible node type.
For dynamic languages like Ruby that benefit kind of evaporates, but at the same time runtime type checks are normal, and so yes, you can just use any standard algorithm that iterates over the nodes in your preferred order and pass it a closure or suitable object that .e.g. does "case object.class; when ..." or similar to group the code together instead. If one absolutely wanted to mimic the GoF visitor, one could do 'send("visit_#{object.class.name}".to_sym,object)' or something along those lines to make visitors be classes with methods for each node type instead.
A lot of the GoF patterns are mainly useful in statically typed languages and/or languages lacking first-order functions or closures.