rapuncel 0.0.1.alpha → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/README.md +33 -36
  2. data/{Rakefile → Rakefile.rb} +1 -1
  3. data/lib/rapuncel.rb +1 -2
  4. data/lib/rapuncel/adapters/net_http_adapter.rb +6 -6
  5. data/lib/rapuncel/adapters/typhoeus_adapter.rb +33 -0
  6. data/lib/rapuncel/base.rb +2 -2
  7. data/lib/rapuncel/client.rb +13 -21
  8. data/lib/rapuncel/connection.rb +2 -2
  9. data/lib/rapuncel/core_ext/array.rb +16 -9
  10. data/lib/rapuncel/core_ext/big_decimal.rb +0 -7
  11. data/lib/rapuncel/core_ext/boolean.rb +13 -10
  12. data/lib/rapuncel/core_ext/float.rb +7 -4
  13. data/lib/rapuncel/core_ext/hash.rb +27 -17
  14. data/lib/rapuncel/core_ext/integer.rb +10 -2
  15. data/lib/rapuncel/core_ext/object.rb +6 -6
  16. data/lib/rapuncel/core_ext/string.rb +7 -5
  17. data/lib/rapuncel/core_ext/symbol.rb +3 -2
  18. data/lib/rapuncel/core_ext/time.rb +8 -5
  19. data/lib/rapuncel/fault.rb +10 -0
  20. data/lib/rapuncel/proxy.rb +14 -39
  21. data/lib/rapuncel/request.rb +6 -7
  22. data/lib/rapuncel/response.rb +31 -69
  23. data/rapuncel.gemspec +4 -3
  24. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-adapters-typhoeus_adapter_rb.html +231 -0
  25. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-base_rb.html +105 -0
  26. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-client_rb.html +321 -0
  27. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-connection_rb.html +513 -0
  28. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-array_rb.html +303 -0
  29. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-boolean_rb.html +255 -0
  30. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-float_rb.html +177 -0
  31. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-hash_rb.html +297 -0
  32. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-integer_rb.html +177 -0
  33. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-object_rb.html +297 -0
  34. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-string_rb.html +159 -0
  35. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-core_ext-time_rb.html +165 -0
  36. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-fault_rb.html +93 -0
  37. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-proxy_rb.html +393 -0
  38. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-request_rb.html +351 -0
  39. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel-response_rb.html +399 -0
  40. data/test/coverage/-Users-mariantheisen-Projects-Kayoom-rapuncel-lib-rapuncel_rb.html +201 -0
  41. data/test/coverage/functional_test_helper_rb.html +141 -0
  42. data/test/coverage/index.html +410 -0
  43. data/test/coverage/jquery-1.3.2.min.js +19 -0
  44. data/test/coverage/jquery.tablesorter.min.js +15 -0
  45. data/test/coverage/print.css +12 -0
  46. data/test/coverage/rcov.js +42 -0
  47. data/test/coverage/screen.css +270 -0
  48. data/test/coverage/test_helper_rb.html +291 -0
  49. data/test/coverage/test_server_rb.html +231 -0
  50. data/test/functional/client_test.rb +7 -38
  51. data/test/functional_test_helper.rb +2 -2
  52. data/test/test_server.rb +29 -3
  53. data/test/unit/array_test.rb +14 -14
  54. data/test/unit/boolean_test.rb +6 -6
  55. data/test/unit/float_test.rb +7 -7
  56. data/test/unit/hash_test.rb +16 -16
  57. data/test/unit/object_test.rb +29 -29
  58. data/test/unit/proxy_test.rb +9 -9
  59. data/test/unit/response_test.rb +5 -69
  60. data/test/unit/string_test.rb +7 -15
  61. metadata +56 -20
  62. data/lib/rapuncel/core_ext/nil.rb +0 -7
  63. data/rapuncel-0.0.1.preview.gem +0 -0
  64. data/test/unit/nil_test.rb +0 -16
