Skip to content

Instantly share code, notes, and snippets.

@ianwhite
Created October 27, 2009 14:46
Show Gist options
  • Save ianwhite/219609 to your computer and use it in GitHub Desktop.
Save ianwhite/219609 to your computer and use it in GitHub Desktop.
module VisitorHelper
# give this method an object or collection, optional other arguments, and a block. When you call visit within that block, the block itself will be called with the argument(s)
#
# <ul>
# <% visit tree do |node| %>
# <li>
# <%= node.name %>
# <ul><% visit node.children %></ul>
# </li>
# <% end %>
# </ul>
#
# For nested visitors, you can provide :as => <name> to distinguish which visitor to call
#
# <% visit tree, 1, :as => :outer_visit do |node, depth| %>
# <p>
# <%= "#{depth}. node.name" %>
# <% visit node.children, :as => :inner_visit do |child| %>
# <em><%= child.name %></em>
# <% inner_visit child.children %>
# <% end %>
# </p>
# <% outer_visit node.children, depth + 1 %>
# <% end %>
#
#
def visit(collection, *args, &visitor)
opts = args.extract_options!
visit_name = opts[:as] || :visit
metaclass.send :define_method, visit_name do |collection, *args|
Array(collection).inject('') {|out, i| out << instance_exec(i, *args, &visitor)}
end
send visit_name, collection, *args
ensure
metaclass.send :remove_method, visit_name
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment