smacks-savon 0.0.91 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,11 +1,12 @@
1
1
  = Savon
2
2
 
3
- Savon is a lightweight SOAP client.
3
+ Ruby SOAP client library to enjoy.
4
4
 
5
- Instantiate Savon::Service and pass in the WSDL of the service you would
6
- like to use. Then just call the SOAP service method on your Savon::Service
7
- instance (catched via method_missing) and pass in a Hash of options for the
8
- service method to receive.
5
+ Communicating with a SOAP webservice can be done in two lines of code.
6
+ Instantiate a new Savon::Service passing in the URI to the WSDL of the
7
+ service you would like to use. Then call the SOAP service method on your
8
+ Savon::Service instance (catched via method_missing) and pass in a Hash
9
+ of options for the service method to receive.
9
10
 
10
11
  == Install
11
12
 
@@ -14,43 +15,66 @@ service method to receive.
14
15
  == Dependencies
15
16
 
16
17
  hpricot 0.6.164 (also available for JRuby)
17
- smacks-apricoteatsgorilla >= 0.3.5
18
+ smacks-apricoteatsgorilla >= 0.4.1
18
19
 
19
20
  == How to use
20
21
 
21
- === Usage example
22
+ Instantiate a new Savon::Service instance passing in the WSDL of your service.
22
23
 
23
24
  proxy = Savon::Service.new "http://example.com/ExampleService?wsdl"
25
+
26
+ Call the SOAP service method you would like to choose on your Savon::Service
27
+ instance passing in a Hash of options for the service method to receive.
28
+
24
29
  response = proxy.findExampleById(:id => 123)
25
30
 
26
31
  === Check for available SOAP service methods
27
32
 
33
+ You can use the service_methods method of the WSDL in your Savon::Service
34
+ instance to get a list of available SOAP service methods.
35
+
28
36
  proxy.wsdl.service_methods
29
37
  # => [ "findExampleById", "findExampleByName" ]
30
38
 
31
- === Checking for HTTP and SOAP faults
39
+ === Handle HTTP and SOAP errors
40
+
41
+ Check if the SOAP request was successful.
32
42
 
33
43
  response.success?
34
44
  response.fault?
35
45
 
36
- === Access the fault message and code
46
+ Access the fault message and code.
37
47
 
38
48
  response.fault
39
49
  response.fault_code
40
50
 
41
- === Working with different response formats
51
+ === Different response formats
42
52
 
43
- # raw XML response:
53
+ To work with the response of the service you need to convert the response
54
+ object using one of the following methods.
55
+
56
+ # SOAP response XML:
44
57
  response.to_s
45
58
 
46
59
  # response as a Hash
47
60
  response.to_hash
48
61
 
49
- # response as a Hash starting at a custom root node (via XPath)
50
- response.to_hash("//item")
51
-
52
62
  # response as a Mash
53
63
  response.to_mash
54
64
 
55
- # response as a Mash starting at a custom root node (via XPath)
56
- response.to_mash("//user/email")
65
+ The to_hash and to_mash methods accept an XPath expression (Hpricot search)
66
+ as second parameter to define a custom root node to start translating the
67
+ response XML at.
68
+
69
+ # response as a Hash starting at a custom root node
70
+ response.to_hash("//item")
71
+
72
+ # response as a Mash starting at a custom root node
73
+ response.to_mash("//user/email")
74
+
75
+ === Logging request and response
76
+
77
+ You should specify the logger to use before working with any services.
78
+
79
+ # example for Ruby on Rails
80
+ Savon::Service.logger = RAILS_DEFAULT_LOGGER
data/lib/savon/mash.rb CHANGED
@@ -3,8 +3,8 @@ module Savon
3
3
  # Savon::Mash converts a given Hash into an Object.
4
4
  class Mash
5
5
 
6
- # Loops through a given +hash+, stores each value in an instance variable
7
- # and creates getter and setter methods.
6
+ # Iterates through a given +hash+, stores each value in an instance
7
+ # variable and creates getter and setter methods.
8
8
  #
9
9
  # === Parameters
10
10
  #
@@ -19,9 +19,9 @@ module Savon
19
19
  end
