rapuncel 0.0.5.RC1 → 0.0.5.RC2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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