@@ -1,32 +1,42 @@
1
+ require 'builder'
2
+
3
+ class Rapuncel::Hash
4
+
5
+ end
6
+
1
7
  class Hash
2
- # Hash will be translated into an XML-RPC "struct" object
8
+ #Hash will be translated into an XML-RPC "struct" object
3
9
 
4
10
  def to_xml_rpc b = Rapuncel.get_builder
11
+
5
12
  b.struct do |b|
6
13
  self.each_pair do |key, value|
7
- b.member do |b|
8
- b.name key.to_s
9
14
 
10
- b.value do |b|
15
+ #warn "The key #{key.to_s} is a #{key.class.to_s}, which is neither a symbol nor a string. It will be converted using to_s" unless key.is_a?(String) || key.is_a?(Symbol)
16
+
17
+ b.member do
18
+
19
+ b.name key.to_s
20
+ b.value do
11
21
  value.to_xml_rpc b
12
22
  end
13
23
  end
14
24
  end
15
25
  end
16
-
17
- b.to_xml
18
26
  end
19
-
27
+
20
28
  def self.from_xml_rpc xml_node
21
- keys_and_values = xml_node.element_children
22
-
23
- new.tap do |hash|
24
- keys_and_values.each do |kv|
25
- key = kv.first_element_child.text.strip.to_sym
26
- value = Object.from_xml_rpc kv.last_element_child.first_element_child
27
-
28
- hash[key] = value
29
- end
29
+ #warn "The given xml_node is a #{xml_node.name}, not a 'struct'. Continuing at your risk" unless ['struct'].include? xml_node.name
30
+
31
+ keys_and_values = xml_node.element_children #xpath('./member')
32
+
33
+ hash = new
34
+ keys_and_values.each do |kv|
35
+ key = kv.first_element_child.text.to_sym
36
+
37
+ value = Object.from_xml_rpc kv.last_element_child.first_element_child
38
+ hash[key] = value
30
39
  end
31
- end
40
+ hash
41
+ end
32
42
  end
@@ -1,11 +1,19 @@
1
+ require 'builder'
2
+ require 'nokogiri'
3
+ require 'ruby-debug'
4
+
1
5
  class Integer
6
+
2
7
  def to_xml_rpc b = Rapuncel.get_builder
8
+ #warn "XML-RPC standard only supports 4 byte signed integers, i.e #{(-2**31).to_s} to #{2**31-1}" unless ((-2**31)...(2**31)) === self
9
+
3
10
  b.int self.to_s
4
11
 
5
- b.to_xml
6
12
  end
7
13
 
8
14
  def self.from_xml_rpc xml_node
9
- xml_node.text.strip.to_i #calling to_i on the text between the i4 or int tags
15
+ #warn "xml node given (name of #{xml_node.name}) is not of integer type, node name should be 'i4' or 'int'" unless ['i4','int'].include? xml_node.name.downcase
16
+
17
+ xml_node.text.to_i #calling to_i on the text between the i4 or int tags
10
18
  end
11
19
  end
@@ -1,21 +1,21 @@
1
+ require 'builder'
2
+
1
3
  class Object
2
4
  def to_xml_rpc b = Rapuncel.get_builder
3
5
  if respond_to?(:acts_like?) && acts_like?(:time)
4
6
  to_time.to_xml_rpc b
5
- else
7
+ else
6
8
  _collect_ivars_in_hash.to_xml_rpc b
7
9
  end
8
-
9
- b.to_xml
10
10
  end
11
11
 
12
12
  def self.from_xml_rpc xml_node
13
13
  if xml_node.is_a? String
14
14
  xml_node = Nokogiri::XML.parse(xml_node).root
15
15
  end
16
-
16
+
17
17
  return nil if xml_node.nil?
18
-
18
+
19
19
  case xml_node.name
20
20
  when 'i4', 'int'
21
21
  Integer.from_xml_rpc xml_node
@@ -34,7 +34,7 @@ class Object
34
34
  when 'base64'
35
35
  raise 'Now its time to implement Base64'
36
36
  else
37
- raise "What is this? I didn't know #{xml_node.name} was part of the XMLRPC specification? Anyway, the value was: #{xml_node.text.strip}"
37
+ raise "What is this? I didn't know #{xml_node.name} was part of the XMLRPC specification? Anyway, the value was: #{xml_node.text}"
38
38
  end
39
39
  end
40
40
 
@@ -1,12 +1,14 @@
1
+ require 'builder'
2
+ require 'nokogiri'
3
+
1
4
  class String
2
5
  def to_xml_rpc b = Rapuncel.get_builder
3
6
  b.string self
4
-
5
- b.to_xml
6
7
  end
7
-
8
+
8
9
  def self.from_xml_rpc xml_node
9
- xml_node.text.gsub(/(\r\n|\r)/, "\n") #just give back the string between the 'string' tags
10
- # DISCUSS: to strip or not to strip
10
+ #warn "I, String.from_xml_rpc have been given an xml_node with the wrong tag (name of #{xml_node.name}). My tag should be 'string'. Will still parse at your risk" unless ['string'].include? xml_node.name.downcase
11
+
12
+ xml_node.text #just give back the string between the 'string' tags
11
13
  end
12
14
  end
@@ -1,7 +1,8 @@
1
+ require 'builder'
2
+ require 'nokogiri'
3
+
1
4
  class Symbol
2
5
  def to_xml_rpc b = Rapuncel.get_builder
3
6
  b.string to_s
4
-
5
- b.to_xml
6
7
  end
7
8
  end
@@ -1,14 +1,17 @@
1
+ require 'builder'
1
2
  require 'time'
3
+ require 'nokogiri'
2
4
 
3
5
  class Time
4
6
 
5
7
  def to_xml_rpc b=Rapuncel.get_builder
6
- b.send "dateTime.iso8601", self.iso8601
7
-
8
- b.to_xml
8
+ b.tag! "dateTime.iso8601", self.iso8601
9
9
  end
10
-
10
+
11
11
  def self.from_xml_rpc xml_node
12
- Time.parse xml_node.text.strip #make a Time object of this string which is hopefully in the right format
12
+ #warn "Need node to be named 'dateTime.iso8601', but it is #{xml_node.name}. Will still parse, at your risk" unless ['dateTime.iso8601'].include? xml_node.name
13
+
14
+ Time.parse xml_node.text #make a Time object of this string which is hopefully in the right format
13
15
  end
16
+
14
17
  end
@@ -0,0 +1,10 @@
1
+ module Rapuncel
2
+ class Fault
3
+ attr_accessor :code, :string
4
+
5
+ def initialize hsh
6
+ @code = hsh[:faultCode]
7
+ @string = hsh[:faultString]
8
+ end
9
+ end
10
+ end
@@ -2,38 +2,23 @@ require 'rapuncel/request'
2
2
 
3
3
  module Rapuncel
4
4
  class Proxy
5
- PROXY_METHODS = %w(tap inspect clone freeze dup class initialize).freeze
6
- LOCKED_METHODS = %w(method_missing).freeze
7
- LOCKED_PATTERN = /(\A__|\?\Z|!\Z)/.freeze
5
+ PROXY_METHODS = %w(tap inspect clone freeze dup class initialize)
6
+ LOCKED_METHODS = %w(method_missing)
7
+ LOCKED_PATTERN = /(\A__|\?\Z|!\Z)/
8
8
 
9
9
  class << self
10
- # Initialize a new Proxy object for a specific Client. Alternatively
11
- # you can pass a Hash containing configuration for a new Client, which
12
- # will be created on-the-fly, but not accessible. The second parameter
13
- # specifies a specific interface/namespace for the remote calls,
14
- # i.e. if your RPC method is
15
- #
16
- # int numbers.add(int a, int b)
17
- #
18
- # You can create a specific proxy for +numbers+, and use +add+ directly
19
- #
20
- # proxy = Proxy.new client, 'numbers'
21
- # proxy.add(40, 2) -> 42
22
- #
23
- def new client_or_configuration, interface = nil
10
+ def new client_or_configuration, interface = nil
24
11
  client_or_configuration = Client.new client_or_configuration if client_or_configuration.is_a?(Hash)