20
20
  end
21
21
 
22
- set_instance_variable key, value
23
- define_reader key
24
- define_writer key
22
+ set_instance_variable(key, value)
23
+ define_reader(key)
24
+ define_writer(key)
25
25
  end
26
26
  end
27
27
 
@@ -5,42 +5,15 @@ require "apricoteatsgorilla"
5
5
  module Savon
6
6
 
7
7
  # Savon::Response represents the HTTP response.
8
- #
9
- # === Checking for HTTP and SOAP faults
10
- #
11
- # response.success?
12
- # response.fault?
13
- #
14
- # === Access the fault message and code
15
- #
16
- # response.fault
17
- # response.fault_code
18
- #
19
- # === Different response formats
20
- #
21
- # # raw XML response:
22
- # response.to_s
23
- #
24
- # # response as a Hash
25
- # response.to_hash
26
- #
27
- # # response as a Hash starting at a custom root node (via XPath)
28
- # response.to_hash("//item")
29
- #
30
- # # response as a Mash
31
- # response.to_mash
32
- #
33
- # # response as a Mash starting at a custom root node (via XPath)
34
- # response.to_mash("//user/email")
35
8
  class Response
36
9
 
37
- # The HTTP/SOAP fault.
10
+ # The HTTP or SOAP fault message.
38
11
  attr_reader :fault
39
12
 
40
- # The HTTP/SOAP fault code.
13
+ # The HTTP or SOAP fault code.
41
14
  attr_reader :fault_code
42
15
 
43
- # Initializer to set the SOAP response.
16
+ # Initializer expects the HTTP response and checks for HTTP or SOAP faults.
44
17
  #
45
18
  # === Parameters
46
19
  #
@@ -55,18 +28,18 @@ module Savon
55
28
  @fault_code.nil?
56
29
  end
57
30
 
58
- # Returns true if the request was not successful, false otherwise.
31
+ # Returns true if there was a HTTP or SOAP fault, false otherwise.
59
32
  def fault?
60
33
  !@fault_code.nil?
61
34
  end
62
35
 
63
36
  # Returns the SOAP response message as a Hash. Call with XPath expession
64
- # to define a custom +root_node+ to start parsing at. Defaults to "//return".
65
- # The root node itself will not be included in the Hash.
37
+ # (Hpricot search) to define a custom +root_node+ to start parsing at.
38
+ # Defaults to "//return". The root node will not be included in the Hash.
66
39
  #
67
40
  # === Parameters
68
41
  #
69
- # * +root_node+ - Optional. Custom root node to start parsing at. Defaults to "//return".
42
+ # * +root_node+ - Optional. Custom root node to start parsing at.
70
43
  def to_hash(root_node = "//return")
71
44
  return nil if fault?
72
45
  ApricotEatsGorilla[@response.body, root_node]
@@ -74,25 +47,25 @@ module Savon
74
47
 
75
48
  # Returns the SOAP response message as a Savon::Mash object. Call with
76
49
  # XPath expession to define a custom +root_node+. Defaults to "//return".
77
- # The root node itself will not be included in the Mash object.
50
+ # The root node will not be included in the Mash object.
78
51
  #
79
52
  # === Parameters
80
53
  #
81
- # * +root_node+ - Optional. Custom root node to start parsing at. Defaults to "//return".
54
+ # * +root_node+ - Optional. Custom root node to start parsing at.
82
55
  def to_mash(root_node = "//return")
83
56
  return nil if fault?
84
57
  hash = to_hash(root_node)
85
58
  Savon::Mash.new(hash)
86
59
  end
87
60
 
88
- # Returns the raw XML response.
61
+ # Returns the SOAP response XML.
89
62
  def to_s
90
63
  @response.body
91
64
  end
92
65
 
93
66
  private
94
67
 
95
- # Checks for and stores HTTP and SOAP fault errors.
68
+ # Checks for HTTP and SOAP faults.
96
69
  def validate
97
70
  if @response.code.to_i >= 300
98
71
  @fault, @fault_code = @response.message, @response.code
data/lib/savon/service.rb CHANGED
@@ -5,54 +5,28 @@ require "apricoteatsgorilla"
5
5
 
