Created
August 11, 2015 23:48
-
-
Save cheeyeo/627c01da0f087ffd6e2b to your computer and use it in GitHub Desktop.
XML DSL
This file contains hidden or 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
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 |
This file contains hidden or 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
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Idea from https://robots.thoughtbot.com/writing-a-domain-specific-language-in-ruby