Skip to content

Instantly share code, notes, and snippets.

@tobyclemson
Created August 8, 2012 08:00
Show Gist options
  • Save tobyclemson/3293300 to your computer and use it in GitHub Desktop.
Save tobyclemson/3293300 to your computer and use it in GitHub Desktop.
A little cleaner
module Visitors
class PartialViewVisitor
def initialize description
@description = AddressableObjectTree.new(description)
@view = AddressableObjectTree.new({})
@cursor = Address.new
end
def view
@view.unwrap
end
def start key, value
@cursor.push(key) unless root_node?(key)
end
alias_method :start_hash, :start
alias_method :start_array, :start
alias_method :start_leaf, :start
def end key, value
@cursor.pop
end
alias_method :end_hash, :end
alias_method :end_array, :end
alias_method :end_leaf, :end
def visit_hash key, value
if @description.node?(@cursor.parent) && !root_node?(key)
@view.put @cursor.parent, key, {}
end
end
def visit_array key, value
if @description.node?(@cursor.parent) && !root_node?(key)
@view.put @cursor.parent, key, []
end
end
def visit_leaf key, value
if @description.leaf?(@cursor.self) && !root_node?(key)
@view.put @cursor.parent, key, value
end
end
def root_node?(key)
key == "root"
end
end
class Address
def initialize
@address = []
end
def push reference
@address.push reference
end
def pop
@address.pop
end
def parent
@address[0..-2]
end
def self
@address
end
end
class AddressableObjectTree
def initialize tree
@tree = tree
end
def unwrap
@tree
end
def node? address
with_node_at(address) do |node|
(node.is_a?(Hash) || node.is_a?(Array))
end
end
def leaf? address
with_node_at(address) do |node|
!(node.is_a?(Hash) || node.is_a?(Array))
end
end
def get address
find_node_at(address)
end
def put address, key, value
with_node_at(address) do |node|
node[key] = value
end
end
private
def with_node_at(address, &block)
find_node_at(address).tap do |node|
block.call(node) if node
end
end
def find_node_at(address)
address.reduce(@tree) { |subtree, key| subtree[key] if subtree }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment