julianmorrison-savon 0.6.8
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +92 -0
- data/README.textile +71 -0
- data/Rakefile +27 -0
- data/lib/savon.rb +34 -0
- data/lib/savon/client.rb +84 -0
- data/lib/savon/core_ext.rb +3 -0
- data/lib/savon/core_ext/datetime.rb +8 -0
- data/lib/savon/core_ext/hash.rb +78 -0
- data/lib/savon/core_ext/object.rb +21 -0
- data/lib/savon/core_ext/string.rb +47 -0
- data/lib/savon/core_ext/symbol.rb +8 -0
- data/lib/savon/core_ext/uri.rb +10 -0
- data/lib/savon/request.rb +159 -0
- data/lib/savon/response.rb +108 -0
- data/lib/savon/soap.rb +138 -0
- data/lib/savon/wsdl.rb +122 -0
- data/lib/savon/wsse.rb +122 -0
- data/spec/endpoint_helper.rb +22 -0
- data/spec/fixtures/response/response_fixture.rb +32 -0
- data/spec/fixtures/response/xml/authentication.xml +14 -0
- data/spec/fixtures/response/xml/soap_fault.xml +8 -0
- data/spec/fixtures/response/xml/soap_fault12.xml +18 -0
- data/spec/fixtures/wsdl/wsdl_fixture.rb +37 -0
- data/spec/fixtures/wsdl/xml/authentication.xml +63 -0
- data/spec/fixtures/wsdl/xml/namespaced_actions.xml +307 -0
- data/spec/fixtures/wsdl/xml/no_namespace.xml +115 -0
- data/spec/http_stubs.rb +23 -0
- data/spec/savon/client_spec.rb +83 -0
- data/spec/savon/core_ext/datetime_spec.rb +12 -0
- data/spec/savon/core_ext/hash_spec.rb +134 -0
- data/spec/savon/core_ext/object_spec.rb +40 -0
- data/spec/savon/core_ext/string_spec.rb +68 -0
- data/spec/savon/core_ext/symbol_spec.rb +11 -0
- data/spec/savon/core_ext/uri_spec.rb +15 -0
- data/spec/savon/request_spec.rb +124 -0
- data/spec/savon/response_spec.rb +122 -0
- data/spec/savon/savon_spec.rb +23 -0
- data/spec/savon/soap_spec.rb +131 -0
- data/spec/savon/wsdl_spec.rb +84 -0
- data/spec/savon/wsse_spec.rb +132 -0
- data/spec/spec_helper.rb +16 -0
- metadata +166 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
== UPCOMING
|
2
|
+
* Changed the way you can disable Savon::WSDL. More information at: http://wiki.github.com/rubiii/savon/wsdl
|
3
|
+
Instead of disabling the WSDL globally/per request via two different methods, you now simply append an
|
4
|
+
exclamation mark (!) to your SOAP call. For example: client.get_all_users!
|
5
|
+
The Wiki page will be updated to relect this change as soon as it's released.
|
6
|
+
* Setting the "xmlns:wsdl" can be done by using the soap#namespaces method which returns a Hash of namespaces.
|
7
|
+
For example: soap.namespaces["xmlns:wsdl"] = "http://example.com"
|
8
|
+
I added soap#namespace as a convenience method to simplify setting the "xmlns:wsdl" namespace.
|
9
|
+
For example: soap.namespace = "http://example.com"
|
10
|
+
|
11
|
+
== 0.6.8 (2010-01-01)
|
12
|
+
* Improved specifications for various kinds of WSDL documents.
|
13
|
+
* Added support for SOAP endpoints which are different than the WSDL endpoint of a service.
|
14
|
+
* Changed how SOAP actions and inputs are retrieved from the WSDL documents. This might break a few existing
|
15
|
+
implementations, but makes Savon work well with even more services. If this change breaks your implementation,
|
16
|
+
please take a look at the +action+ and +input+ methods of the Savon::SOAP object.
|
17
|
+
One specific problem I know of is working with the createsend WSDL and its namespaced actions.
|
18
|
+
To make it work, call the SOAP action without namespace and specify the input manually:
|
19
|
+
client.get_api_key { |soap| soap.input = "User.GetApiKey" }
|
20
|
+
|
21
|
+
== 0.6.7 (2009-12-18)
|
22
|
+
* Implemented support for a proxy server. The proxy URI can be set through an optional Hash of options passed
|
23
|
+
to instantiating Savon::Client (Dave Woodward <dave@futuremint.com>)
|
24
|
+
* Implemented support for SSL client authentication. Settings can be set through an optional Hash of arguments
|
25
|
+
passed to instantiating Savon::Client (colonhyphenp)
|
26
|
+
* Patch for issue #10 (Problem with operation tags without a namespace).
|
27
|
+
|
28
|
+
== 0.6.6 (2009-12-14)
|
29
|
+
* Default to use the name of the SOAP action (the method called in a client) in lowerCamelCase for SOAP action
|
30
|
+
and input when Savon::WSDL is disabled. You still need to specify soap.action and maybe soap.input in case
|
31
|
+
your SOAP actions are named any different.
|
32
|
+
|
33
|
+
== 0.6.5 (2009-12-13)
|
34
|
+
* Added an open_timeout method to Savon::Request.
|
35
|
+
|
36
|
+
== 0.6.4 (2009-12-13)
|
37
|
+
* Refactored specs to be less unit-like.
|
38
|
+
* Added a getter for the Savon::Request to Savon::Client and a read_timeout setter for HTTP requests.
|
39
|
+
* wsdl.soap_actions now returns an Array of SOAP actions. For the previous "mapping" please use wsdl.operations.
|
40
|
+
* Replaced WSDL document with stream parsing.
|
41
|
+
|
42
|
+
Benchmarks (1000 SOAP calls):
|
43
|
+
|
44
|
+
user system total real
|
45
|
+
0.6.4 72.180000 8.280000 80.460000 (750.799011)
|
46
|
+
0.6.3 192.900000 19.630000 212.530000 (914.031865)
|
47
|
+
|
48
|
+
== 0.6.3 (2009-12-11)
|
49
|
+
* Removing 2 ruby deprecation warnings for parenthesized arguments. (Dave Woodward <dave@futuremint.com>)
|
50
|
+
* Added global and per request options for disabling Savon::WSDL.
|
51
|
+
|
52
|
+
Benchmarks (1000 SOAP calls):
|
53
|
+
|
54
|
+
user system total real
|
55
|
+
WSDL 192.900000 19.630000 212.530000 (914.031865)
|
56
|
+
disabled WSDL 5.680000 1.340000 7.020000 (298.265318)
|
57
|
+
|
58
|
+
* Improved XPath expressions for parsing the WSDL document.
|
59
|
+
|
60
|
+
Benchmarks (1000 SOAP calls):
|
61
|
+
|
62
|
+
user system total real
|
63
|
+
0.6.3 192.900000 19.630000 212.530000 (914.031865)
|
64
|
+
0.6.2 574.720000 78.380000 653.100000 (1387.778539)
|
65
|
+
|
66
|
+
== 0.6.2 (2009-12-06)
|
67
|
+
* Added support for changing the name of the SOAP input node.
|
68
|
+
* Added a CHANGELOG.
|
69
|
+
|
70
|
+
== 0.6.1 (2009-12-06)
|
71
|
+
* Fixed a problem with WSSE credentials, where every request contained a WSSE authentication header.
|
72
|
+
|
73
|
+
== 0.6.0 (2009-12-06)
|
74
|
+
* method_missing now yields the SOAP and WSSE objects to a given block.
|
75
|
+
* The response_process (which previously was a block passed to method_missing) was replaced by Savon::Response.
|
76
|
+
* Improved SOAP action handling (another problem that came up with issue #1).
|
77
|
+
|
78
|
+
== 0.5.3 (2009-11-30)
|
79
|
+
* Patch for issue #2 (NoMethodError: undefined method `invalid!' for Savon::WSDL)
|
80
|
+
|
81
|
+
== 0.5.2 (2009-11-30)
|
82
|
+
* Patch for issue #1 (Calls fail if api methods have periods in them)
|
83
|
+
|
84
|
+
== 0.5.1 (2009-11-29)
|
85
|
+
* Optimized default response process.
|
86
|
+
* Added WSSE settings via defaults.
|
87
|
+
* Added SOAP fault and HTTP error handling.
|
88
|
+
* Improved documentation
|
89
|
+
* Added specs
|
90
|
+
|
91
|
+
== 0.5.0 (2009-11-29)
|
92
|
+
* Complete rewrite.
|
data/README.textile
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
h1. Savon
|
2
|
+
|
3
|
+
h4. Heavy metal Ruby SOAP client library
|
4
|
+
|
5
|
+
p. "RDoc":http://rdoc.info/projects/rubiii/savon | "Wiki":http://wiki.github.com/rubiii/savon | "ToDo":http://rubiii.tadalist.com/lists/1459816/public | "Metrics":http://getcaliper.com/caliper/project?repo=git://github.com/rubiii/savon.git
|
6
|
+
|
7
|
+
h2. Installation
|
8
|
+
|
9
|
+
bc. $ gem install savon
|
10
|
+
|
11
|
+
p. Savon expects you to be familiar with SOAP, WSDL and tools like soapUI.
|
12
|
+
|
13
|
+
h2. Instantiate a client
|
14
|
+
|
15
|
+
p. Instantiate Savon::Client, passing in the WSDL of your service.
|
16
|
+
|
17
|
+
bc. client = Savon::Client.new "http://example.com/UserService?wsdl"
|
18
|
+
|
19
|
+
p. More information: "Client":http://wiki.github.com/rubiii/savon/client
|
20
|
+
|
21
|
+
h2. Calling a SOAP action
|
22
|
+
|
23
|
+
p. Assuming your service applies to the "Defaults":http://wiki.github.com/rubiii/savon/defaults, you can now call any available SOAP action.
|
24
|
+
|
25
|
+
bc. response = client.get_all_users
|
26
|
+
|
27
|
+
p. Savon lets you call SOAP actions using snake_case, because even though they will propably be written in lowerCamelCase or CamelCase, it just feels much more natural.
|
28
|
+
|
29
|
+
h2. The WSDL object
|
30
|
+
|
31
|
+
p. Savon::WSDL represents the WSDL of your service, including information like the namespace URI and available SOAP actions.
|
32
|
+
|
33
|
+
bc. client.wsdl.soap_actions
|
34
|
+
=> [:get_all_users, :get_user_by_id, :user_magic]
|
35
|
+
|
36
|
+
p. More information: "WSDL":http://wiki.github.com/rubiii/savon/wsdl
|
37
|
+
|
38
|
+
h2. The SOAP object
|
39
|
+
|
40
|
+
p. Savon::SOAP represents the SOAP request. Pass a block to your SOAP call and the SOAP object is passed to it as the first argument. The object allows setting the SOAP version, header, body and namespaces per request.
|
41
|
+
|
42
|
+
bc. response = client.get_user_by_id { |soap| soap.body = { :id => 666 } }
|
43
|
+
|
44
|
+
p. More information: "SOAP":http://wiki.github.com/rubiii/savon/soap
|
45
|
+
|
46
|
+
h2. The WSSE object
|
47
|
+
|
48
|
+
p. Savon::WSSE represents WSSE authentication. Pass a block to your SOAP call and the WSSE object is passed to it as the second argument. The object allows setting the WSSE username, password and whether to use digest authentication.
|
49
|
+
|
50
|
+
bc. response = client.get_user_by_id do |soap, wsse|
|
51
|
+
wsse.username = "gorilla"
|
52
|
+
wsse.password = "secret"
|
53
|
+
soap.body = { :id => 666 }
|
54
|
+
end
|
55
|
+
|
56
|
+
p. More information: "WSSE":http://wiki.github.com/rubiii/savon/wsse
|
57
|
+
|
58
|
+
h2. The Response object
|
59
|
+
|
60
|
+
p. Savon::Response represents the HTTP and SOAP response. It contains and raises errors in case of an HTTP error or SOAP fault (unless disabled). Also you can get the response as XML (for parsing it with an XML library) or translated into a Hash.
|
61
|
+
More information: "Response":http://wiki.github.com/rubiii/savon/response
|
62
|
+
|
63
|
+
h2. HTTP errors and SOAP faults
|
64
|
+
|
65
|
+
p. Savon raises a Savon::SOAPFault in case of a SOAP fault and a Savon::HTTPError in case of an HTTP error.
|
66
|
+
More information: "Errors":http://wiki.github.com/rubiii/savon/errors
|
67
|
+
|
68
|
+
h2. Logging
|
69
|
+
|
70
|
+
p. Savon logs each request and response to STDOUT. But there are a couple of options to change the default behaviour.
|
71
|
+
More information: "Logging":http://wiki.github.com/rubiii/savon/logging
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
require "spec/rake/spectask"
|
4
|
+
require "spec/rake/verify_rcov"
|
5
|
+
require "rake/rdoctask"
|
6
|
+
|
7
|
+
task :default => :spec_verify_rcov
|
8
|
+
|
9
|
+
Spec::Rake::SpecTask.new do |spec|
|
10
|
+
spec.spec_files = FileList["spec/**/*_spec.rb"]
|
11
|
+
spec.spec_opts << "--color"
|
12
|
+
spec.libs += ["lib", "spec"]
|
13
|
+
spec.rcov = true
|
14
|
+
spec.rcov_dir = "rcov"
|
15
|
+
end
|
16
|
+
|
17
|
+
RCov::VerifyTask.new(:spec_verify_rcov => :spec) do |verify|
|
18
|
+
verify.threshold = 100.0
|
19
|
+
verify.index_html = "rcov/index.html"
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::RDocTask.new do |rdoc|
|
23
|
+
rdoc.title = "Savon"
|
24
|
+
rdoc.rdoc_dir = "rdoc"
|
25
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
26
|
+
rdoc.options = ["--line-numbers", "--inline-source"]
|
27
|
+
end
|
data/lib/savon.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Savon
|
2
|
+
|
3
|
+
# Supported SOAP versions.
|
4
|
+
SOAPVersions = [1, 2]
|
5
|
+
|
6
|
+
# SOAP xs:dateTime format.
|
7
|
+
SOAPDateTimeFormat = "%Y-%m-%dT%H:%M:%S"
|
8
|
+
|
9
|
+
# SOAP xs:dateTime Regexp.
|
10
|
+
SOAPDateTimeRegexp = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
|
11
|
+
|
12
|
+
# Raised in case of an HTTP error.
|
13
|
+
class HTTPError < StandardError; end
|
14
|
+
|
15
|
+
# Raised in case of a SOAP fault.
|
16
|
+
class SOAPFault < StandardError; end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
# standard libs
|
21
|
+
%w(logger net/http net/https openssl uri base64 digest/sha1 rexml/document).each do |lib|
|
22
|
+
require lib
|
23
|
+
end
|
24
|
+
|
25
|
+
# gems
|
26
|
+
require "rubygems"
|
27
|
+
%w(builder crack/xml).each do |gem|
|
28
|
+
require gem
|
29
|
+
end
|
30
|
+
|
31
|
+
# core files
|
32
|
+
%w(core_ext wsse soap request response wsdl client).each do |file|
|
33
|
+
require File.dirname(__FILE__) + "/savon/#{file}"
|
34
|
+
end
|
data/lib/savon/client.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
module Savon
|
2
|
+
|
3
|
+
# == Savon::Client
|
4
|
+
#
|
5
|
+
# Heavy metal Ruby SOAP client library. Minimizes the overhead of working
|
6
|
+
# with SOAP services and XML.
|
7
|
+
class Client
|
8
|
+
|
9
|
+
# Expects a SOAP +endpoint+ String. Also accepts an optional Hash of
|
10
|
+
# +options+ for specifying a proxy server and SSL client authentication.
|
11
|
+
def initialize(endpoint, options = {})
|
12
|
+
@request = Request.new endpoint, options
|
13
|
+
@wsdl = WSDL.new @request
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the Savon::WSDL.
|
17
|
+
attr_reader :wsdl
|
18
|
+
|
19
|
+
# Returns the Savon::Request.
|
20
|
+
attr_reader :request
|
21
|
+
|
22
|
+
# Returns +true+ for available methods and SOAP actions.
|
23
|
+
def respond_to?(method)
|
24
|
+
return true if @wsdl.respond_to? method
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
# Dispatches requests to SOAP actions matching a given +method+ name.
|
31
|
+
def method_missing(method, *args, &block) #:doc:
|
32
|
+
soap_call = soap_call_from method.to_s
|
33
|
+
super if @wsdl.enabled? && !@wsdl.respond_to?(soap_call)
|
34
|
+
|
35
|
+
setup_objects operation_from(soap_call), &block
|
36
|
+
Response.new @request.soap(@soap)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Sets whether to use Savon::WSDL by a given +method+ name and
|
40
|
+
# removes exclamation marks from the given +method+ name.
|
41
|
+
def soap_call_from(method)
|
42
|
+
if method[-1, 1] == "!"
|
43
|
+
@wsdl.enabled = false
|
44
|
+
method[0, method.length-1].to_sym
|
45
|
+
else
|
46
|
+
@wsdl.enabled = true
|
47
|
+
method.to_sym
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns a SOAP operation Hash containing the SOAP action and input
|
52
|
+
# for a given +soap_call+.
|
53
|
+
def operation_from(soap_call)
|
54
|
+
return @wsdl.operations[soap_call] if @wsdl.enabled?
|
55
|
+
{ :action => soap_call.to_soap_key, :input => soap_call.to_soap_key }
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns the SOAP endpoint.
|
59
|
+
def soap_endpoint
|
60
|
+
@wsdl.enabled? ? @wsdl.soap_endpoint : @request.endpoint
|
61
|
+
end
|
62
|
+
|
63
|
+
# Expects a SOAP operation Hash and sets up Savon::SOAP and Savon::WSSE.
|
64
|
+
# Yields them to a given +block+ in case one was given.
|
65
|
+
def setup_objects(operation, &block)
|
66
|
+
@soap, @wsse = SOAP.new, WSSE.new
|
67
|
+
@soap.action, @soap.input, @soap.endpoint = operation[:action], operation[:input], soap_endpoint
|
68
|
+
|
69
|
+
yield_objects &block if block
|
70
|
+
|
71
|
+
@soap.namespaces["xmlns:wsdl"] ||= @wsdl.namespace_uri if @wsdl.enabled?
|
72
|
+
@soap.wsse = @wsse
|
73
|
+
end
|
74
|
+
|
75
|
+
# Yields Savon::SOAP and Savon::WSSE to a given +block+.
|
76
|
+
def yield_objects(&block)
|
77
|
+
case block.arity
|
78
|
+
when 1 then yield @soap
|
79
|
+
when 2 then yield @soap, @wsse
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class Hash
|
2
|
+
|
3
|
+
# Expects an Array of Regexp Objects of which every Regexp recursively
|
4
|
+
# matches a key to be accessed. Returns the value of the last Regexp filter
|
5
|
+
# found in the Hash or an empty Hash in case the path of Regexp filters
|
6
|
+
# did not match the Hash structure.
|
7
|
+
def find_regexp(regexp)
|
8
|
+
regexp = [regexp] unless regexp.kind_of? Array
|
9
|
+
result = dup
|
10
|
+
|
11
|
+
regexp.each do |pattern|
|
12
|
+
result_key = result.keys.find { |key| key.to_s.match pattern }
|
13
|
+
result = result[result_key] ? result[result_key] : {}
|
14
|
+
end
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the Hash translated into SOAP request compatible XML.
|
19
|
+
#
|
20
|
+
# To control the order of output, add a key of :@inorder with
|
21
|
+
# the value being an array listing the other keys in order.
|
22
|
+
#
|
23
|
+
# === Example
|
24
|
+
#
|
25
|
+
# { :find_user => { :id => 666 } }.to_soap_xml
|
26
|
+
# => "<findUser><id>666</id></findUser>"
|
27
|
+
#
|
28
|
+
# { :find_user => { :name => 'Lucy', :id => 666, :@inorder => [:id,:name] } }.to_soap_xml
|
29
|
+
# => "<findUser><id>666</id><name>Lucy</name></findUser>"
|
30
|
+
def to_soap_xml
|
31
|
+
@soap_xml = Builder::XmlMarkup.new
|
32
|
+
i = self.delete :@inorder # retrieve the hash element keyed by :@inorder if it exists
|
33
|
+
k = self.keys
|
34
|
+
i = k unless (i and i.class == Array)
|
35
|
+
raise "missing elements in :@inorder #{(k - i).inspect}" unless (k - i).empty?
|
36
|
+
raise "spurious elements in :@inorder #{(i - k).inspect}" unless (i - k).empty?
|
37
|
+
i.each {|key| nested_data_to_soap_xml key, self[key] }
|
38
|
+
@soap_xml.target!
|
39
|
+
end
|
40
|
+
|
41
|
+
# Maps keys and values of a Hash created from SOAP response XML to
|
42
|
+
# more convenient Ruby Objects.
|
43
|
+
def map_soap_response
|
44
|
+
inject({}) do |hash, (key, value)|
|
45
|
+
key = key.strip_namespace.snakecase.to_sym
|
46
|
+
|
47
|
+
value = case value
|
48
|
+
when Hash then value["xsi:nil"] ? nil : value.map_soap_response
|
49
|
+
when Array then value.map { |a_value| a_value.map_soap_response rescue a_value }
|
50
|
+
when String then value.map_soap_response
|
51
|
+
end
|
52
|
+
hash.merge key => value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
# Expects a Hash +key+ and +value+ and recursively creates an XML structure
|
59
|
+
# representing the Hash content.
|
60
|
+
def nested_data_to_soap_xml(key, value)
|
61
|
+
case value
|
62
|
+
when Array
|
63
|
+
value.map { |sitem| nested_data_to_soap_xml key, sitem }
|
64
|
+
when Hash
|
65
|
+
@soap_xml.tag!(key.to_soap_key) do
|
66
|
+
i = value.delete :@inorder
|
67
|
+
k = value.keys
|
68
|
+
i = k unless (i and i.class == Array)
|
69
|
+
raise "missing elements in :@inorder #{(k - i).inspect}" unless (k - i).empty?
|
70
|
+
raise "spurious elements in :@inorder #{(i - k).inspect}" unless (i - k).empty?
|
71
|
+
i.each { |subkey| nested_data_to_soap_xml subkey, value[subkey] }
|
72
|
+
end
|
73
|
+
else
|
74
|
+
@soap_xml.tag!(key.to_soap_key) { @soap_xml << value.to_soap_value }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Object
|
2
|
+
|
3
|
+
# Returns +true+ if the Object is false, empty, or a whitespace string.
|
4
|
+
# For example, "", false, nil, [], and {} are blank.
|
5
|
+
# Implementation from ActiveSupport.
|
6
|
+
def blank?
|
7
|
+
respond_to?(:empty?) ? empty? : !self
|
8
|
+
end unless defined? blank?
|
9
|
+
|
10
|
+
# Returns the Object as a SOAP request compliant key.
|
11
|
+
def to_soap_key
|
12
|
+
to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the Object as a SOAP request compliant value.
|
16
|
+
def to_soap_value
|
17
|
+
return to_s unless respond_to? :to_datetime
|
18
|
+
to_datetime.to_soap_value
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Returns a random String of a given +length+.
|
4
|
+
def self.random(length = 100)
|
5
|
+
(0...length).map { ("a".."z").to_a[rand(26)] }.join
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns the String in snake_case.
|
9
|
+
def snakecase
|
10
|
+
str = dup
|
11
|
+
str.gsub! /::/, '/'
|
12
|
+
str.gsub! /([A-Z]+)([A-Z][a-z])/, '\1_\2'
|
13
|
+
str.gsub! /([a-z\d])([A-Z])/, '\1_\2'
|
14
|
+
str.tr! ".", "_"
|
15
|
+
str.tr! "-", "_"
|
16
|
+
str.downcase!
|
17
|
+
str
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the String in lowerCamelCase.
|
21
|
+
def lower_camelcase
|
22
|
+
str = dup
|
23
|
+
str.gsub!(/\/(.?)/) { "::#{$1.upcase}" }
|
24
|
+
str.gsub!(/(?:_+|-+)([a-z])/) { $1.upcase }
|
25
|
+
str.gsub!(/(\A|\s)([A-Z])/) { $1 + $2.downcase }
|
26
|
+
str
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the String without namespace.
|
30
|
+
def strip_namespace
|
31
|
+
gsub /(.+:)(.+)/, '\2'
|
32
|
+
end
|
33
|
+
|
34
|
+
# Translates SOAP response values to more convenient Ruby Objects.
|
35
|
+
def map_soap_response
|
36
|
+
return DateTime.parse( self ) if Savon::SOAPDateTimeRegexp === self
|
37
|
+
return true if self.strip.downcase == "true"
|
38
|
+
return false if self.strip.downcase == "false"
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns the String as a SOAP request compliant value.
|
43
|
+
def to_soap_value
|
44
|
+
to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|