Skip to content

Instantly share code, notes, and snippets.

@cheeyeo
Created August 11, 2015 23:48
Show Gist options
  • Save cheeyeo/627c01da0f087ffd6e2b to your computer and use it in GitHub Desktop.
Save cheeyeo/627c01da0f087ffd6e2b to your computer and use it in GitHub Desktop.
XML DSL
class User
attr_accessor :name, :pet_name
end
class Post
end
class Factory < BasicObject
def initialize
@attributes = {}
end
attr_reader :attributes
def method_missing(name, *args, &block)
attributes[name] = args[0]
end
end
class DefinitionProxy
def factory(factory_class, &block)
factory = Factory.new
factory.instance_eval(&block)
Smokestack.registry[factory_class] = factory
end
end
module Smokestack
@registry = {}
def self.registry
@registry
end
def self.define(&block)
definition_proxy = DefinitionProxy.new
definition_proxy.instance_eval(&block)
end
def self.build(factory_class, overrides={})
instance = factory_class.new
factory = registry[factory_class]
attributes = factory.attributes.merge(overrides)
attributes.each do |attribute_name, value|
instance.send("#{attribute_name}=", value)
end
instance
end
end
Smokestack.define do
factory User do
name "Lorem Ipsum"
pet_name "LI"
end
factory Post
end
user = Smokestack.build(User)
puts user.name
puts user.pet_name
other_user = Smokestack.build(User, name: 'Bob')
puts other_user.name
puts other_user.pet_name
require "nokogiri"
require 'virtus'
class Result
include Virtus.model
attribute :id, String
attribute :color, String
attribute :name, String
end
class Scan
include Virtus.model
attribute :name, String
attribute :results, Array[Result]
end
class Factory < BasicObject
def initialize
@attributes = {}
end
attr_reader :attributes
def method_missing(name, *args, &block)
attributes[name] = args[0]
end
end
class Parser
def initialize(file)
@reader = Nokogiri::XML::Reader(File.open(file))
@hash = {}
@scan = Scan.new
Smokestack.registry['Hash']=@hash
Smokestack.registry[Scan] = @scan
end
def factory_class
Smokestack.registry[Scan]
end
def inside_element(name, &block)
@reader.each do |node|
if node.name == name && node.node_type == Nokogiri::XML::Reader::TYPE_ELEMENT
@current_node = Nokogiri::XML(node.outer_xml).at("./#{name}")
self.instance_eval(&block)
end
end
end
def for_element(name, &block)
@current_node.xpath("./#{name}").each do |a|
@node = a
self.instance_eval(&block)
end
end
end
module Smokestack
@registry = {}
def self.registry
@registry
end
def self.define(file, &block)
parser = Parser.new(file)
parser.instance_eval(&block)
end
def self.build(factory_class, overrides={})
instance = factory_class.new
factory = registry[factory_class]
attributes = factory.attributes.merge(overrides)
attributes.each do |attribute_name, value|
instance.send("#{attribute_name}=", value)
end
instance
end
end
Smokestack.define('sample.xml') do
inside_element 'Scan' do
for_element 'Name' do
puts @node.text
@hash['name'] = @node.text
@scan.name = @node.text
end
inside_element 'ReportItems' do
puts "Getting ReportItems"
for_element 'ReportItem' do
@hash['report_items'] ||= []
inside_element 'Name' do
puts @current_node.text
@hash['report_items'] << {:text => @current_node.text, :id => @node.attr('id')}
@scan.results << {:text => @current_node.text, :id => @node.attr('id')}
end
end # end for_element
end
end
end
puts Smokestack.registry[Scan].inspect
@cheeyeo
Copy link
Author

cheeyeo commented Aug 11, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment