rackful 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/example/config.ru +11 -10
- data/lib/rackful.rb +9 -5
- data/lib/rackful/global.rb +12 -0
- data/lib/rackful/httpstatus.rb +50 -51
- data/lib/rackful/middleware.rb +5 -0
- data/lib/rackful/middleware/headerspoofing.rb +7 -1
- data/lib/rackful/middleware/methodoverride.rb +8 -2
- data/lib/rackful/parser.rb +80 -101
- data/lib/rackful/request.rb +100 -129
- data/lib/rackful/resource.rb +263 -207
- data/lib/rackful/serializer.rb +46 -17
- data/lib/rackful/server.rb +25 -33
- data/lib/rackful/uri.rb +8 -0
- data/rackful.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3ca6f8649b19811edf97934421a559a7737c0e4
|
4
|
+
data.tar.gz: 7ca6cbcbd870d257c2e05de94ff612b43802bbf7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebe348706302e4f09e1cc9670135f87ab8092b397514fa049164cd0e6a9880d3418c1c1f456d9e8a54aac9f650b297bc0ff76a8ea10275eeafd2d28e4a49315a
|
7
|
+
data.tar.gz: dc046d625255efb54558810c9069ee89856963fac75b1672b7b3877dc5ff4647ffdd3937d086d509479b91ccecffc6e67111582021458f88bd02d1e401a39d31
|
data/example/config.ru
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
# Load core functionality:
|
2
2
|
require 'rackful'
|
3
3
|
|
4
|
+
|
4
5
|
# Load extra middlewares: ({Rackful::MethodOverride}, {Rackful::HeaderSpoofing})
|
5
6
|
require 'rackful/middleware'
|
6
|
-
|
7
7
|
require 'digest/md5'
|
8
8
|
|
9
|
+
|
9
10
|
# The class of the object we're going to serve:
|
10
|
-
class
|
11
|
-
|
11
|
+
class MyResource
|
12
|
+
include Rackful::Resource
|
13
|
+
attr_accessor :to_rackful
|
14
|
+
|
12
15
|
def initialize
|
13
|
-
|
16
|
+
self.uri = '/hello_world'
|
14
17
|
@to_rackful = {
|
15
18
|
:a => 'Hello',
|
16
19
|
:b => Time.now,
|
17
|
-
:c => URI('http://www.example.com/some/path')
|
18
|
-
|
19
|
-
def do_PUT request, response
|
20
|
-
@to_rackful = self.parser(request).parse
|
20
|
+
:c => URI('http://www.example.com/some/path')
|
21
|
+
}
|
21
22
|
end
|
23
|
+
|
22
24
|
def get_etag
|
23
25
|
'"' + Digest::MD5.new.update(to_rackful.inspect).to_s + '"'
|
24
26
|
end
|
@@ -27,12 +29,11 @@ class Root < Rackful::Resource
|
|
27
29
|
add_parser Rackful::Parser::XHTML
|
28
30
|
add_parser Rackful::Parser::JSON
|
29
31
|
end
|
30
|
-
$root_resource = nil
|
31
32
|
|
32
33
|
use Rack::Reloader
|
33
34
|
use Rackful::MethodOverride
|
34
35
|
use Rackful::HeaderSpoofing
|
35
36
|
|
36
37
|
run Rackful::Server.new { |uri|
|
37
|
-
$root_resource ||=
|
38
|
+
$root_resource ||= MyResource.new
|
38
39
|
}
|
data/lib/rackful.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# External requirements:
|
2
4
|
require 'nokogiri'
|
3
5
|
require 'rack'
|
4
6
|
require 'rack/utils'
|
@@ -6,10 +8,12 @@ require 'base64'
|
|
6
8
|
require 'time'
|
7
9
|
require 'json'
|
8
10
|
|
9
|
-
|
10
|
-
require 'rackful/
|
11
|
-
require 'rackful/
|
11
|
+
# Internal “core” files, in alphabetic order:
|
12
|
+
require 'rackful/global.rb'
|
13
|
+
require 'rackful/httpstatus.rb'
|
12
14
|
require 'rackful/parser.rb'
|
15
|
+
require 'rackful/request.rb'
|
13
16
|
require 'rackful/resource.rb'
|
14
|
-
require 'rackful/
|
17
|
+
require 'rackful/serializer.rb'
|
15
18
|
require 'rackful/server.rb'
|
19
|
+
require 'rackful/uri.rb'
|
data/lib/rackful/httpstatus.rb
CHANGED
@@ -1,63 +1,58 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
# Required for parsing:
|
4
|
+
require 'rackful/global.rb'
|
3
5
|
require 'rackful/resource.rb'
|
4
6
|
require 'rackful/serializer.rb'
|
5
7
|
|
8
|
+
# Required for running:
|
6
9
|
|
7
10
|
module Rackful
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
# Groups together class {HTTPStatus} and its many subclasses into one namespace.
|
13
|
+
#
|
14
|
+
# For code brevity and legibility, this module is included in {Rackful},
|
15
|
+
# {Resource}, {Serializer}, and {Parser}. So class
|
16
|
+
# {HTTP404NotFound Rackful::StatusCodes::HTTP404NotFound}
|
17
|
+
# can also be addressed as {HTTP404NotFound} in any of those contexts.
|
18
|
+
module StatusCodes
|
14
19
|
|
20
|
+
# Exception which represents an HTTP Status response.
|
21
|
+
# @abstract
|
22
|
+
class HTTPStatus < RuntimeError
|
15
23
|
|
16
|
-
|
17
|
-
|
24
|
+
include Resource
|
25
|
+
|
26
|
+
class XHTML < Serializer::XHTML
|
18
27
|
|
19
28
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
retval
|
29
|
+
def header
|
30
|
+
retval = super
|
31
|
+
retval += "<h1>HTTP/1.1 #{Rack::Utils.escape_html(resource.title)}</h1>\n"
|
32
|
+
unless resource.message.empty?
|
33
|
+
retval += "<div id=\"rackful-description\">#{resource.message}</div>\n"
|
27
34
|
end
|
35
|
+
retval
|
36
|
+
end
|
28
37
|
|
29
38
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end # class Rackful::HTTPStatus::XHTML
|
34
|
-
|
35
|
-
|
36
|
-
add_serializer XHTML, 1.0
|
37
|
-
|
38
|
-
extend Forwardable
|
39
|
-
def_delegators :@http_status_object, :headers, :to_rackful, :title, :message
|
40
|
-
|
39
|
+
def headers; self.resource.headers; end
|
41
40
|
|
42
|
-
def initialize(uri, http_status_object)
|
43
|
-
super(uri)
|
44
|
-
@http_status_object = http_status_object
|
45
|
-
end
|
46
41
|
|
42
|
+
end # class Rackful::StatusCodes::HTTPStatus::XHTML
|
47
43
|
|
48
|
-
end # class Rackful::HTTPStatus::Resource
|
49
44
|
|
45
|
+
add_serializer XHTML, 1.0
|
46
|
+
add_serializer Serializer::JSON, 0.5
|
50
47
|
|
51
48
|
attr_reader :status, :headers, :to_rackful
|
52
49
|
|
53
50
|
|
54
|
-
|
55
|
-
@param
|
56
|
-
@param
|
57
|
-
|
58
|
-
|
59
|
-
* **Strings** indexed by **Strings** are returned as response headers.
|
60
|
-
=end
|
51
|
+
# @param status [Symbol, Integer] e.g. `404` or `:not_found`
|
52
|
+
# @param message [String] XHTML
|
53
|
+
# @param info [ { Symbol => Object, String => String } ]
|
54
|
+
# * **Objects** indexed by **Symbols** are returned in the response body.
|
55
|
+
# * **Strings** indexed by **Strings** are returned as response headers.
|
61
56
|
def initialize status, message = nil, info = {}
|
62
57
|
@status = Rack::Utils.status_code status
|
63
58
|
raise "Wrong status: #{status}" if 0 === @status
|
@@ -86,24 +81,20 @@ class HTTPStatus < RuntimeError
|
|
86
81
|
end
|
87
82
|
super message
|
88
83
|
end
|
89
|
-
|
90
|
-
def serializer request
|
91
|
-
Resource.new( request.url, self ).serializer( request )
|
92
|
-
end
|
93
84
|
|
85
|
+
|
86
|
+
# @api private
|
94
87
|
def title
|
95
88
|
"#{status} #{Rack::Utils::HTTP_STATUS_CODES[status]}"
|
96
89
|
end
|
97
90
|
|
98
91
|
|
99
92
|
|
100
|
-
end # class Rackful::HTTPStatus
|
93
|
+
end # class Rackful::StatusCodes::HTTPStatus
|
101
94
|
|
102
95
|
|
103
|
-
|
104
|
-
|
105
|
-
no message at all.
|
106
|
-
=end
|
96
|
+
# @abstract Base class for HTTP status codes with only a simple text message, or
|
97
|
+
# no message at all.
|
107
98
|
class HTTPSimpleStatus < HTTPStatus
|
108
99
|
|
109
100
|
def initialize message = nil
|
@@ -117,9 +108,12 @@ end
|
|
117
108
|
|
118
109
|
class HTTP201Created < HTTPStatus
|
119
110
|
|
111
|
+
# @param locations [URI::Generic, String, Array<URI::Generic, String>]
|
120
112
|
def initialize locations
|
121
113
|
locations = [ locations ] unless locations.kind_of? Array
|
122
|
-
locations = locations.collect
|
114
|
+
locations = locations.collect do |location|
|
115
|
+
location.kind_of?( URI::Generic ) ? location : URI(location).normalize
|
116
|
+
end
|
123
117
|
if locations.size > 1
|
124
118
|
super( 201, 'New resources were created:', :locations => locations )
|
125
119
|
else
|
@@ -136,9 +130,10 @@ end
|
|
136
130
|
|
137
131
|
class HTTP202Accepted < HTTPStatus
|
138
132
|
|
133
|
+
# @param location [URI::Generic, String]
|
139
134
|
def initialize location = nil
|
140
135
|
if location
|
141
|
-
location = URI(location)
|
136
|
+
location = location.kind_of?( URI::Generic ) ? location : URI(location).normalize
|
142
137
|
super(
|
143
138
|
202, "The request body you sent has been accepted for processing.",
|
144
139
|
:"Job status location:" => location, 'Location' => location
|
@@ -153,8 +148,9 @@ end
|
|
153
148
|
|
154
149
|
class HTTP301MovedPermanently < HTTPStatus
|
155
150
|
|
151
|
+
# @param location [URI::Generic, String]
|
156
152
|
def initialize location
|
157
|
-
location = URI(location)
|
153
|
+
location = location.kind_of?( URI::Generic ) ? location : URI(location).normalize
|
158
154
|
super( 301, '', :'New location:' => location, 'Location' => location )
|
159
155
|
end
|
160
156
|
|
@@ -163,8 +159,9 @@ end
|
|
163
159
|
|
164
160
|
class HTTP303SeeOther < HTTPStatus
|
165
161
|
|
162
|
+
# @param location [URI::Generic, String]
|
166
163
|
def initialize location
|
167
|
-
location = URI(location)
|
164
|
+
location = location.kind_of?( URI::Generic ) ? location : URI(location).normalize
|
168
165
|
super( 303, '', :'See:' => location, 'Location' => location )
|
169
166
|
end
|
170
167
|
|
@@ -182,8 +179,9 @@ end
|
|
182
179
|
|
183
180
|
class HTTP307TemporaryRedirect < HTTPStatus
|
184
181
|
|
182
|
+
# @param location [URI::Generic, String]
|
185
183
|
def initialize location
|
186
|
-
location = URI(location)
|
184
|
+
location = location.kind_of?( URI::Generic ) ? location : URI(location).normalize
|
187
185
|
super( 301, '', :'Current location:' => location, 'Location' => location )
|
188
186
|
end
|
189
187
|
|
@@ -247,4 +245,5 @@ class HTTP501NotImplemented < HTTPSimpleStatus; end
|
|
247
245
|
|
248
246
|
class HTTP503ServiceUnavailable < HTTPSimpleStatus; end
|
249
247
|
|
248
|
+
end # module Rackful::StatusCodes
|
250
249
|
end # module Rackful
|
data/lib/rackful/middleware.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
# Required for parsing:
|
4
|
+
|
5
|
+
# This requirement is only made explicit in source files that aren’t
|
6
|
+
# included in the rackful “core”.
|
3
7
|
require 'rackful'
|
4
8
|
|
5
9
|
# Required for running:
|
6
10
|
|
11
|
+
module Rackful
|
7
12
|
|
8
13
|
# Rack middleware that provides header spoofing.
|
9
14
|
#
|
@@ -18,7 +23,7 @@ require 'rackful'
|
|
18
23
|
# @example Using this middleware
|
19
24
|
# require 'rackful/middleware/header_spoofing'
|
20
25
|
# use Rackful::HeaderSpoofing
|
21
|
-
class
|
26
|
+
class HeaderSpoofing
|
22
27
|
|
23
28
|
def initialize app
|
24
29
|
@app = app
|
@@ -47,3 +52,4 @@ def call env
|
|
47
52
|
end
|
48
53
|
|
49
54
|
end # Rackful::HeaderSpoofing
|
55
|
+
end # module Rackful
|
@@ -1,9 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
|
2
3
|
# Required for parsing:
|
4
|
+
|
5
|
+
# This requirement is only made explicit in source files that aren’t
|
6
|
+
# included in the rackful “core”.
|
3
7
|
require 'rackful'
|
4
8
|
|
5
9
|
# Required for running:
|
6
|
-
|
10
|
+
|
11
|
+
module Rackful
|
7
12
|
|
8
13
|
|
9
14
|
# Middleware that provides method spoofing, like {Rack::MethodOverride}.
|
@@ -47,7 +52,7 @@ require 'set'
|
|
47
52
|
# @example Using this middleware
|
48
53
|
# require 'rackful/middleware/method_override'
|
49
54
|
# use Rackful::MethodOverride
|
50
|
-
class
|
55
|
+
class MethodOverride
|
51
56
|
|
52
57
|
METHOD_OVERRIDE_PARAM_KEY = '_method'.freeze
|
53
58
|
|
@@ -134,3 +139,4 @@ class Rackful::MethodOverride
|
|
134
139
|
end
|
135
140
|
|
136
141
|
end # Rackful::MethodOverride
|
142
|
+
end # module Rackful
|
data/lib/rackful/parser.rb
CHANGED
@@ -1,77 +1,80 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# Required for parsing:
|
4
|
+
require 'rackful/global.rb'
|
3
5
|
|
4
|
-
|
6
|
+
# Required for running:
|
5
7
|
|
8
|
+
module Rackful
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
# Base class for all concrete parsers defined in this library. You’ll probably
|
11
|
+
# want to use this class as the base class for your own parsers, too.
|
12
|
+
#
|
13
|
+
# This class mixes in module `StatusCodes` for convenience, as explained in the
|
14
|
+
# {StatusCodes StatusCodes documentation}.
|
15
|
+
# @abstract Subclasses must implement classmethod `::parse` with signature
|
16
|
+
# `(void) parse( Request, Response, Resource )`
|
17
|
+
# explained in {Resource::ClassMethods::add_parser}
|
18
|
+
# @example Subclassing this class
|
19
|
+
# class MyTextParser < Rackful::Parser
|
20
|
+
# parses 'text/*', 'application/xhtml+xml'
|
21
|
+
# def self.parse request, response, resource
|
22
|
+
# # YOUR CODE HERE...
|
23
|
+
# end
|
24
|
+
# end
|
19
25
|
class Parser
|
26
|
+
include StatusCodes
|
27
|
+
class << self
|
28
|
+
# @api private
|
29
|
+
def media_types
|
30
|
+
@media_types ||= begin
|
31
|
+
retval = rackful_parser_media_types
|
32
|
+
if superclass.respond_to?(:media_types)
|
33
|
+
retval += superclass.media_types
|
34
|
+
end
|
35
|
+
retval.uniq
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @overload parses( media_type, ... )
|
40
|
+
# @param media_type [String]
|
41
|
+
def parses *args
|
42
|
+
rackful_parser_media_types.unshift(
|
43
|
+
*( args.map { |mt| mt.to_s }.reverse )
|
44
|
+
)
|
45
|
+
rackful_parser_media_types.uniq!
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def rackful_parser_media_types
|
51
|
+
@rackful_parser_media_types ||= []
|
52
|
+
end
|
53
|
+
end # class << self # Rackful::Parser
|
20
54
|
|
55
|
+
end # class Rackful::Parser
|
21
56
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
=end
|
26
|
-
|
27
|
-
|
28
|
-
# @return [Request]
|
29
|
-
attr_reader :request
|
30
|
-
# @return [Resource]
|
31
|
-
attr_reader :resource
|
32
|
-
|
33
|
-
|
34
|
-
=begin markdown
|
35
|
-
@param request [Request]
|
36
|
-
@param resource [Resource]
|
37
|
-
=end
|
38
|
-
def initialize request, resource
|
39
|
-
@request, @resource = request, resource
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
|
-
end # class Parser
|
44
|
-
|
45
|
-
|
46
|
-
=begin markdown
|
47
|
-
Parent class of all XML-parsing parsers.
|
48
|
-
@abstract
|
49
|
-
@since 0.2.0
|
50
|
-
=end
|
57
|
+
# Parent class of all XML-parsing parsers.
|
58
|
+
# @abstract
|
59
|
+
# @since 0.2.0
|
51
60
|
class Parser::DOM < Parser
|
52
61
|
|
62
|
+
# The media types parsed by this parser.
|
63
|
+
# @see Parser
|
64
|
+
parses 'text/xml', 'application/xml'
|
53
65
|
|
54
|
-
=begin markdown
|
55
|
-
The media types parsed by this parser.
|
56
|
-
@see Parser
|
57
|
-
=end
|
58
|
-
MEDIA_TYPES = [
|
59
|
-
'text/xml',
|
60
|
-
'application/xml'
|
61
|
-
]
|
62
66
|
|
67
|
+
def self.parse request, response, resource
|
68
|
+
self.new(request).parse( response, resource )
|
69
|
+
end
|
63
70
|
|
64
|
-
|
65
|
-
@return [Nokogiri::XML::Document]
|
66
|
-
=end
|
71
|
+
# @return [Nokogiri::XML::Document]
|
67
72
|
attr_reader :document
|
73
|
+
attr_reader :request
|
68
74
|
|
69
|
-
|
70
|
-
|
71
|
-
@
|
72
|
-
=end
|
73
|
-
def initialize request, resource
|
74
|
-
super request, resource
|
75
|
+
# @raise [HTTP400BadRequest] if the document is malformed.
|
76
|
+
def initialize request
|
77
|
+
@request = request
|
75
78
|
# TODO Is ISO-8859-1 indeed the default encoding for XML documents? If so,
|
76
79
|
# that fact must be documented and referenced.
|
77
80
|
encoding = self.request.media_type_params['charset'] || 'ISO-8859-1'
|
@@ -88,31 +91,21 @@ The media types parsed by this parser.
|
|
88
91
|
end
|
89
92
|
raise( HTTP400BadRequest, $!.to_s ) unless @document.root
|
90
93
|
end
|
94
|
+
|
95
|
+
end # class Rackful::Parser::DOM
|
91
96
|
|
92
97
|
|
93
|
-
end # class Parser::DOM
|
94
98
|
|
95
99
|
|
96
|
-
|
97
|
-
Parses XHTML as generated by {Serializer::XHTML}.
|
98
|
-
=end
|
100
|
+
# Parses XHTML as generated by {Serializer::XHTML}.
|
99
101
|
class Parser::XHTML < Parser::DOM
|
100
102
|
|
101
103
|
|
102
|
-
|
103
|
-
The media types parsed by this parser.
|
104
|
-
@see Parser
|
105
|
-
=end
|
106
|
-
MEDIA_TYPES = Parser::DOM::MEDIA_TYPES + [
|
107
|
-
'application/xhtml+xml',
|
108
|
-
'text/html'
|
109
|
-
]
|
104
|
+
parses 'application/xhtml+xml', 'text/html'
|
110
105
|
|
111
106
|
|
112
|
-
|
113
|
-
|
114
|
-
=end
|
115
|
-
def parse
|
107
|
+
# @see Parser#parse
|
108
|
+
def parse response, resource
|
116
109
|
# Try to find the actual content:
|
117
110
|
content = self.document.root.xpath(
|
118
111
|
'//html:div[@id="rackful-content"]',
|
@@ -139,13 +132,11 @@ The media types parsed by this parser.
|
|
139
132
|
end
|
140
133
|
end
|
141
134
|
# Parse the f*cking thing:
|
142
|
-
self.parse_recursive content.first
|
135
|
+
resource.to_rackful = self.parse_recursive content.first
|
143
136
|
end
|
144
137
|
|
145
138
|
|
146
|
-
|
147
|
-
@api private
|
148
|
-
=end
|
139
|
+
# @api private
|
149
140
|
def parse_recursive node
|
150
141
|
|
151
142
|
# A URI:
|
@@ -181,9 +172,7 @@ The media types parsed by this parser.
|
|
181
172
|
end
|
182
173
|
|
183
174
|
|
184
|
-
|
185
|
-
@api private
|
186
|
-
=end
|
175
|
+
# @api private
|
187
176
|
def parse_simple_type node, typename
|
188
177
|
case typename
|
189
178
|
when 'boolean'
|
@@ -208,9 +197,7 @@ The media types parsed by this parser.
|
|
208
197
|
end
|
209
198
|
|
210
199
|
|
211
|
-
|
212
|
-
@api private
|
213
|
-
=end
|
200
|
+
# @api private
|
214
201
|
def parse_object node
|
215
202
|
current_property = nil
|
216
203
|
r = {}
|
@@ -234,9 +221,7 @@ The media types parsed by this parser.
|
|
234
221
|
end
|
235
222
|
|
236
223
|
|
237
|
-
|
238
|
-
@api private
|
239
|
-
=end
|
224
|
+
# @api private
|
240
225
|
def parse_object_list node
|
241
226
|
properties = node.xpath(
|
242
227
|
'html:thead/html:tr/html:th',
|
@@ -273,22 +258,18 @@ end # class Parser::XHTML
|
|
273
258
|
class Parser::JSON < Parser
|
274
259
|
|
275
260
|
|
276
|
-
|
277
|
-
'application/json',
|
278
|
-
'application/x-json'
|
279
|
-
]
|
261
|
+
parses 'application/json', 'application/x-json'
|
280
262
|
|
281
|
-
|
282
|
-
def parse
|
263
|
+
def self.parse request, response, resource
|
283
264
|
r = ::JSON.parse(
|
284
|
-
|
265
|
+
request.env['rack.input'].read,
|
285
266
|
:symbolize_names => true
|
286
267
|
)
|
287
|
-
self.recursive_datetime_parser r
|
268
|
+
resource.to_rackful = self.recursive_datetime_parser r
|
288
269
|
end
|
289
270
|
|
290
271
|
|
291
|
-
def recursive_datetime_parser p
|
272
|
+
def self.recursive_datetime_parser p
|
292
273
|
if p.kind_of?(String)
|
293
274
|
begin
|
294
275
|
return Time.xmlschema(p)
|
@@ -297,12 +278,12 @@ class Parser::JSON < Parser
|
|
297
278
|
elsif p.kind_of?(Hash)
|
298
279
|
p.keys.each do
|
299
280
|
|key|
|
300
|
-
p[key] =
|
281
|
+
p[key] = recursive_datetime_parser( p[key] )
|
301
282
|
end
|
302
283
|
elsif p.kind_of?(Array)
|
303
284
|
(0 ... p.size).each do
|
304
285
|
|i|
|
305
|
-
p[i] =
|
286
|
+
p[i] = recursive_datetime_parser( p[i] )
|
306
287
|
end
|
307
288
|
end
|
308
289
|
p
|
@@ -310,6 +291,4 @@ class Parser::JSON < Parser
|
|
310
291
|
|
311
292
|
|
312
293
|
end # class Parser::JSON
|
313
|
-
|
314
|
-
|
315
294
|
end # module Rackful
|