smacks-apricoteatsgorilla 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
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