6
6
  module Savon
7
7
 
8
- # Savon is a lightweight SOAP client.
8
+ # Ruby SOAP client library to enjoy.
9
9
  #
10
- # Instantiate Savon::Service and pass in the WSDL of the service you would
11
- # like to use. Then just call the SOAP service method on your Savon::Service
12
- # instance (catched via method_missing) and pass in a Hash of options for the
13
- # service method to receive.
14
- #
15
- # === Usage example
16
- #
17
- # proxy = Savon::Service.new "http://example.com/ExampleService?wsdl"
18
- # response = proxy.findExampleById(:id => 123)
19
- #
20
- # === Check for available SOAP service methods
21
- #
22
- # proxy.wsdl.service_methods
23
- # # => [ "findExampleById", "findExampleByName" ]
24
- #
25
- # === Working with different response formats
26
- #
27
- # # raw XML response:
28
- # response.to_s
29
- #
30
- # # response as a Hash
31
- # response.to_hash
32
- #
33
- # # response as a Hash starting at a custom root node (via XPath)
34
- # response.to_hash("//item")
35
- #
36
- # # response as a Mash
37
- # response.to_mash
38
- #
39
- # # response as a Mash starting at a custom root node (via XPath)
40
- # response.to_mash("//user/email")
10
+ # Communicating with a SOAP webservice can be done in two lines of code.
11
+ # Instantiate a new Savon::Service passing in the URI to the WSDL of the
12
+ # service you would like to use. Then call the SOAP service method on your
13
+ # Savon::Service instance (catched via method_missing) and pass in a Hash
14
+ # of options for the service method to receive.
41
15
  class Service
42
16
 
43
17
  # The logger to use.
44
18
  @@logger = nil
45
19
 
46
- # The Net::HTTP connection instance to use.
47
- attr_writer :http
48
-
49
- # Initializer sets the WSDL +endpoint+ URI.
20
+ # Initializer expects the WSDL +endpoint+ URI to use and sets up
21
+ # Apricot eats Gorilla.
50
22
  #
51
23
  # ==== Parameters
52
24
  #
53
- # * +endpoint+ - The WSDL endpoint URI.
25
+ # * +endpoint+ - WSDL endpoint URI to use.
54
26
  def initialize(endpoint)
55
27
  @uri = URI(endpoint)
28
+ ApricotEatsGorilla.nodes_to_namespace = wsdl.choice_elements
29
+ ApricotEatsGorilla.node_namespace = "wsdl"
56
30
  end
57
31
 
58
32
  # Returns an instance of the WSDL.
@@ -61,6 +35,11 @@ module Savon
61
35
  @wsdl
62
36
  end
63
37
 
38
+ # Sets the Net::HTTP instance to use.
39
+ def http=(http)
40
+ @http = http
41
+ end
42
+
64
43
  # Sets the logger to use.
65
44
  def self.logger=(logger)
66
45
  @@logger = logger
@@ -68,20 +47,16 @@ module Savon
68
47
 
69
48
  private
70
49
 
71
- # Prepares and processes the SOAP request. Returns a Savon::Response object.
50
+ # Sets up and dispatches the SOAP request. Returns a Savon::Response object.
72
51
  def call_service
73
52
  headers = { "Content-Type" => "text/xml; charset=utf-8", "SOAPAction" => @action }
74
53
 
75
- ApricotEatsGorilla.setup do |s|
76
- s.nodes_to_namespace = wsdl.choice_elements
77
- s.node_namespace = "wsdl"
78
- end
79
54
  body = ApricotEatsGorilla.soap_envelope("wsdl" => wsdl.namespace_uri) do
80
55
  ApricotEatsGorilla["wsdl:#{@action}" => @options]
81
56
  end
82
57
 
83
58
  debug do |logger|
84
- logger.info "Request; #{@uri}"
59
+ logger.info "Requesting #{@uri}"
85
60
  logger.info headers.map { |key, value| "#{key}: #{value}" }.join("\n")
86
61
  logger.info body
87
62
  end
@@ -110,20 +85,19 @@ module Savon
110
85
  end
111
86
  end
112
87
 
