Hey there, I have read the few posts here on when/how to use the visitor pattern, and some articles/chapters on it, and it makes sense if you are traversing an AST and it is highly structured, and you want to encapsulate the logic into a separate "visitor" object, etc. But with Ruby, it seems like overkill because you could just use blocks to do nearly the same thing.
I would like to pretty_print xml using Nokogiri. The author recommended that I use the visitor pattern, which would require I create a FormatVisitor or something similar, so I could just say "node.accept(FormatVisitor.new)".
The issue is, what if I want to start customizing all the stuff in the FormatVisitor (say it allows you to specify how nodes are tabbed, how attributes are sorted, how attributes are spaced, etc.).
- One time I want the nodes to have 1 tab for each nest level, and the attributes to be in any order
- The next time, I want the nodes to have 2 spaces, and the attributes in alphabetical order
- The next time, I want them with 3 spaces and with two attributes per line.
I have a few options:
- Create an options hash in the constructor (FormatVisitor.new({:tabs => 2})
- Set values after I have constructed the Visitor
- Subclass the FormatVisitor for each new implementation
- Or just use blocks, not the visitor
Instead of having to construct a FormatVisitor, set values, and pass it to the node.accept method, why not just do this:
node.pretty_print do |format|
format.tabs = 2
format.sort_attributes_by {...}
end
That's in contrast to what I feel like the visitor pattern would look like:
visitor = Class.new(FormatVisitor) do
attr_accessor :format
def pretty_print(node)
# do something with the text
@format.tabs = 2 # two tabs per nest level
@format.sort_attributes_by {...}
end
end.new