25
-
12
+
26
13
  allocate.__tap__ do |new_proxy|
27
14
  new_proxy.__initialize__ client_or_configuration, interface
28
15
  end
29
16
  end
30
17
 
31
18
  def define_proxy_method name
32
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
33
- def #{name} *args, &block
34
- call! '#{name}', *args, &block
35
- end
36
- RUBY
19
+ define_method name do |*args|
20
+ call! name, *args
21
+ end
37
22
  end
38
23
  end
39
24
 
@@ -48,34 +33,24 @@ module Rapuncel
48
33
  end
49
34
 
50
35
  def call! name, *args
51
- name = "#{@interface}.#{name}" if @interface
52
-
53
- @client.call_to_ruby(name, *args).tap do |response|
54
-
55
- if block_given?
56
- yield response
57
- end
58
- end
36
+ name = [@interface, name] * '.' if @interface
37
+ @client.execute_to_ruby Request.new(name, *args)
59
38
  end
60
39
 
61
- def __initialize__ client, interface #:nodoc:
40
+ def __initialize__ client, interface
62
41
  @interface = interface
63
42
  @client = client
64
43
  end
65
44
 
66
- def respond_to? name #:nodoc:
67
- LOCKED_PATTERN.match(name.to_s) ? super : true
68
- end
69
-
70
45
  protected
71
- def method_missing name, *args, &block #:nodoc:
46
+ def method_missing name, *args
72
47
  name = name.to_s
73
48
 
74
49
  if LOCKED_PATTERN.match name
75
- super name.to_sym, *args, &block
50
+ super
76
51
  else
77
52
  self.__class__.define_proxy_method name
78
- call! name, *args, &block
53
+ call! name, *args
79
54
  end
80
55
  end
81
56
  end
@@ -1,4 +1,4 @@
1
-
1
+ require 'builder'
2
2
 
3
3
 
4
4
  module Rapuncel
@@ -13,14 +13,13 @@ module Rapuncel
13
13
 
14
14
  def to_xml_rpc builder = Rapuncel.get_builder
15
15
  method_call! builder
16
-
17
- builder.to_xml :encoding => 'UTF-8'
18
16
  end
19
17
 
20
18
  protected
21
19
  def method_call! builder
20
+ builder.instruct!
22
21
 
23
- builder.methodCall do |builder|
22
+ builder.methodCall do
24
23
  method_name! builder
25
24
  params! builder
26
25
  end
@@ -31,7 +30,7 @@ module Rapuncel
31
30
  end
32
31
 
33
32
  def params! builder
34
- builder.params do |builder|
33
+ builder.params do
35
34
  arguments.each do |value|
36
35
  param! builder, value
37
36
  end
@@ -39,8 +38,8 @@ module Rapuncel
39
38
  end
40
39
 
41
40
  def param! builder, value
42
- builder.param do |builder|
43
- builder.value do |builder|
41
+ builder.param do
42
+ builder.value do
44
43
  value.to_xml_rpc builder
45
44
  end
46
45
  end
@@ -1,22 +1,9 @@
1
1
  require 'active_support/core_ext/module/delegation'
2
+ require 'rapuncel/fault'
2
3
 
3
4
  module Rapuncel
4
5
  class Response
5
- class Exception < ::Exception
6
- attr_accessor :code, :string
7
-
8
- def initialize code, string
9
- @code, @string = code, string
10
- end
11
-
12
- def exception
13
- self
14
- end
15
- end
16
- class Fault < Exception ; end
17
- class Error < Exception ; end
18
-
19
- attr_accessor :http_response, :status, :status_code
6
+ attr_accessor :http_response, :status
20
7
 
