rapuncel 0.0.5.RC1 → 0.0.5.RC2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +30 -0
- data/README.md +44 -22
- data/lib/rapuncel/base_64_string.rb +17 -12
- data/lib/rapuncel/client.rb +29 -4
- data/lib/rapuncel/connection.rb +2 -1
- data/lib/rapuncel/proxy.rb +10 -3
- data/lib/rapuncel/request.rb +0 -2
- data/lib/rapuncel/response.rb +5 -6
- data/lib/rapuncel/xml_rpc/deserializer.rb +113 -0
- data/lib/rapuncel/xml_rpc/serializer.rb +153 -0
- data/rapuncel-0.0.5.RC1.gem +0 -0
- data/rapuncel.gemspec +1 -1
- data/spec/unit/array_spec.rb +2 -2
- data/spec/unit/base64_spec.rb +2 -2
- data/spec/unit/boolean_spec.rb +5 -5
- data/spec/unit/custom_serialization_spec.rb +23 -0
- data/spec/unit/float_spec.rb +5 -5
- data/spec/unit/hash_spec.rb +2 -2
- data/spec/unit/int_spec.rb +3 -3
- data/spec/unit/nil_spec.rb +1 -1
- data/spec/unit/object_spec.rb +23 -2
- data/spec/unit/request_spec.rb +1 -1
- data/spec/unit/response_spec.rb +3 -3
- data/spec/unit/string_spec.rb +5 -5
- data/spec/unit/time_spec.rb +2 -2
- metadata +92 -51
- data/lib/rapuncel/xml_rpc_deserializer.rb +0 -110
- data/lib/rapuncel/xml_rpc_serializer.rb +0 -148
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'bigdecimal'
|
2
|
+
require 'time'
|
3
|
+
|
4
|
+
module Rapuncel
|
5
|
+
module XmlRpc
|
6
|
+
class Serializer
|
7
|
+
XML_ENCODING = 'UTF-8'
|
8
|
+
|
9
|
+
attr_reader :builder
|
10
|
+
|
11
|
+
def initialize object
|
12
|
+
@builder = Nokogiri::XML::Builder.new :encoding => XML_ENCODING
|
13
|
+
|
14
|
+
serialize object
|
15
|
+
end
|
16
|
+
|
17
|
+
def serialize object
|
18
|
+
case object
|
19
|
+
when Base64String
|
20
|
+
serialize_base64 object
|
21
|
+
when Array
|
22
|
+
serialize_array object
|
23
|
+
when String, Symbol
|
24
|
+
serialize_string object.to_s
|
25
|
+
when TrueClass
|
26
|
+
serialize_true
|
27
|
+
when FalseClass
|
28
|
+
serialize_false
|
29
|
+
when Float
|
30
|
+
serialize_float object
|
31
|
+
when BigDecimal
|
32
|
+
serialize_big_decimal object
|
33
|
+
when Hash
|
34
|
+
serialize_hash object
|
35
|
+
when Integer
|
36
|
+
serialize_integer object
|
37
|
+
when NilClass
|
38
|
+
serialize_nil
|
39
|
+
when Time
|
40
|
+
serialize_time object
|
41
|
+
when Request
|
42
|
+
serialize_request object
|
43
|
+
else
|
44
|
+
if object.respond_to?(:acts_like?) && object.acts_like?(:time)
|
45
|
+
serialize_time object
|
46
|
+
elsif object.respond_to?(:to_xmlrpc)
|
47
|
+
object.to_xmlrpc self
|
48
|
+
else
|
49
|
+
serialize_hash instance_variable_hash(object)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def serialize_base64 string
|
57
|
+
builder.base64 string.base64_encoded
|
58
|
+
end
|
59
|
+
|
60
|
+
def serialize_array array
|
61
|
+
builder.array do |builder|
|
62
|
+
builder.data do |builder|
|
63
|
+
array.each do |element|
|
64
|
+
builder.value do |_|
|
65
|
+
serialize element
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def serialize_string string
|
73
|
+
builder.string string
|
74
|
+
end
|
75
|
+
|
76
|
+
def serialize_true
|
77
|
+
builder.boolean "1"
|
78
|
+
end
|
79
|
+
|
80
|
+
def serialize_false
|
81
|
+
builder.boolean "0"
|
82
|
+
end
|
83
|
+
alias_method :serialize_nil, :serialize_false
|
84
|
+
|
85
|
+
def serialize_float float
|
86
|
+
builder.double float.to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
def serialize_big_decimal big_decimal
|
90
|
+
builder.double big_decimal.to_s("F")
|
91
|
+
end
|
92
|
+
|
93
|
+
def serialize_hash hash
|
94
|
+
builder.struct do |builder|
|
95
|
+
hash.each_pair do |key, value|
|
96
|
+
builder.member do |builder|
|
97
|
+
# Get a better string representation of BigDecimals
|
98
|
+
key = key.to_s("F") if BigDecimal === key
|
99
|
+
builder.name key.to_s
|
100
|
+
|
101
|
+
builder.value do |builder|
|
102
|
+
serialize value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def serialize_integer int
|
110
|
+
builder.int int.to_s
|
111
|
+
end
|
112
|
+
|
113
|
+
def serialize_time time
|
114
|
+
builder.send "dateTime.iso8601", time.iso8601
|
115
|
+
end
|
116
|
+
|
117
|
+
def serialize_request request
|
118
|
+
builder.methodCall do |builder|
|
119
|
+
builder.methodName request.method_name
|
120
|
+
builder.params do |builder|
|
121
|
+
request.arguments.each do |argument|
|
122
|
+
builder.param do |builder|
|
123
|
+
builder.value do |builder|
|
124
|
+
serialize argument
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def to_xml
|
133
|
+
@builder.to_xml
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
def instance_variable_hash object
|
138
|
+
{}.tap do |hash|
|
139
|
+
object.instance_variables.each do |ivar|
|
140
|
+
hash[ivar[1..-1]] = object.instance_variable_get ivar
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class << self
|
146
|
+
def serialize object
|
147
|
+
new(object).to_xml
|
148
|
+
end
|
149
|
+
alias_method :[], :serialize
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
Binary file
|
data/rapuncel.gemspec
CHANGED
data/spec/unit/array_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Array do
|
|
5
5
|
before do
|
6
6
|
@array = (1..10).to_a.map &:to_s
|
7
7
|
|
8
|
-
@xml = Rapuncel::
|
8
|
+
@xml = Rapuncel::XmlRpc::Serializer[@array]
|
9
9
|
end
|
10
10
|
|
11
11
|
it "yields a value tag for each array element" do
|
@@ -27,7 +27,7 @@ describe Array do
|
|
27
27
|
<value><string>3</string></value>
|
28
28
|
</data></array>
|
29
29
|
XML
|
30
|
-
@array = Rapuncel::
|
30
|
+
@array = Rapuncel::XmlRpc::Deserializer[@xml]
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'has correct number of elements' do
|
data/spec/unit/base64_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe "Base64" do
|
|
14
14
|
string = "abcdefghABCDEFGH1234567890".as_base64
|
15
15
|
string.should be_a Rapuncel::Base64String
|
16
16
|
|
17
|
-
xml = Rapuncel::
|
17
|
+
xml = Rapuncel::XmlRpc::Serializer[string]
|
18
18
|
xml.should have_xpath('/base64', :content => to_base64(string))
|
19
19
|
end
|
20
20
|
|
@@ -23,7 +23,7 @@ describe "Base64" do
|
|
23
23
|
<base64>YWJjZGVmZ2hBQkNERUZHSDEyMzQ1Njc4OTA=</base64>
|
24
24
|
XML
|
25
25
|
|
26
|
-
string = Rapuncel::
|
26
|
+
string = Rapuncel::XmlRpc::Deserializer[xml]
|
27
27
|
string.should be_a Rapuncel::Base64String
|
28
28
|
string.should == "abcdefghABCDEFGH1234567890"
|
29
29
|
end
|
data/spec/unit/boolean_spec.rb
CHANGED
@@ -3,11 +3,11 @@ require 'spec_helper'
|
|
3
3
|
describe TrueClass, FalseClass do
|
4
4
|
describe "Serialization" do
|
5
5
|
it 'represents true as 1' do
|
6
|
-
Rapuncel::
|
6
|
+
Rapuncel::XmlRpc::Serializer[true].should have_xpath('/boolean', :content => '1')
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'represents false as 0' do
|
10
|
-
Rapuncel::
|
10
|
+
Rapuncel::XmlRpc::Serializer[false].should have_xpath('/boolean', :content => '0')
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -17,7 +17,7 @@ describe TrueClass, FalseClass do
|
|
17
17
|
<boolean>1</boolean>
|
18
18
|
XML
|
19
19
|
|
20
|
-
Rapuncel::
|
20
|
+
Rapuncel::XmlRpc::Deserializer[xml].should be_a TrueClass
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'reads 0 as false' do
|
@@ -25,7 +25,7 @@ describe TrueClass, FalseClass do
|
|
25
25
|
<boolean>0</boolean>
|
26
26
|
XML
|
27
27
|
|
28
|
-
Rapuncel::
|
28
|
+
Rapuncel::XmlRpc::Deserializer[xml].should be_a FalseClass
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'reads anything else as false' do
|
@@ -33,7 +33,7 @@ describe TrueClass, FalseClass do
|
|
33
33
|
<boolean>abcd</boolean>
|
34
34
|
XML
|
35
35
|
|
36
|
-
Rapuncel::
|
36
|
+
Rapuncel::XmlRpc::Deserializer[xml].should be_a FalseClass
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Custom serialization" do
|
4
|
+
module CustomSerialization
|
5
|
+
class Serializer < Rapuncel::XmlRpc::Serializer
|
6
|
+
end
|
7
|
+
|
8
|
+
class Deserializer < Rapuncel::XmlRpc::Deserializer
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'client selects custom (de)serializer, if provided by Symbol' do
|
13
|
+
client = Rapuncel::Client.new :serialization => :CustomSerialization
|
14
|
+
|
15
|
+
client.send(:serializer).should == CustomSerialization::Serializer
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'client selects custom (de)serializer, if provided by Class' do
|
19
|
+
client = Rapuncel::Client.new :serialization => CustomSerialization
|
20
|
+
|
21
|
+
client.send(:serializer).should == CustomSerialization::Serializer
|
22
|
+
end
|
23
|
+
end
|
data/spec/unit/float_spec.rb
CHANGED
@@ -4,12 +4,12 @@ describe Float do
|
|
4
4
|
describe "Serialization" do
|
5
5
|
it "can serialize Floats" do
|
6
6
|
number = 1.23456
|
7
|
-
Rapuncel::
|
7
|
+
Rapuncel::XmlRpc::Serializer[number].should have_xpath('/double', :content => "1.23456")
|
8
8
|
end
|
9
9
|
|
10
10
|
it "can serialize BigDecimal" do
|
11
11
|
number = BigDecimal.new '1.23456'
|
12
|
-
Rapuncel::
|
12
|
+
Rapuncel::XmlRpc::Serializer[number].should have_xpath('/double', :content => "1.23456")
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -18,18 +18,18 @@ describe Float do
|
|
18
18
|
xml = <<-XML
|
19
19
|
<double>1.23456</double>
|
20
20
|
XML
|
21
|
-
number = Rapuncel::
|
21
|
+
number = Rapuncel::XmlRpc::Deserializer[xml]
|
22
22
|
number.should be_a Float
|
23
23
|
number.should == 1.23456
|
24
24
|
end
|
25
25
|
|
26
26
|
it "can optionally deserialize all double to BigDecimal" do
|
27
|
-
Rapuncel::
|
27
|
+
Rapuncel::XmlRpc::Deserializer.double_as_bigdecimal = true
|
28
28
|
|
29
29
|
xml = <<-XML
|
30
30
|
<double>1.23456</double>
|
31
31
|
XML
|
32
|
-
number = Rapuncel::
|
32
|
+
number = Rapuncel::XmlRpc::Deserializer[xml]
|
33
33
|
|
34
34
|
number.should be_a BigDecimal
|
35
35
|
number.to_s("F").should == "1.23456"
|
data/spec/unit/hash_spec.rb
CHANGED
@@ -10,7 +10,7 @@ describe Hash do
|
|
10
10
|
BigDecimal.new('1.23') => "abcd"
|
11
11
|
}
|
12
12
|
|
13
|
-
@xml = Rapuncel::
|
13
|
+
@xml = Rapuncel::XmlRpc::Serializer[@hash]
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'preserves number of key-value pairs' do
|
@@ -35,7 +35,7 @@ describe Hash do
|
|
35
35
|
</struct>
|
36
36
|
XML
|
37
37
|
|
38
|
-
@hash = Rapuncel::
|
38
|
+
@hash = Rapuncel::XmlRpc::Deserializer[@xml]
|
39
39
|
end
|
40
40
|
|
41
41
|
it 'preserves number of key-value pairs' do
|
data/spec/unit/int_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Integer do
|
4
4
|
it "serialization" do
|
5
|
-
Rapuncel::
|
5
|
+
Rapuncel::XmlRpc::Serializer[123].should have_xpath('/int', :content => "123")
|
6
6
|
end
|
7
7
|
|
8
8
|
it "deserialization of int" do
|
@@ -10,7 +10,7 @@ describe Integer do
|
|
10
10
|
<int>123</int>
|
11
11
|
XML
|
12
12
|
|
13
|
-
Rapuncel::
|
13
|
+
Rapuncel::XmlRpc::Deserializer[xml].should == 123
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'deserialization of i4' do
|
@@ -18,6 +18,6 @@ describe Integer do
|
|
18
18
|
<i4>123</i4>
|
19
19
|
XML
|
20
20
|
|
21
|
-
Rapuncel::
|
21
|
+
Rapuncel::XmlRpc::Deserializer[xml].should == 123
|
22
22
|
end
|
23
23
|
end
|
data/spec/unit/nil_spec.rb
CHANGED
data/spec/unit/object_spec.rb
CHANGED
@@ -5,20 +5,41 @@ describe Object do
|
|
5
5
|
attr_accessor :a, :b, :c
|
6
6
|
end
|
7
7
|
|
8
|
+
class TestObjectWithOwnBehavior < TestObject
|
9
|
+
def to_xmlrpc serializer
|
10
|
+
serializer.builder.string "custom thing"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
8
14
|
describe "Serialization of an arbitrary Object" do
|
9
15
|
it "serializes all instance variables like a hash" do
|
10
16
|
obj = TestObject.new
|
11
17
|
obj.a = "one"
|
12
18
|
obj.b = "two"
|
13
19
|
|
14
|
-
xml = Rapuncel::
|
20
|
+
xml = Rapuncel::XmlRpc::Serializer[obj]
|
15
21
|
xml.should have_xpath('/struct/member', :count => 2)
|
16
22
|
|
17
|
-
reparsed_object = Rapuncel::
|
23
|
+
reparsed_object = Rapuncel::XmlRpc::Deserializer[xml]
|
18
24
|
reparsed_object.should == {
|
19
25
|
:a => 'one',
|
20
26
|
:b => 'two'
|
21
27
|
}
|
22
28
|
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "Serialization of an Object with #to_xmlrpc" do
|
33
|
+
it "uses this method to serialize" do
|
34
|
+
obj = TestObjectWithOwnBehavior.new
|
35
|
+
|
36
|
+
obj.a = 'one'
|
37
|
+
|
38
|
+
xml = Rapuncel::XmlRpc::Serializer[obj]
|
39
|
+
xml.should have_xpath('/string')
|
40
|
+
|
41
|
+
reparsed_object = Rapuncel::XmlRpc::Deserializer[xml]
|
42
|
+
reparsed_object.should == "custom thing"
|
43
|
+
end
|
23
44
|
end
|
24
45
|
end
|
data/spec/unit/request_spec.rb
CHANGED
@@ -5,7 +5,7 @@ describe Rapuncel::Request do
|
|
5
5
|
describe "Serialization" do
|
6
6
|
before do
|
7
7
|
@request = Rapuncel::Request.new 'test_method', "one argument", "another"
|
8
|
-
@xml = Rapuncel::
|
8
|
+
@xml = Rapuncel::XmlRpc::Serializer[@request]
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'should be in xml version=1.0' do
|
data/spec/unit/response_spec.rb
CHANGED
@@ -27,7 +27,7 @@ describe Rapuncel::Response do
|
|
27
27
|
</methodResponse>
|
28
28
|
XML
|
29
29
|
|
30
|
-
response = Rapuncel::Response.new successful_response
|
30
|
+
response = Rapuncel::Response.new successful_response, Rapuncel::XmlRpc::Deserializer
|
31
31
|
response.should be_success
|
32
32
|
|
33
33
|
response.result.should == "foo foo foo"
|
@@ -66,7 +66,7 @@ describe Rapuncel::Response do
|
|
66
66
|
</methodResponse>
|
67
67
|
XML
|
68
68
|
|
69
|
-
response = Rapuncel::Response.new fault_response
|
69
|
+
response = Rapuncel::Response.new fault_response, Rapuncel::XmlRpc::Deserializer
|
70
70
|
response.should be_fault
|
71
71
|
|
72
72
|
response.to_ruby.should be_a Hash
|
@@ -76,7 +76,7 @@ describe Rapuncel::Response do
|
|
76
76
|
it 'should handle errors' do
|
77
77
|
error_response = HttpResponse.new "Not Found", false, 404
|
78
78
|
|
79
|
-
response = Rapuncel::Response.new error_response
|
79
|
+
response = Rapuncel::Response.new error_response, Rapuncel::XmlRpc::Deserializer
|
80
80
|
response.should be_error
|
81
81
|
|
82
82
|
response.to_ruby.should be_a Hash
|
data/spec/unit/string_spec.rb
CHANGED
@@ -3,19 +3,19 @@ require 'spec_helper'
|
|
3
3
|
describe String, Symbol do
|
4
4
|
it 'serialization of a String' do
|
5
5
|
string = "foobar"
|
6
|
-
xml = Rapuncel::
|
6
|
+
xml = Rapuncel::XmlRpc::Serializer[string]
|
7
7
|
xml.should have_xpath('/string', :content => "foobar")
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'serialization of a Symbol' do
|
11
11
|
symbol = :foobar
|
12
|
-
xml = Rapuncel::
|
12
|
+
xml = Rapuncel::XmlRpc::Serializer[symbol]
|
13
13
|
xml.should have_xpath('/string', :content => "foobar")
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'preservation of trailing an leading whitespaces' do
|
17
17
|
string = "\n\t abcd\n \t"
|
18
|
-
xml = Rapuncel::
|
18
|
+
xml = Rapuncel::XmlRpc::Serializer[string]
|
19
19
|
xml.should have_xpath('/string', :content => "\n\t abcd\n \t")
|
20
20
|
end
|
21
21
|
|
@@ -23,13 +23,13 @@ describe String, Symbol do
|
|
23
23
|
xml = <<-XML
|
24
24
|
<string>abcd\nefgh \n\t</string>
|
25
25
|
XML
|
26
|
-
string = Rapuncel::
|
26
|
+
string = Rapuncel::XmlRpc::Deserializer[xml]
|
27
27
|
string.should == "abcd\nefgh \n\t"
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'normalization of linebreaks' do
|
31
31
|
string = "one\r\ntwo\rthree\nfour"
|
32
|
-
string2 = Rapuncel::
|
32
|
+
string2 = Rapuncel::XmlRpc::Deserializer[Rapuncel::XmlRpc::Serializer[string]]
|
33
33
|
string2.should == "one\ntwo\nthree\nfour"
|
34
34
|
end
|
35
35
|
end
|