Skip to content

Commit

Permalink
adding some XML stuff: .get and .all
Browse files Browse the repository at this point in the history
  • Loading branch information
Anders Törnqvist committed Mar 14, 2011
1 parent d3b2525 commit 80c9d5f
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 40 deletions.
107 changes: 72 additions & 35 deletions example/zerigodns.rb
Expand Up @@ -18,8 +18,21 @@ class Zerigo

# Zones are called Domains in our web interface.
class Zone < Zerigo
property :id, Integer do
validate_presence
end
property :nx_ttl, String, :remote_name => 'nx-ttl'
property :default_ttl, String, :remote_name => 'default-ttl'
property :domain, String
property :state, String
resto_request do
path 'api/1.1/zones'
translator [:zone]
end

resto_response do
format :xml, :xpath => '//zone'
translator :default
end
end

Expand All @@ -28,45 +41,69 @@ class Zone < Zerigo
# http://nokogiri.org/
# http://www.w3.org/TR/xpath/
# http://www.w3schools.com/xpath/xpath_syntax.asp
#Zone.all(:per_page => 3, :page => 1)
#Zone.get(1871829974)
zones = Zone.all(:per_page => 3, :page => 1)
pp zones.first.id
pp zones.first.attributes
zone = Zone.get(1871829974)
pp zone.attributes


<zone>
<nx-ttl nil="true"></nx-ttl>
<default-ttl type="integer">900</default-ttl>
<created-at type="datetime">2010-12-04T22:17:14Z</created-at>
<follow-template>no</follow-template>
<ns2 nil="true"></ns2>
<updated-at type="datetime">2011-03-06T15:53:15Z</updated-at>
<domain>readinglist.com</domain>
<zone-template-id nil="true"></zone-template-id>
<ns3 nil="true"></ns3>
<hosts type="array"/>
<notes nil="true"></notes>
<tag-list></tag-list>
<slave-nameservers></slave-nameservers>
<state>active</state>
<ns-type>pri_sec</ns-type>
<ns1 nil="true"></ns1>
<customer-id type="integer">1712607333</customer-id>
<hosts-count type="integer">0</hosts-count>
<id type="integer">1871829974</id>
</zone>

xml =<<-XML
<zone>
<nx-ttl nil="true"></nx-ttl>
<default-ttl type="integer">900</default-ttl>
<created-at type="datetime">2010-12-04T22:17:14Z</created-at>
<follow-template>no</follow-template>
<ns2 nil="true"></ns2>
<updated-at type="datetime">2011-03-06T15:53:15Z</updated-at>
<domain>readinglist.com</domain>
<zone-template-id nil="true"></zone-template-id>
<ns3 nil="true"></ns3>
<hosts type="array"/>
<notes nil="true"></notes>
<tag-list></tag-list>
<slave-nameservers></slave-nameservers>
<state>active</state>
<ns-type>pri_sec</ns-type>
<ns-type>pri_sec</ns-type>
<ns1 nil="true"></ns1>
<customer-id type="integer">1712607333</customer-id>
<hosts-count type="integer">0</hosts-count>
<id type="integer">1871829974</id>
</zone>
XML

#doc = Nokogiri::XML(xml)
#path = doc.xpath('//zone')
#puts path.size
#path.each do |node|
# puts "********************"
# node.children.map do |child|
# puts "#{child.name} : #{child.text}" if child.is_a?(Nokogiri::XML::Element)
# end
#end

# http://woss.name/2011/03/06/using-tcpflow/
# tcpflow
require 'rubygems'
require 'nokogiri'
# http://www.circlemud.org/~jelson/software/tcpflow/tcpflow.1.html
#require 'rubygems'
#require 'nokogiri'
#
#attribute_name = "follow-template"# <follow-template>no</follow-template>
#@builder = Nokogiri::XML::Builder.new do |xml|
#
# xml.zone do
# xml.nx_ttl(:nil => "true") { xml.text "" }
# xml.default_ttl(:type => true) { xml.text 900 }
# xml.send(attribute_name, :type => "Integer") { xml.text 'no' }
# xml.send("created-at", :type => "datetime") do
# xml.text "2010-12-04T22:17:14Z"
# end
# end
#end
#
#puts @builder.doc

attribute_name = "follow-template"# <follow-template>no</follow-template>
@builder = Nokogiri::XML::Builder.new do |xml|

xml.zone {
xml.nx_ttl(:nil => "true")
xml.default_ttl(:type => true) { xml.text 900 }
xml.send(attribute_name, :type => "Ingeter") { xml.text 'no' }
}
end

puts @builder.doc

2 changes: 1 addition & 1 deletion lib/resto/format/json.rb
Expand Up @@ -20,7 +20,7 @@ def encode(hash, options = nil)
Yajl::Encoder.encode(hash)
end

def decode(json)
def decode(json, options=nil)
raise ArgumentError unless json.is_a?(String)

Yajl::Parser.parse(json)
Expand Down
43 changes: 42 additions & 1 deletion lib/resto/format/xml.rb
@@ -1,6 +1,8 @@
# encoding: utf-8