21
8
  delegate :body,
22
9
  :to => :http_response
@@ -24,16 +11,11 @@ module Rapuncel
24
11
  def initialize http_response
25
12
  @http_response = http_response
26
13
 
27
- evaluate_status
28
- end
29
-
30
- def evaluate_status
31
- @status_code = http_response.code.to_i
32
-
33
- @status = case
34
- when !http_response.success? then 'error'
35
- when parsed_body && method_response_success? then 'success'
36
- else 'fault'
14
+ if http_response.success?
15
+ parse_response
16
+ else
17
+ @status = http_response.code
18
+ raise("HTTP Error: #{@status}\n#{body}")
37
19
  end
38
20
  end
39
21
 
@@ -41,52 +23,32 @@ module Rapuncel
41
23
  status == 'success'
42
24
  end
43
25
 
44
- def fault?
45
- status == 'fault'
46
- end
47
-
48
- def error?
49
- status == 'error'
50
- end
51
-
52
- def fault
53
- if fault?
54
- @fault ||= begin
55
- fault_node = parsed_body.xpath('/methodResponse/fault/value/struct').first
56
- fault_hash = Hash.from_xml_rpc(fault_node)
57
-
58
- Fault.new fault_hash[:faultCode], fault_hash[:faultString]
59
- end
60
- end
61
- end
62
-
63
- def error
64
- if error?
65
- @error ||= Error.new @status_code, body
66
- end
67
- end
68
-
69
- def result
70
- if success?
71
- @result ||= begin
72
- return_values = parsed_body.xpath('/methodResponse/params/param/value/*')
73
-
74
- Object.from_xml_rpc return_values.first
75
- end
76
- end
77
- end
78
-
79
26
  def to_ruby
80
- result || fault || error
81
- end
82
-
83
- protected
84
- def parsed_body
85
- @xml_doc ||= Nokogiri::XML.parse body
27
+ @to_ruby
28
+ end
29
+
30
+ def parse_fault
31
+ fault = @xml_doc.xpath('/methodResponse/fault/value/struct')
32
+
33
+ @to_ruby = Fault.new Hash.from_xml_rpc(fault.first)
34
+ end
35
+
36
+ def parse_response
37
+ @xml_doc = Nokogiri::XML.parse body
38
+
39
+ if @xml_doc.xpath('/methodResponse/fault').empty?
40
+ @status = 'success'
41
+ parse_success
42
+ else
43
+ @status = 'fault'
44
+ parse_fault
45
+ end
86
46
  end
87
-
88
- def method_response_success?
89
- parsed_body.xpath('/methodResponse/fault').empty?
47
+
48
+ def parse_success
49
+ values = @xml_doc.xpath('/methodResponse/params/param/value/*')
50
+
51
+ @to_ruby = Object.from_xml_rpc values.to_a.first
90
52
  end
91
53
  end
92
54
  end
data/rapuncel.gemspec CHANGED
@@ -1,12 +1,12 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rapuncel"
3
- s.version = "0.0.1.alpha"
4
- s.date = "2010-12-02"
3
+ s.version = "0.0.1"
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'
7
7
  s.summary = "Simple XML-RPC Client"
8
8
  s.homepage = "http://github.com/cice/rapuncel"
9
- s.description = "Rapuncel is a simple XML-RPC Client based on Nokogiri, thus provides a fast and easy way to interact with XML-RPC services."
9
+ s.description = "Simple XML-RPC Client"
10
10
 
11
11
  s.files = Dir["**/*"] -
12
12
  Dir["coverage/**/*"] -
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
16
16
  Dir["rcov/**/*"]
17
17
 
18
18
  s.add_dependency 'nokogiri'
19
+ s.add_dependency 'builder'
19
20
  s.add_dependency 'activesupport', '>= 3.0.0'
20
21
 
21
22
  s.add_development_dependency 'mocha'