113
- # Debug method. Outputs a given +message+ to the defined @@logger or
114
- # yields the @@logger to a +block+ in case one was given.
88
+ # Logs a given +message+ using the @@logger instance or yields the logger
89
+ # to a given +block+ for logging multiple things at once.
115
90
  def debug(message = nil)
116
91
  if @@logger
117
- if message
118
- @@logger.info(message)
119
- end
120
- if block_given?
121
- yield @@logger
122
- end
92
+ @@logger.info(message) if message
93
+ yield @@logger if block_given?
123
94
  end
124
95
  end
125
96
 
126
- # Intercepts calls to SOAP service methods.
97
+ # Method missing catches SOAP service methods called on this object. This
98
+ # is the default way of calling a SOAP service. The given +method+ will be
99
+ # validated against the WSDL and dispatched if available. Values supplied
100
+ # through the optional Hash of +options+ will be send to the service method.
127
101
  #
128
102
  # === Parameters
129
103
  #
data/lib/savon/wsdl.rb CHANGED
@@ -4,7 +4,7 @@ require "hpricot"
4
4
 
5
5
  module Savon
6
6
 
7
- # Savon::Wsdl gets, parses and represents the SOAP-WSDL.
7
+ # Savon::Wsdl gets, parses and represents the WSDL.
8
8
  class Wsdl
9
9
 
10
10
  # The namespace URI.
@@ -21,7 +21,7 @@ module Savon
21
21
  #
22
22
  # === Parameters
23
23
  #
24
- # * +uri+ - The URI to access.
24
+ # * +uri+ - The URI of the WSDL.
25
25
  # * +http+ - The Net::HTTP connection instance to use.
26
26
  def initialize(uri, http)
27
27
  @uri, @http = uri, http
@@ -49,15 +49,13 @@ module Savon
49
49
  end
50
50
  end
51
51
 
52
- # Parses the WSDL to find and store the namespace URI.
52
+ # Parses the WSDL for the namespace URI.
53
53
  def parse_namespace_uri
54
54
  node = @doc.at("//wsdl:definitions")
55
- if node
56
- @namespace_uri = node.get_attribute("targetNamespace")
57
- end
55
+ @namespace_uri = node.get_attribute("targetNamespace") if node
58
56
  end
59
57
 
60
- # Parses the WSDL to find and store the available SOAP service methods.
58
+ # Parses the WSDL for available SOAP service methods.
61
59
  def parse_service_methods
62
60
  @service_methods, node = [], @doc.search("//soap:operation")
63
61
  if node
@@ -67,7 +65,7 @@ module Savon
67
65
  end
68
66
  end
69
67
 
70
- # Parses the WSDL to find and store any choice elements.
68
+ # Parses the WSDL for choice elements.
71
69
  def parse_choice_elements
72
70
  @choice_elements, node = [], @doc.search("//xs:choice//xs:element")
73
71
  if node
@@ -1,26 +1,26 @@
1
1
  module SoapResponseFixture
2
2
 
3
3
  def some_soap_response
4
- '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
5
- <soap:Body>
6
- <ns2:result xmlns:ns2="http://example.com/">
7
- <return>
8
- <token>secret</token>
9
- </return>
10
- </ns2:result>
11
- </soap:Body>
12
- </soap:Envelope>'
4
+ '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' <<
5
+ '<soap:Body>' <<
6
+ '<ns2:result xmlns:ns2="http://example.com/">' <<
7
+ '<return>' <<
8
+ '<token>secret</token>' <<
9
+ '</return>' <<
10
+ '</ns2:result>' <<
11
+ '</soap:Body>' <<
12
+ '</soap:Envelope>'
13
13
  end
14
14
 
15
15
  def soap_fault_response
16
- '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
17
- <soap:Body>
18
- <soap:Fault>
19
- <faultcode>' << soap_fault_code << '</faultcode>
20
- <faultstring>' << soap_fault << '</faultstring>
21
- </soap:Fault>
22
- </soap:Body>
23
- </soap:Envelope>'
16
+ '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' <<
17
+ '<soap:Body>' <<
18
+ '<soap:Fault>' <<
19
+ '<faultcode>' << soap_fault_code << '</faultcode>' <<
20
+ '<faultstring>' << soap_fault << '</faultstring>' <<
21
+ '</soap:Fault>' <<
22
+ '</soap:Body>' <<
23
+ '</soap:Envelope>'
24
24
  end
