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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rapuncel"
3
- s.version = "0.0.5.RC1"
3
+ s.version = "0.0.5.RC2"
4
4
  s.date = Time.now.strftime("%Y-%m-%d")
5
5
  s.authors = ["Michael Eickenberg", "Marian Theisen"]
6
6
  s.email = 'marian@cice-online.net'
@@ -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::XmlRpcSerializer[@array]
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::XmlRpcDeserializer[@xml]
30
+ @array = Rapuncel::XmlRpc::Deserializer[@xml]
31
31
  end
32
32
 
33
33
  it 'has correct number of elements' do
@@ -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::XmlRpcSerializer[string]
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::XmlRpcDeserializer[xml]
26
+ string = Rapuncel::XmlRpc::Deserializer[xml]
27
27
  string.should be_a Rapuncel::Base64String
28
28
  string.should == "abcdefghABCDEFGH1234567890"
29
29
  end
@@ -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::XmlRpcSerializer[true].should have_xpath('/boolean', :content => '1')
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::XmlRpcSerializer[false].should have_xpath('/boolean', :content => '0')
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::XmlRpcDeserializer[xml].should be_a TrueClass
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::XmlRpcDeserializer[xml].should be_a FalseClass
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::XmlRpcDeserializer[xml].should be_a FalseClass
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
@@ -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::XmlRpcSerializer[number].should have_xpath('/double', :content => "1.23456")
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::XmlRpcSerializer[number].should have_xpath('/double', :content => "1.23456")
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::XmlRpcDeserializer[xml]
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::XmlRpcDeserializer.double_as_bigdecimal = true
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::XmlRpcDeserializer[xml]
32
+ number = Rapuncel::XmlRpc::Deserializer[xml]
33
33
 
34
34
  number.should be_a BigDecimal
35
35
  number.to_s("F").should == "1.23456"
@@ -10,7 +10,7 @@ describe Hash do
10
10
  BigDecimal.new('1.23') => "abcd"
11
11
  }
12
12
 
13
- @xml = Rapuncel::XmlRpcSerializer[@hash]
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::XmlRpcDeserializer[@xml]
38
+ @hash = Rapuncel::XmlRpc::Deserializer[@xml]
39
39
  end
40
40
 
41
41
  it 'preserves number of key-value pairs' do
@@ -2,7 +2,7 @@ require 'spec_helper'
2
2
 
3
3
  describe Integer do
4
4
  it "serialization" do
5
- Rapuncel::XmlRpcSerializer[123].should have_xpath('/int', :content => "123")
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::XmlRpcDeserializer[xml].should == 123
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::XmlRpcDeserializer[xml].should == 123
21
+ Rapuncel::XmlRpc::Deserializer[xml].should == 123
22
22
  end
23
23
  end
@@ -2,6 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe NilClass do
4
4
  it 'serializes like false' do
5
- Rapuncel::XmlRpcSerializer[nil].should have_xpath('/boolean', :content => '0')
5
+ Rapuncel::XmlRpc::Serializer[nil].should have_xpath('/boolean', :content => '0')
6
6
  end
7
7
  end
@@ -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::XmlRpcSerializer[obj]
20
+ xml = Rapuncel::XmlRpc::Serializer[obj]
15
21
  xml.should have_xpath('/struct/member', :count => 2)
16
22
 
17
- reparsed_object = Rapuncel::XmlRpcDeserializer[xml]
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
@@ -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::XmlRpcSerializer[@request]
8
+ @xml = Rapuncel::XmlRpc::Serializer[@request]
9
9
  end
10
10
 
11
11
  it 'should be in xml version=1.0' do
@@ -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
@@ -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::XmlRpcSerializer[string]
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::XmlRpcSerializer[symbol]
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::XmlRpcSerializer[string]
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::XmlRpcDeserializer[xml]
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::XmlRpcDeserializer[Rapuncel::XmlRpcSerializer[string]]
32
+ string2 = Rapuncel::XmlRpc::Deserializer[Rapuncel::XmlRpc::Serializer[string]]
33
33
  string2.should == "one\ntwo\nthree\nfour"
34
34
  end
35
35
  end