Created
August 8, 2012 08:00
-
-
Save tobyclemson/3293300 to your computer and use it in GitHub Desktop.
A little cleaner
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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