25
25
 
26
26
  def soap_fault
data/test/helper.rb CHANGED
@@ -19,15 +19,15 @@ module TestHelper
19
19
  end
20
20
 
21
21
  def service_http_mock(response_body)
22
- http_mock = mock()
23
- http_mock.expects(:get).returns(response_mock(WsdlFactory.new.build))
24
- http_mock.expects(:request_post).returns(response_mock(response_body))
22
+ http_mock = mock("Net::HTTP")
23
+ http_mock.stubs(:get).returns(response_mock(WsdlFactory.new.build))
24
+ http_mock.stubs(:request_post).returns(response_mock(response_body))
25
25
  http_mock
26
26
  end
27
27
 
28
28
  def http_mock(response_body)
29
- http_mock = mock()
30
- http_mock.expects(:get).returns(response_mock(response_body))
29
+ http_mock = mock("Net::HTTP")
30
+ http_mock.stubs(:get).returns(response_mock(response_body))
31
31
  http_mock
32
32
  end
33
33
 
@@ -41,10 +41,7 @@ module TestHelper
41
41
 
42
42
  def build_response_mock(code, message, body = nil)
43
43
  response_mock = mock("Net::HTTPResponse")
44
- response_mock.stubs(
45
- :code => code, :message => message, :content_type => "text/html",
46
- :body => body
47
- )
44
+ response_mock.stubs(:code => code, :message => message, :body => body)
48
45
  response_mock
49
46
  end
50
47
 
@@ -2,8 +2,17 @@ require File.join(File.dirname(__FILE__), "..", "helper")
2
2
 
3
3
  class SavonMashTest < Test::Unit::TestCase
4
4
 
5
- def test_nupsi
6
- assert true
5
+ context "Creating a new Savon::Mash" do
6
+ context "with a simple Hash" do
7
+ should "return a Mash object matching the given Hash" do
8
+ hash = { :some => { :simple => "test" } }
9
+ mash = Savon::Mash.new(hash)
10
+
11
+ assert_respond_to(mash, :some)
12
+ assert_respond_to(mash, :simple)
13
+ assert_equal "test", mash.some.simple
14
+ end
15
+ end
7
16
  end
8
17
 
9
18
  end
@@ -7,6 +7,10 @@ class SavonServiceTest < Test::Unit::TestCase
7
7
 
8
8
  context "Savon::Service" do
9
9
  setup do
10
+ @some_factory = WsdlFactory.new
11
+ @some_wsdl = Savon::Wsdl.new(some_uri, http_mock(@some_factory.build))
12
+ Savon::Wsdl.stubs(:new).returns(@some_wsdl)
13
+
10
14
  @service = Savon::Service.new(some_url)
11
15
  @service.http = service_http_mock(some_soap_response)
12
16
  @result = @service.findById
data/test/savon_test.rb CHANGED
@@ -1,5 +1,5 @@
1
- $:.unshift(File.join(File.dirname(__FILE__), 'savon'))
1
+ $:.unshift(File.join(File.dirname(__FILE__), "savon"))
2
+ require "service_test"
3
+ require "response_test"
2
4
  require "mash_test"
3
5
  require "wsdl_test"
4
- require "response_test"
5
- require "service_test"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smacks-savon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.91
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Harrington
@@ -30,9 +30,9 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.3.8
33
+ version: 0.4.1
34
34
  version:
35
- description: Savon is a lightweight SOAP client.
35
+ description: Ruby SOAP client library to enjoy.
36
36
  email:
37
37
  executables: []
38
38
 
@@ -73,7 +73,7 @@ rubyforge_project:
73
73
  rubygems_version: 1.2.0
74
74
  signing_key:
75
75
  specification_version: 2
76
- summary: Savon is a lightweight SOAP client.
76
+ summary: Ruby SOAP client library to enjoy.
77
77
  test_files:
78
78
  - test/savon_test.rb
79
79
  - test/helper.rb