Skip to content

Instantly share code, notes, and snippets.

@jamis
Last active March 1, 2017 16:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamis/3b8b11c410f97c5a423b9920efa2a99b to your computer and use it in GitHub Desktop.
Save jamis/3b8b11c410f97c5a423b9920efa2a99b to your computer and use it in GitHub Desktop.
Source files from a presentation to AtomicJolt about wrapping a general API (Nokogiri) with a domain specific API
# rubocop:disable Style/SingleLineMethods
require 'nokogiri'
class Object; alias try send; end
class NilClass; def try(*); nil; end; end
<tree>
<person id="p0001">
<name>
<full>Frank Edward Redington</full>
<given>Frank Edward</given>
<surname>Redington</surname>
</name>
<event type="birth">
<date>1914-04-03</date>
<location>Elma, Chehalis, Washington, USA</location>
</event>
<event type="death">
<date>1978-12-27</date>
<location>Medford, Jackson, Oregon, USA</location>
</event>
</person>
<person id="p0002">
<name>
<full>Frank Willard Redington</full>
<given>Frank Willard</given>
<surname>Redington</surname>
</name>
<event type="birth">
<date>1865-01-22</date>
<location>Orleans, Ionia, Michigan, USA</location>
</event>
<event type="death">
<date>1930-12-27</date>
<location>Elma, Grays Harbor, Washington, USA</location>
</event>
</person>
<person id="p0003">
<name>
<full>Francis Burrows</full>
<given>Francis</given>
<surname>Burrows</surname>
</name>
<event type="birth">
<date>1880-04-10</date>
<location>Vina, Tehama, California, USA</location>
</event>
<event type="death">
<date>1964-11-27</date>
<location>Elma, Grays Harbor, Washington, USA</location>
</event>
</person>
<family id="f0001">
<father id="p0002" />
<mother id="p0003" />
<child id="p0001" />
<event type="marriage">
<date>1911-12-21</date>
<location>Oroville, Butte, California, USA</location>
</event>
<event type="divorce">
<date>between 1920 and 1927-12-12</date>
</event>
</family>
</tree>
require './000-_init'
doc = Nokogiri::XML(File.read('001-data.xml'))
frank = doc.at('person#p0001')
puts frank.at('name full').try(:text)
puts frank.at('event[type=death] date').try(:text)
require './000-_init'
def find_person(doc, id)
doc.at("person##{id}")
end
def person_name(record)
record.at('name full').try(:text)
end
def person_death(record)
record.at('event[type=death] date').try(:text)
end
doc = Nokogiri::XML(File.read('000-data.xml'))
frank = find_person(doc, 'p0001')
puts person_name(frank)
puts person_death(frank)
require './000-_init'
require './005-genealogy_take1'
#require './007-genealogy_take2'
#require './009-genealogy_take3'
tree = Genealogy::Tree.from_file('001-data.xml')
frank = tree.find_person('p0001')
puts frank.name.full
puts frank.death.date
require 'nokogiri'
module Genealogy
class Tree
def self.from_file(filename)
from_xml(File.read(filename))
end
def self.from_xml(xml)
new(Nokogiri::XML(xml))
end
def initialize(node)
@node = node
end
def find_person(id)
person = @node.at("person##{id}")
person ? Person.new(person) : nil
end
end
# ==================================================================== #
class Person
def initialize(node)
@node = node
end
def name
@name ||= begin
name = @node.at('name')
name ? Name.new(name) : nil
end
end
def event(type)
event = @node.at("event[type=#{type}]")
event ? Event.new(event) : nil
end
def birth
@birth ||= event :birth
end
def death
@death ||= event :death
end
end
# ==================================================================== #
class Name
def initialize(node)
@node = node
end
def full
@node.at('full').try(:text)
end
def surname
@node.at('surname').try(:text)
end
def given
@node.at('given').try(:text)
end
end
# ==================================================================== #
class Event
def initialize(node)
@node = node
end
def date
@node.at('date').try(:text)
end
def location
@node.at('location').try(:text)
end
end
end
require 'delegate'
class Wrapper < SimpleDelegator
def encrypt
# shhh -- just rot13 here
tr('a-z', 'n-za-m')
end
end
string = Wrapper.new('hello world')
puts string.length
puts string.encrypt
require 'delegate'
require 'nokogiri'
module Genealogy
class Tree < SimpleDelegator
def self.from_file(filename)
from_xml(File.read(filename))
end
def self.from_xml(xml)
new(Nokogiri::XML(xml))
end
def find_person(id)
node = at("person##{id}")
node ? Person.new(node) : nil
end
end
# ==================================================================== #
class Person < SimpleDelegator
def name
@name ||= begin
name = at('name')
name ? Name.new(name) : nil
end
end
def event(type)
event = at("event[type=#{type}]")
event ? Event.new(event) : nil
end
def birth
@birth ||= event :birth
end
def death
@death ||= event :death
end
end
# ==================================================================== #
class Name < SimpleDelegator
def full
at('full').try(:text)
end
def surname
at('surname').try(:text)
end
def given
at('given').try(:text)
end
end
# ==================================================================== #
class Event < SimpleDelegator
def date
at('date').try(:text)
end
def location
at('location').try(:text)
end
end
end
module A
def hiccup
'HICCUP!'
end
end
o = Object.new.extend(A)
puts o.hiccup #-> HICCUP!
require 'nokogiri'
module Genealogy
module Tree
def self.from_file(filename)
from_xml(File.read(filename))
end
def self.from_xml(xml)
Nokogiri::XML(xml).extend(self)
end
def find_person(id)
person = at("person##{id}")
person ? person.extend(Person) : nil
end
end
# ==================================================================== #
module Person
def name
@name ||= begin
name = at('name')
name ? name.extend(Name) : nil
end
end
def event(type)
event = at("event[type=#{type}]")
event ? event.extend(Event) : nil
end
def birth
@birth ||= event :birth
end
def death
@death ||= event :death
end
end
# ==================================================================== #
module Name
def full
at('full').try(:text)
end
def given
at('given').try(:text)
end
def surname
at('surname').try(:text)
end
end
# ==================================================================== #
module Event
def date
at('date').try(:text)
end
def location
at('location').try(:text)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment