smacks-apricoteatsgorilla 0.2.5 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -1,11 +1,8 @@
1
1
  = Apricot eats Gorilla
2
2
 
3
- Apricot eats Gorilla translates between XML documents and Hashes.
4
- It's based on CobraVsMongoose but uses Hpricot instead of REXML to parse
5
- XML and it also doesn't follow the BadgerFish convention.
6
-
7
- Its initial purpose was to convert SOAP response messages to Hashes,
8
- but it quickly evolved into a more general translation tool.
3
+ Apricot eats Gorilla is a helper for working with XML and SOAP messages.
4
+ It's based on CobraVsMongoose but without REXML and the BadgerFish convention.
5
+ Also it offers some extras for working with SOAP messages.
9
6
 
10
7
  == Install
11
8
 
@@ -68,4 +65,4 @@ And it gets converted into a nice little Hash:
68
65
 
69
66
  == More information
70
67
 
71
- Take a look at the tests for some more examples.
68
+ Take a look at the tests for some more examples.
@@ -2,22 +2,20 @@
2
2
  require 'rubygems'
3
3
  require 'hpricot'
4
4
 
5
- # Apricot eats Gorilla translates between XML documents and Hashes.
6
- # It's based on CobraVsMongoose but uses Hpricot instead of REXML to parse
7
- # XML and it also doesn't follow the BadgerFish convention.
8
- #
9
- # Its initial purpose was to convert SOAP response messages to Hashes,
10
- # but it quickly evolved into a more general translation tool.
5
+ # Apricot eats Gorilla is a helper for working with XML and SOAP messages.
6
+ # It's based on CobraVsMongoose but without REXML and the BadgerFish convention.
7
+ # Also it offers some extras for working with SOAP messages.
11
8
  class ApricotEatsGorilla
12
-
13
9
  class << self
10
+
11
+ # Flag to enable optional sorting of Hash keys. Especially useful for
12
+ # comparing expected values with actual results while testing.
14
13
  attr_accessor :sort_keys
15
14
 
16
15
  # Converts XML into a Hash. Starts parsing at root node by default.
17
16
  # Call with XPath expession (Hpricot search) as second parameter to define
18
17
  # a custom root node. The root node itself will not be included in the Hash.
19
18
  #
20
- # E.g.
21
19
  # xml = "<dude><likes>beer</likes><hates>appletini</hates></dude>"
22
20
  # ApricotEatsGorilla.xml_to_hash(xml)
23
21
  # # => { "hates" => "appletini", "likes" => "beer" }
@@ -29,8 +27,7 @@ class ApricotEatsGorilla
29
27
  end
30
28
 
31
29
  # Converts a Hash to XML.
32
- #
33
- # E.g.
30
+ #
34
31
  # hash = { "dude" => { "likes" => "beer", "hates" => "appletini" } }
35
32
  # ApricotEatsGorilla.hash_to_xml(hash)
36
33
  # # => "<dude><hates>appletini</hates><likes>beer</likes></dude>"
@@ -38,24 +35,52 @@ class ApricotEatsGorilla
38
35
  nested_data_to_xml(hash.keys.first, hash.values.first)
39
36
  end
40
37
 
38
+ # Builds a SOAP envelope and includes the content from an expected block
39
+ # into the envelope body. Pass in a Hash of namespaces and their URI to
40
+ # set custom namespaces.
41
+ #
42
+ # <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
43
+ # <env:Body>
44
+ # yield
45
+ # </env:Body>
46
+ # </env:Envelope>
47
+ def soap_envelope(namespaces = {})
48
+ namespaces["env"] = "http://schemas.xmlsoap.org/soap/envelope/"
49
+ tag("env:Envelope", namespaces) do
50
+ tag("env:Body") do
51
+ yield if block_given?
52
+ end
53
+ end
54
+ end
55
+
56
+ # Creates an XML tag. Expects a block for tag content.
57
+ # Defaults to an empty element tag in case no block was supplied.
58
+ def tag(name, attributes = {})
59
+ return "<#{name} />" unless block_given?
60
+
61
+ attr = opt_order(attributes).map { |k, v| sprintf(' xmlns:%s="%s"', k, v) }.to_s
62
+ body = (yield && !yield.empty?) ? yield : ""
63
+ "<#{name}#{attr}>" << body << "</#{name}>"
64
+ end
65
+
41
66
  private
42
67
 
43
68
  # Converts XML into a Hash.
44
69
  def xml_node_to_hash(node)
45
70
  this_node = {}
46
-
47
71
  node.each_child do |child|
72
+ # hpricot 0.6.1 returns an empty array, while 0.8 returns nil
48
73
  if child.children.nil? || child.children.empty?
49
74
  key, value = child.name, nil
50
75
  elsif child.children.size == 1 && child.children.first.text?
51
- key, value = child.name, string_to_bool?(child.children.first.inner_text)
76
+ key, value = child.name, booleanize(child.children.first.inner_text)
52
77
  else
53
78
  key, value = child.name, xml_node_to_hash(child)
54
79
  end
55
80
 
56
81
  current = this_node[key]
57
82
  case current
58
- when Array:
83
+ when Array
59
84
  this_node[key] << value
60
85
  when nil
61
86
  this_node[key] = value
@@ -63,7 +88,6 @@ class ApricotEatsGorilla
63
88
  this_node[key] = [current.dup, value]
64
89
  end
65
90
  end
66
-
67
91
  this_node
68
92
  end
69
93
 
@@ -71,15 +95,15 @@ class ApricotEatsGorilla
71
95
  def nested_data_to_xml(name, item)
72
96
  case item
73
97
  when String
74
- make_tag(name) { item }
98
+ tag(name) { item }
75
99
  when Array
76
100
  item.map { |subitem| nested_data_to_xml(name, subitem) }.join
77
101
  when Hash
78
- make_tag(name) do
102
+ tag(name) do
79
103
  opt_order(item).map { |tag, value|
80
104
  case value
81
105
  when String
82
- make_tag(tag) { value }
106
+ tag(tag) { value }
83
107
  when Array
84
108
  value.map { |subitem| nested_data_to_xml(tag, subitem) }.join
85
109
  when Hash
@@ -90,17 +114,7 @@ class ApricotEatsGorilla
90
114
  end
91
115
  end
92
116
 
93
- # Helper to create an XML tag. Expects a block for tag content.
94
- # Defaults to an empty element tag in case no block was supplied.
95
- def make_tag(name)
96
- body = yield
97
- if body && !body.empty?
98
- "<#{name}>" << body << "</#{name}>"
99
- else
100
- "<#{name} />"
101
- end
102
- end
103
-
117
+ # Returns a sorted version of a given Hash in case :sort_keys is enabled.
104
118
  def opt_order(hash)
105
119
  if sort_keys
106
120
  hash.sort_by{ |kv| kv.first }
@@ -117,7 +131,7 @@ class ApricotEatsGorilla
117
131
 
118
132
  # Helper to convert "true" and "false" strings to boolean values.
119
133
  # Returns the original string in case it doesn't match "true" or "false".
120
- def string_to_bool?(string)
134
+ def booleanize(string)
121
135
  return true if string == "true"
122
136
  return false if string == "false"
123
137
  string
@@ -0,0 +1,125 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'test/unit'
3
+ require File.join(File.dirname(__FILE__), "..", "lib", "apricoteatsgorilla")
4
+
5
+ class ApricotEatsGorillaTest < Test::Unit::TestCase
6
+
7
+ def setup
8
+ ApricotEatsGorilla.sort_keys = true
9
+ end
10
+
11
+ # xml_to_hash
12
+ def test_xml_to_hash_with_soap_response_example
13
+ xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
14
+ <soap:Body>
15
+ <ns2:authenticateResponse xmlns:ns2="http://v1_0.ws.example.com/">
16
+ <return>
17
+ <authValue>
18
+ <token>secret</token>
19
+ <client>example</client>
20
+ </authValue>
21
+ </return>
22
+ </ns2:authenticateResponse>
23
+ </soap:Body>
24
+ </soap:Envelope>'
25
+ expected = { 'authValue' => { 'token' => 'secret', 'client' => 'example' } }
26
+
27
+ result = ApricotEatsGorilla.xml_to_hash(xml, '//return')
28
+ assert_equal expected, result
29
+ end
30
+
31
+ def test_xml_to_hash_make_sure_boolean_values_get_converted_to_boolean_objects
32
+ xml = '<root><yes>true</yes><no>false</no><txt>something</txt></root>'
33
+ expected = { 'yes' => true, 'no' => false, 'txt' => 'something' }
34
+
35
+ result = ApricotEatsGorilla.xml_to_hash(xml)
36
+ assert_equal expected, result
37
+ end
38
+
39
+ def test_xml_to_hash_make_sure_empty_element_tags_get_converted_to_nil
40
+ xml = '<contact><name>Jungle Julia</name><email /><phone/></contact>'
41
+ expected = { 'name' => 'Jungle Julia', 'email' => nil, 'phone' => nil }
42
+
43
+ result = ApricotEatsGorilla.xml_to_hash(xml)
44
+ assert_equal expected, result
45
+ end
46
+
47
+ def test_xml_to_hash_make_sure_node_attributes_get_removed
48
+ xml = '<todo><paint subject="chair" color="#000000">black</paint></todo>'
49
+ expected = { 'paint' => 'black' }
50
+
51
+ result = ApricotEatsGorilla.xml_to_hash(xml)
52
+ assert_equal expected, result
53
+ end
54
+
55
+ def test_xml_to_hash_make_sure_node_groups_with_text_values_get_converted_to_arrays
56
+ xml = '<root><items>first</items><items>second</items></root>'
57
+ expected = { 'items' => [ 'first', 'second' ] }
58
+
59
+ result = ApricotEatsGorilla.xml_to_hash(xml)
60
+ assert_equal expected, result
61
+ end
62
+
63
+ def test_xml_to_hash_make_sure_node_groups_with_nesting_get_converted_to_arrays_with_hashes
64
+ xml = '<root><items><name>first</name></items><items><name>second</name></items></root>'
65
+ expected = { 'items' => [ { 'name' => 'first' }, { 'name' => 'second' } ] }
66
+
67
+ result = ApricotEatsGorilla.xml_to_hash(xml)
68
+ assert_equal expected, result
69
+ end
70
+
71
+ # hash_to_xml
72
+ def test_hash_to_xml_with_simple_hash
73
+ hash = { "dude" => "likes beer" }
74
+ expected = "<dude>likes beer</dude>"
75
+
76
+ result = ApricotEatsGorilla.hash_to_xml(hash)
77
+ assert_equal expected, result
78
+ end
79
+
80
+ def test_hash_to_xml_with_nested_hash
81
+ hash = { "dude" => { "likes" => "beer", "hates" => "appletini" } }
82
+ expected = "<dude><hates>appletini</hates><likes>beer</likes></dude>"
83
+
84
+ result = ApricotEatsGorilla.hash_to_xml(hash)
85
+ assert_equal expected, result
86
+ end
87
+
88
+ def test_hash_to_xml_with_nested_hash_and_array
89
+ hash = { "dude" => { "likes" => [ "beer", "helicopters" ] } }
90
+ expected = "<dude><likes>beer</likes><likes>helicopters</likes></dude>"
91
+
92
+ result = ApricotEatsGorilla.hash_to_xml(hash)
93
+ assert_equal expected, result
94
+ end
95
+
96
+ def test_hash_to_xml_with_nested_hash_and_array_containing_a_hash
97
+ hash = { "dude" => { "likes" => [ { "beer" => "a lot" }, { "helicopters" => "a little more" } ] } }
98
+ expected = "<dude><likes><beer>a lot</beer></likes><likes><helicopters>a little more</helicopters></likes></dude>"
99
+
100
+ result = ApricotEatsGorilla.hash_to_xml(hash)
101
+ assert_equal expected, result
102
+ end
103
+
104
+ # soap_envelope
105
+ def test_soap_envelope_without_namespace_and_block_returns_pure_envelope
106
+ expected = '<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">' <<
107
+ '<env:Body></env:Body></env:Envelope>'
108
+
109
+ result = ApricotEatsGorilla.soap_envelope
110
+ assert_equal expected, result
111
+ end
112
+
113
+ def test_soap_envelope_with_namespace_and_block_returns_envelope_with_namespace_and_content
114
+ expected = '<env:Envelope ' <<
115
+ 'xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" ' <<
116
+ 'xmlns:wsdl="http://example.com">' <<
117
+ '<env:Body><id>123</id></env:Body></env:Envelope>'
118
+
119
+ result = ApricotEatsGorilla.soap_envelope("wsdl" => "http://example.com") do
120
+ "<id>123</id>"
121
+ end
122
+ assert_equal expected, result
123
+ end
124
+
125
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smacks-apricoteatsgorilla
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Harrington
@@ -22,7 +22,7 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: 0.6.164
24
24
  version:
25
- description: Apricot eats Gorilla translates between XML documents and Hashes.
25
+ description: Apricot eats Gorilla is a helper for working with XML and SOAP messages.
26
26
  email:
27
27
  executables: []
28
28
 
@@ -59,8 +59,6 @@ rubyforge_project:
59
59
  rubygems_version: 1.2.0
60
60
  signing_key:
61
61
  specification_version: 2
62
- summary: Apricot eats Gorilla translates between XML documents and Hashes.
62
+ summary: Apricot eats Gorilla is a helper for working with XML and SOAP messages.
63
63
  test_files:
64
- - tests/apricot_eats_gorilla_testsuite.rb
65
- - tests/hash_to_xml_test.rb
66
- - tests/xml_to_hash_test.rb
64
+ - tests/apricoteatsgorilla_test.rb
@@ -1,3 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require File.join(File.dirname(__FILE__), "hash_to_xml_test")
3
- require File.join(File.dirname(__FILE__), "xml_to_hash_test")
@@ -1,43 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'test/unit'
3
- require File.join(File.dirname(__FILE__), "..", "lib", "apricoteatsgorilla")
4
-
5
- class HashToXmlTest < Test::Unit::TestCase
6
-
7
- def setup
8
- ApricotEatsGorilla.sort_keys = true
9
- end
10
-
11
- def test_dead_simple
12
- hash = { "dude" => "likes beer" }
13
- expected = "<dude>likes beer</dude>"
14
-
15
- result = ApricotEatsGorilla.hash_to_xml(hash)
16
- assert_equal expected, result
17
- end
18
-
19
- def test_nested_hash
20
- hash = { "dude" => { "likes" => "beer", "hates" => "appletini" } }
21
- expected = "<dude><hates>appletini</hates><likes>beer</likes></dude>"
22
-
23
- result = ApricotEatsGorilla.hash_to_xml(hash)
24
- assert_equal expected, result
25
- end
26
-
27
- def test_nested_hash_with_array
28
- hash = { "dude" => { "likes" => [ "beer", "helicopters" ] } }
29
- expected = "<dude><likes>beer</likes><likes>helicopters</likes></dude>"
30
-
31
- result = ApricotEatsGorilla.hash_to_xml(hash)
32
- assert_equal expected, result
33
- end
34
-
35
- def test_nested_hash_with_array_containing_a_hash
36
- hash = { "dude" => { "likes" => [ { "beer" => "a lot" }, { "helicopters" => "a little more" } ] } }
37
- expected = "<dude><likes><beer>a lot</beer></likes><likes><helicopters>a little more</helicopters></likes></dude>"
38
-
39
- result = ApricotEatsGorilla.hash_to_xml(hash)
40
- assert_equal expected, result
41
- end
42
-
43
- end
@@ -1,66 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- require 'test/unit'
3
- require File.join(File.dirname(__FILE__), "..", "lib", "apricoteatsgorilla")
4
-
5
- class XmlToHashTest < Test::Unit::TestCase
6
-
7
- def test_soap_response_example
8
- xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
9
- <soap:Body>
10
- <ns2:authenticateResponse xmlns:ns2="http://v1_0.ws.example.com/">
11
- <return>
12
- <authValue>
13
- <token>secret</token>
14
- <client>example</client>
15
- </authValue>
16
- </return>
17
- </ns2:authenticateResponse>
18
- </soap:Body>
19
- </soap:Envelope>'
20
- expected = { 'authValue' => { 'token' => 'secret', 'client' => 'example' } }
21
-
22
- result = ApricotEatsGorilla.xml_to_hash(xml, '//return')
23
- assert_equal expected, result
24
- end
25
-
26
- def test_that_boolean_string_values_are_converted_to_actual_boolean_objects
27
- xml = '<root><yes>true</yes><no>false</no><txt>something</txt></root>'
28
- expected = { 'yes' => true, 'no' => false, 'txt' => 'something' }
29
-
30
- result = ApricotEatsGorilla.xml_to_hash(xml)
31
- assert_equal expected, result
32
- end
33
-
34
- def test_that_empty_element_tags_are_converted_to_nil
35
- xml = '<contact><name>Jungle Julia</name><email /><phone/></contact>'
36
- expected = { 'name' => 'Jungle Julia', 'email' => nil, 'phone' => nil }
37
-
38
- result = ApricotEatsGorilla.xml_to_hash(xml)
39
- assert_equal expected, result
40
- end
41
-
42
- def test_that_attributes_get_removed
43
- xml = '<todo><paint subject="chair" color="#000000">black</paint></todo>'
44
- expected = { 'paint' => 'black' }
45
-
46
- result = ApricotEatsGorilla.xml_to_hash(xml)
47
- assert_equal expected, result
48
- end
49
-
50
- def test_that_node_groups_with_text_values_get_converted_to_arrays
51
- xml = '<root><items>first</items><items>second</items></root>'
52
- expected = { 'items' => [ 'first', 'second' ] }
53
-
54
- result = ApricotEatsGorilla.xml_to_hash(xml)
55
- assert_equal expected, result
56
- end
57
-
58
- def test_that_node_groups_with_nesting_get_converted_to_arrays_with_hashes
59
- xml = '<root><items><name>first</name></items><items><name>second</name></items></root>'
60
- expected = { 'items' => [ { 'name' => 'first' }, { 'name' => 'second' } ] }
61
-
62
- result = ApricotEatsGorilla.xml_to_hash(xml)
63
- assert_equal expected, result
64
- end
65
-
66
- end