restfulie 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +2 -2
- data/lib/restfulie/client/atom_media_type.rb +19 -2
- data/lib/restfulie/client/base.rb +36 -31
- data/lib/restfulie/client/cache.rb +103 -0
- data/lib/restfulie/client/entry_point.rb +19 -2
- data/lib/restfulie/client/extensions/http.rb +116 -0
- data/lib/restfulie/client/helper.rb +17 -0
- data/lib/restfulie/client/instance.rb +138 -114
- data/lib/restfulie/client/request_execution.rb +255 -65
- data/lib/restfulie/client/state.rb +18 -1
- data/lib/restfulie/client.rb +29 -4
- data/lib/restfulie/logger.rb +13 -0
- data/lib/restfulie/media_type.rb +25 -6
- data/lib/restfulie/media_type_control.rb +40 -1
- data/lib/restfulie/media_type_defaults.rb +19 -2
- data/lib/restfulie/server/atom_media_type.rb +18 -5
- data/lib/restfulie/server/base.rb +18 -1
- data/lib/restfulie/server/controller.rb +73 -20
- data/lib/restfulie/server/instance.rb +96 -44
- data/lib/restfulie/server/marshalling.rb +16 -0
- data/lib/restfulie/server/opensearch/description.rb +54 -0
- data/lib/restfulie/server/opensearch.rb +18 -0
- data/lib/restfulie/server/restfulie_controller.rb +44 -1
- data/lib/restfulie/server/transition.rb +32 -1
- data/lib/restfulie/unmarshalling.rb +84 -42
- data/lib/restfulie.rb +27 -2
- data/lib/vendor/jeokkarak/hashi.rb +23 -19
- data/lib/vendor/jeokkarak/jeokkarak.rb +16 -0
- metadata +18 -4
@@ -1,12 +1,183 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'restfulie/client/extensions/http'
|
19
|
+
|
1
20
|
module Restfulie
|
2
21
|
module Client
|
22
|
+
|
23
|
+
# extension to all answers that allows you to access the web response
|
24
|
+
module WebResponse
|
25
|
+
attr_accessor :web_response
|
26
|
+
end
|
27
|
+
|
28
|
+
# some error ocurred while processing the request
|
29
|
+
class ResponseError < Exception
|
30
|
+
end
|
31
|
+
|
32
|
+
# Handles response answered by servers by accessing the specific callback for a http response code.
|
33
|
+
module ResponseHandler
|
34
|
+
|
35
|
+
class << self
|
36
|
+
|
37
|
+
# registers a new callback for a specific range of response codes
|
38
|
+
#
|
39
|
+
# Restfulie::Client::ResponseHandler.register(400, 599) do |restfulie_response|
|
40
|
+
# # returns the original reponse object
|
41
|
+
# restfulie_response.response
|
42
|
+
# end
|
43
|
+
def register(min_code, max_code, &block)
|
44
|
+
(min_code..max_code).each do |code|
|
45
|
+
handlers[code] = block
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# callback that returns the http response object
|
50
|
+
def pure_response_return(restfulie_response)
|
51
|
+
restfulie_response.response
|
52
|
+
end
|
53
|
+
|
54
|
+
# callback that raises a ResponseError
|
55
|
+
def raise_error(restfulie_response)
|
56
|
+
raise Restfulie::Client::ResponseError.new(restfulie_response.response)
|
57
|
+
end
|
58
|
+
|
59
|
+
# callback that parses the response media type and body,
|
60
|
+
# returning a deserialized representation of the resource.
|
61
|
+
# note that this will also set the _came_from instance variable with the content type
|
62
|
+
# this resource was represented, in order to allow further requests to prefer this content type.
|
63
|
+
def parse_entity(restfulie_response)
|
64
|
+
response = restfulie_response.response
|
65
|
+
content_type = response.content_type
|
66
|
+
type = Restfulie::MediaType.type_for(content_type)
|
67
|
+
if content_type[-3,3]=="xml"
|
68
|
+
result = type.from_xml response.body
|
69
|
+
elsif content_type[-4,4]=="json"
|
70
|
+
result = type.from_json response.body
|
71
|
+
else
|
72
|
+
result = generic_parse_entity restfulie_response
|
73
|
+
end
|
74
|
+
result.instance_variable_set :@_came_from, content_type
|
75
|
+
result
|
76
|
+
end
|
77
|
+
|
78
|
+
# callback taht executes a GET request to the response Location header.
|
79
|
+
# this is the typical callback for 200 response codes.
|
80
|
+
def retrieve_resource_from_location(restfulie_response)
|
81
|
+
restfulie_response.type.from_web restfulie_response.response["Location"]
|
82
|
+
end
|
83
|
+
|
84
|
+
# given a restfulie response, extracts the response code and invoke the registered callback.
|
85
|
+
def handle(restfulie_response)
|
86
|
+
handlers[restfulie_response.response.code.to_i].call(restfulie_response)
|
87
|
+
end
|
88
|
+
|
89
|
+
def generic_parse_entity(restfulie_response)
|
90
|
+
response = restfulie_response.response
|
91
|
+
content_type = response.content_type
|
92
|
+
type = Restfulie::MediaType.type_for(content_type)
|
93
|
+
method = "from_#{content_type}".to_sym
|
94
|
+
raise Restfulie::UnsupportedContentType.new("unsupported content type '#{content_type}' because '#{type}.#{method.to_s}' was not found") unless type.respond_to? method
|
95
|
+
type.send(method, response.body)
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
def handlers
|
100
|
+
@handlers ||= {}
|
101
|
+
end
|
102
|
+
|
103
|
+
def register_func(min, max, proc)
|
104
|
+
register(min, max) { |r| proc.call(r) }
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
register_func( 100, 599, Proc.new{ |r| pure_response_return r} )
|
110
|
+
register_func( 200, 200, Proc.new{ |r| parse_entity r} )
|
111
|
+
register_func( 301, 301, Proc.new{ |r| retrieve_resource_from_location r} )
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
# TODO there should be a response for each method type
|
117
|
+
class Response
|
118
|
+
|
119
|
+
attr_reader :type, :response
|
120
|
+
|
121
|
+
def initialize(type, response)
|
122
|
+
@type = type
|
123
|
+
@response = response
|
124
|
+
end
|
125
|
+
|
126
|
+
# TODO remote_post can probably be moved, does not need to be on the object's class itself
|
127
|
+
# the expected_content_type is used in case a redirection takes place
|
128
|
+
def parse_post(expected_content_type)
|
129
|
+
code = @response.code
|
130
|
+
if code=="301" && @type.follows.moved_permanently? == :all
|
131
|
+
result = @type.remote_post_to(@response["Location"], @response.body)
|
132
|
+
enhance(result)
|
133
|
+
elsif code=="201"
|
134
|
+
Restfulie.at(@response["Location"]).accepts(expected_content_type).get
|
135
|
+
else
|
136
|
+
final_parse
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# gets a result object and enhances it with web response methods
|
141
|
+
# by extending WebResponse and defining the attribute web_response
|
142
|
+
def enhance(result)
|
143
|
+
@response.previous = result.web_response if result.respond_to? :web_response
|
144
|
+
result.extend Restfulie::Client::WebResponse
|
145
|
+
result.web_response = @response
|
146
|
+
result
|
147
|
+
end
|
148
|
+
|
149
|
+
# parses this response using the correct ResponseHandler and enhances it
|
150
|
+
def final_parse
|
151
|
+
enhance Restfulie::Client::ResponseHandler.handle(@response)
|
152
|
+
end
|
153
|
+
|
154
|
+
# detects which type of method invocation it was and act accordingly
|
155
|
+
# TODO this should be called by RequestExcution, not instance
|
156
|
+
def parse(method, invoking_object, content_type)
|
157
|
+
|
158
|
+
return enhance(invoking_object) if @response.code == "304"
|
159
|
+
|
160
|
+
# return block.call(@response) if block
|
161
|
+
|
162
|
+
return final_parse if method == Net::HTTP::Get
|
163
|
+
return parse_post(content_type) if method == Net::HTTP::Post
|
164
|
+
final_parse
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
3
169
|
|
4
170
|
class RequestExecution
|
5
171
|
|
6
172
|
def initialize(type)
|
173
|
+
initialize(type, nil)
|
174
|
+
end
|
175
|
+
|
176
|
+
def initialize(type, invoking_object)
|
7
177
|
@type = type
|
8
178
|
@content_type = "application/xml"
|
9
179
|
@accepts = "application/xml"
|
180
|
+
@invoking_object = invoking_object
|
10
181
|
end
|
11
182
|
|
12
183
|
def at(uri)
|
@@ -26,12 +197,51 @@ module Restfulie
|
|
26
197
|
@accepts = content_type
|
27
198
|
self
|
28
199
|
end
|
200
|
+
|
201
|
+
def with(headers)
|
202
|
+
@headers = headers
|
203
|
+
self
|
204
|
+
end
|
29
205
|
|
30
206
|
# asks to create this content on the server (post it)
|
31
207
|
def create(content)
|
32
208
|
post(content)
|
33
209
|
end
|
210
|
+
|
211
|
+
# executes an http request using the specified verb
|
212
|
+
#
|
213
|
+
# example:
|
214
|
+
# do(Net::HTTP::Get, 'self', nil)
|
215
|
+
# do(Net::HTTP::Post, 'payment', '<payment/>')
|
216
|
+
def do(verb, relation_name, body = nil)
|
217
|
+
url, http_request = prepare_request(verb, relation_name, body)
|
218
|
+
response = execute_request(url, http_request)
|
219
|
+
Restfulie::Client::Response.new(@type, response).parse(verb, @invoking_object, "application/xml")
|
220
|
+
end
|
221
|
+
|
222
|
+
private
|
223
|
+
def execute_request(url, http_request)
|
224
|
+
cached = Restfulie.cache_provider.get(url, http_request)
|
225
|
+
return cached if cached
|
34
226
|
|
227
|
+
response = Net::HTTP.new(url.host, url.port).request(http_request)
|
228
|
+
Restfulie.cache_provider.put(url, http_request, response)
|
229
|
+
end
|
230
|
+
|
231
|
+
public
|
232
|
+
|
233
|
+
def prepare_request(verb, relation_name, body = nil)
|
234
|
+
url = URI.parse(@uri)
|
235
|
+
req = verb.new(url.path)
|
236
|
+
add_basic_request_headers(req, relation_name)
|
237
|
+
|
238
|
+
if body
|
239
|
+
req.body = body
|
240
|
+
req.add_field("Content-type", "application/xml") if req.get_fields("Content-type").nil?
|
241
|
+
end
|
242
|
+
[url, req]
|
243
|
+
end
|
244
|
+
|
35
245
|
# post this content to the server
|
36
246
|
def post(content)
|
37
247
|
remote_post_to(@uri, content)
|
@@ -41,6 +251,48 @@ module Restfulie
|
|
41
251
|
def get(options = {})
|
42
252
|
from_web(@uri, options)
|
43
253
|
end
|
254
|
+
|
255
|
+
def add_headers_to(hash)
|
256
|
+
hash[:headers] = {} unless hash[:headers]
|
257
|
+
hash[:headers]["Content-type"] = @content_type
|
258
|
+
hash[:headers]["Accept"] = @accepts
|
259
|
+
hash
|
260
|
+
end
|
261
|
+
|
262
|
+
def change_to_state(name, args)
|
263
|
+
if !args.empty? && args[args.size-1].kind_of?(Hash)
|
264
|
+
add_headers_to(args[args.size-1])
|
265
|
+
else
|
266
|
+
args << add_headers_to({})
|
267
|
+
end
|
268
|
+
@invoking_object.invoke_remote_transition name, args
|
269
|
+
end
|
270
|
+
|
271
|
+
# invokes an existing relation or delegates to the existing definition of method_missing
|
272
|
+
def method_missing(name, *args)
|
273
|
+
if @invoking_object && @invoking_object.existing_relations[name.to_s]
|
274
|
+
change_to_state(name.to_s, args)
|
275
|
+
else
|
276
|
+
super(name, args)
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
def add_basic_request_headers(req, name = nil)
|
281
|
+
|
282
|
+
req.add_field("Accept", @accepts) unless @accepts.nil?
|
283
|
+
|
284
|
+
@headers.each do |key, value|
|
285
|
+
req.add_field(key, value)
|
286
|
+
end if @headers
|
287
|
+
|
288
|
+
req.add_field("Accept", @invoking_object._came_from) if req.get_fields("Accept")==["*/*"]
|
289
|
+
|
290
|
+
if @type && name && @type.is_self_retrieval?(name) && @invoking_object.respond_to?(:web_response)
|
291
|
+
req.add_field("If-None-Match", @invoking_object.web_response.etag) if !@invoking_object.web_response.etag.nil?
|
292
|
+
req.add_field("If-Modified-Since", @invoking_object.web_response.last_modified) if !@invoking_object.web_response.last_modified.nil?
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
44
296
|
|
45
297
|
private
|
46
298
|
def remote_post_to(uri, content)
|
@@ -52,78 +304,16 @@ module Restfulie
|
|
52
304
|
req.add_field("Content-type", @content_type)
|
53
305
|
|
54
306
|
response = Net::HTTP.new(url.host, url.port).request(req)
|
55
|
-
|
56
|
-
end
|
57
|
-
|
58
|
-
def parse_post_response(response, content)
|
59
|
-
code = response.code
|
60
|
-
if code=="301" && @type.follows.moved_permanently? == :all
|
61
|
-
remote_post_to(response["Location"], content)
|
62
|
-
elsif code=="201"
|
63
|
-
from_web(response["Location"], "Accept" => "application/xml")
|
64
|
-
else
|
65
|
-
response
|
66
|
-
end
|
307
|
+
Restfulie::Client::Response.new(@type, response).parse_post(@content_type)
|
67
308
|
end
|
68
309
|
|
69
310
|
def from_web(uri, options = {})
|
70
311
|
uri = URI.parse(uri)
|
71
312
|
req = Net::HTTP::Get.new(uri.path)
|
72
|
-
options.each
|
313
|
+
options.each { |key,value| req[key] = value }
|
73
314
|
add_basic_request_headers(req)
|
74
|
-
|
75
315
|
res = Net::HTTP.new(uri.host, uri.port).request(req)
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
private
|
80
|
-
|
81
|
-
def add_basic_request_headers(req)
|
82
|
-
req.add_field("Accept", @accepts) unless @accepts.nil?
|
83
|
-
end
|
84
|
-
|
85
|
-
# parses a get response.
|
86
|
-
# if the result code is 301, redirect
|
87
|
-
# otherwise, parses an ok response
|
88
|
-
def parse_get_response(res)
|
89
|
-
|
90
|
-
code = res.code
|
91
|
-
return from_web(res["Location"]) if code=="301"
|
92
|
-
parse_get_ok_response(res, code)
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
# parses a successful get response.
|
97
|
-
# parses the entity and add extra (response related) fields.
|
98
|
-
def parse_get_ok_response(res, code)
|
99
|
-
result = parse_get_entity(res, code)
|
100
|
-
add_extra_fields(result, res)
|
101
|
-
result
|
102
|
-
end
|
103
|
-
|
104
|
-
# add etag, last_modified and web_response fields to the resulting object
|
105
|
-
def add_extra_fields(result,res)
|
106
|
-
result.etag = res['Etag'] unless res['Etag'].nil?
|
107
|
-
result.last_modified = res['Last-Modified'] unless res['Last-Modified'].nil?
|
108
|
-
result.web_response = res
|
109
|
-
end
|
110
|
-
|
111
|
-
# returns an entity for a specific response
|
112
|
-
def parse_get_entity(res, code)
|
113
|
-
if code=="200"
|
114
|
-
content_type = res.content_type
|
115
|
-
type = Restfulie::MediaType.type_for(content_type)
|
116
|
-
if content_type[-3,3]=="xml"
|
117
|
-
result = type.from_xml res.body
|
118
|
-
elsif content_type[-4,4]=="json"
|
119
|
-
result = type.from_json res.body
|
120
|
-
else
|
121
|
-
raise Restfulie::UnsupportedContentType.new("unsupported content type '#{content_type}'")
|
122
|
-
end
|
123
|
-
result
|
124
|
-
else
|
125
|
-
res
|
126
|
-
end
|
316
|
+
Restfulie::Client::Response.new(@type, res).final_parse
|
127
317
|
end
|
128
318
|
|
129
319
|
end
|
@@ -1,3 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
1
18
|
module Restfulie
|
2
19
|
|
3
20
|
module Client
|
@@ -12,7 +29,7 @@ module Restfulie
|
|
12
29
|
|
13
30
|
# returns true if this resource has a state named name
|
14
31
|
def has_state(name)
|
15
|
-
!@
|
32
|
+
!@existing_relations[name].nil?
|
16
33
|
end
|
17
34
|
end
|
18
35
|
end
|
data/lib/restfulie/client.rb
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'restfulie/logger'
|
19
|
+
|
1
20
|
require 'net/http'
|
2
21
|
require 'uri'
|
3
22
|
require 'vendor/jeokkarak/jeokkarak'
|
@@ -10,9 +29,15 @@ require 'restfulie/client/helper'
|
|
10
29
|
require 'restfulie/client/instance'
|
11
30
|
require 'restfulie/client/request_execution'
|
12
31
|
require 'restfulie/client/state'
|
32
|
+
require 'restfulie/client/cache'
|
33
|
+
require 'restfulie/unmarshalling'
|
13
34
|
|
14
35
|
module Restfulie
|
15
36
|
|
37
|
+
class << self
|
38
|
+
attr_accessor :cache_provider
|
39
|
+
end
|
40
|
+
|
16
41
|
# Extends your class to support restfulie-client side's code.
|
17
42
|
# This will extends Restfulie::Client::Base methods as class methods,
|
18
43
|
# Restfulie::Client::Instance as instance methods and Restfulie::Unmarshalling as class methods.
|
@@ -26,10 +51,10 @@ end
|
|
26
51
|
|
27
52
|
Object.extend Restfulie
|
28
53
|
|
29
|
-
|
54
|
+
include ActiveSupport::CoreExtensions::Hash
|
30
55
|
|
31
|
-
|
32
|
-
class CustomHash
|
56
|
+
class Hashi::CustomHash
|
33
57
|
uses_restfulie
|
34
|
-
end
|
35
58
|
end
|
59
|
+
|
60
|
+
Restfulie.cache_provider = Restfulie::BasicCache.new
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Restfulie
|
2
|
+
|
3
|
+
# Configure the logger used by Restfulie
|
4
|
+
#
|
5
|
+
# The logger defaults to ActiveSupport::BufferedLogger.new(STDOUT)
|
6
|
+
class << self
|
7
|
+
attr_accessor :logger
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
Restfulie.logger = ActiveSupport::BufferedLogger.new(STDOUT)
|
13
|
+
Restfulie.logger.level = Logger::DEBUG
|
data/lib/restfulie/media_type.rb
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
1
18
|
require 'restfulie/media_type_control'
|
2
19
|
|
3
20
|
module Restfulie
|
@@ -89,16 +106,10 @@ module Restfulie
|
|
89
106
|
|
90
107
|
def self.from_hash(hash)
|
91
108
|
|
92
|
-
# TODO atom media type from_xml on entry is not working correctly
|
93
|
-
# raise "there should be only one root element but got #{hash.keys}" unless hash.keys.size==1
|
94
|
-
|
95
109
|
type = Restfulie::MediaType.constantize(hash.keys.first.camelize) rescue Hashi
|
96
110
|
|
97
111
|
result = type.from_hash hash.values.first
|
98
112
|
return nil if result.nil?
|
99
|
-
if result.respond_to? :_came_from=
|
100
|
-
result._came_from = :xml
|
101
|
-
end
|
102
113
|
result
|
103
114
|
|
104
115
|
end
|
@@ -108,6 +119,14 @@ module Restfulie
|
|
108
119
|
type = hash.keys.first.camelize.constantize
|
109
120
|
type.from_hash(hash.values.first)
|
110
121
|
end
|
122
|
+
|
123
|
+
def self.from_html(body)
|
124
|
+
Hashi::CustomHash.new :body => body
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.from_xhtml(body)
|
128
|
+
Hashi::CustomHash.new :body => body
|
129
|
+
end
|
111
130
|
|
112
131
|
end
|
113
132
|
end
|
@@ -1,3 +1,32 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
|
17
|
+
# extends Rails mime type
|
18
|
+
|
19
|
+
module Mime
|
20
|
+
class << self
|
21
|
+
# alias_method :old_const_set, :const_set
|
22
|
+
|
23
|
+
# ignores setting the contest again
|
24
|
+
# def const_set(a,b)
|
25
|
+
# super(a,b) unless Mime.const_defined?(a)
|
26
|
+
# end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
1
30
|
module Restfulie
|
2
31
|
|
3
32
|
module MediaTypeControl
|
@@ -31,12 +60,22 @@ module Restfulie
|
|
31
60
|
end
|
32
61
|
|
33
62
|
|
63
|
+
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
|
64
|
+
SET << Mime.const_get(symbol.to_s.upcase)
|
65
|
+
|
66
|
+
([string] + mime_type_synonyms).each { |string| LOOKUP[string] = SET.last } unless skip_lookup
|
67
|
+
([symbol.to_s] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext] = SET.last }
|
68
|
+
end
|
69
|
+
|
34
70
|
module MediaType
|
35
71
|
|
36
72
|
class << self
|
37
73
|
|
38
74
|
def register(type)
|
39
|
-
|
75
|
+
silence_warnings do
|
76
|
+
Mime::Type.register(type.name, type.short_name.to_sym)
|
77
|
+
end
|
78
|
+
|
40
79
|
media_types[type.name] = type
|
41
80
|
end
|
42
81
|
|
@@ -1,11 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
1
18
|
module Restfulie
|
2
19
|
|
3
20
|
module MediaType
|
4
21
|
def self.HtmlType
|
5
|
-
custom_type('html',
|
22
|
+
custom_type('html', DefaultMediaTypeDecoder, lambda {})
|
6
23
|
end
|
7
24
|
def self.TextHtmlType
|
8
|
-
custom_type('text/html',
|
25
|
+
custom_type('text/html', DefaultMediaTypeDecoder, lambda {})
|
9
26
|
end
|
10
27
|
|
11
28
|
# TODO rename it and move it
|
@@ -1,3 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
1
18
|
module Restfulie
|
2
19
|
|
3
20
|
module Server
|
@@ -69,11 +86,7 @@ class AtomFeed
|
|
69
86
|
end
|
70
87
|
|
71
88
|
def updated_at
|
72
|
-
|
73
|
-
@feed.each do |item|
|
74
|
-
last = item.updated_at if item.respond_to?(:updated_at) && (last.nil? || item.updated_at > last)
|
75
|
-
end
|
76
|
-
last || Time.now
|
89
|
+
@feed.updated_at
|
77
90
|
end
|
78
91
|
|
79
92
|
def items_to_atom_xml(controller, serializer = nil)
|
@@ -1,7 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
1
18
|
module Restfulie
|
2
19
|
module Server
|
3
20
|
module Base
|
4
|
-
|
21
|
+
|
5
22
|
# returns the definition for the transaction
|
6
23
|
def existing_transition(name)
|
7
24
|
transitions[name]
|