# https://tools.ietf.org/html/rfc3023
require 'resto/format'
require 'nokogiri'

module Resto
module Format
Expand All @@ -14,11 +16,50 @@ def accept; 'application/xml, */*'; end
def content_type; 'application/xml;charset=utf-8'; end

def encode(hash, options = nil)
Nokogiri::XML::Builder.new { |xml| to_xml(hash, xml) }.to_xml
end

def decode(xml, options)
xpath = options.fetch(:xpath)

doc = Nokogiri::XML(xml)
nodes = doc.xpath(xpath)

case nodes.size
when 0
{}
when 1
elements_to_hash(nodes.first.children)
else
nodes.map { |node| elements_to_hash(node.children) }
end
end

def decode(xml)
private

def elements_to_hash(children)
attributes = {}

children.each do |element|
if element.is_a?(Nokogiri::XML::Element)
attributes[element.name] = element.text
end
end

attributes
end

#http://nokogiri.org/Nokogiri/XML/Builder.html
def to_xml(hash, xml)
hash.each do |key, value|
xml.send("#{key.to_s}_") do
if value.is_a?(Hash)
to_xml(value, xml)
else
xml.text value if value
end
end
end
end
end
end
Expand Down
18 changes: 15 additions & 3 deletions lib/resto/response/base.rb
Expand Up @@ -16,10 +16,20 @@ def translator(translator)
self
end

def format(symbol)
def format(symbol, options = {})
xpath = options[:xpath]
xpath(xpath) if xpath
formatter(Resto::Format.get(@symbol = symbol))
end

def xpath(xpath)
tap { @xpath = xpath }
end

def read_xpath
@xpath || "//#{@klass.to_s.downcase}"
end

def formatter(formatter)
tap { @formatter = formatter }
end
Expand All @@ -33,7 +43,7 @@ def http_response(response)
end

def read_body
body ? current_formatter.decode(body) : nil
body ? current_formatter.decode(body, :xpath => read_xpath) : nil
end

def body
Expand All @@ -57,7 +67,9 @@ def get
def all
return self unless @translator

(read_body || []).map do |hash|
body = read_body.is_a?(Hash) ? [read_body] : read_body

(body || []).map do |hash|
@translator.call(@klass, hash).tap do |instance|
instance.response = self
end
Expand Down
92 changes: 92 additions & 0 deletions spec/resto/format/xml_spec.rb
Expand Up @@ -10,4 +10,96 @@
its(:accept) { should == 'application/xml, */*' }
its(:content_type) { should == 'application/xml;charset=utf-8' }

let(:hash) do
{:zone =>
{ 'default-ttl' => 600,
'domain' => "example.com",
'ns1' => nil,
'ns-type' => "pri_sec",
'nx-ttl' => 900,
'slave-nameservers' => nil
}
}
end

describe ".encode(hash)" do
before { @result = subject.encode(hash) }

it { @result.should =~ /<\?xml version=\"1.0\"\?>/ }
it { @result.should =~ /<zone>.+<\/zone>\Z/m }
it { @result.should =~ /<default-ttl>600<\/default-ttl>/ }
it { @result.should =~ /<ns1\/>/ }
it { @result.should =~ /<slave-nameservers\/>/ }
end

let(:xml) do
'<?xml version="1.0"?><zone>
<default-ttl>600</default-ttl>
<domain>example.com</domain>
<ns1/>
<ns-type>pri_sec</ns-type>
<nx-ttl>900</nx-ttl>
<slave-nameservers/>
</zone>'
end

let(:xml_collection) do
'<?xml version="1.0"?>
<zones>
<zone>
<default-ttl>600</default-ttl>
<domain>example.com</domain>
<ns1/>
<ns-type>pri_sec</ns-type>
<nx-ttl>900</nx-ttl>
<slave-nameservers/>
</zone>
<zone>
<default-ttl>700</default-ttl>
<domain>example.com</domain>
<ns1/>
<ns-type>pri_sec</ns-type>
<nx-ttl>800</nx-ttl>
<slave-nameservers/>
</zone>
</zones>'
end

let(:attributes) do
{ 'default-ttl' => "600",
'domain' => "example.com",
'ns1' => "",
'ns-type' => "pri_sec",
'nx-ttl' => "900",
'slave-nameservers' => ""
}
end

let(:second_attributes) do
{ 'default-ttl' => "700",
'domain' => "example.com",
'ns1' => "",
'ns-type' => "pri_sec",
'nx-ttl' => "800",
'slave-nameservers' => ""
}
end

describe '.decode(xml, xpath)' do
context 'when one item' do
it { subject.decode(xml, :xpath => '//zone').should == attributes }
end

context 'when 0 items' do
it { subject.decode(xml, :xpath => '//xx0').should == {} }
end

context 'when a collection of two items' do
it do
subject.decode(xml_collection, :xpath => '//zone').should ==
[attributes, second_attributes]
end
end
end

end

0 comments on commit 80c9d5f

Please sign in to comment.