restfulie 0.5.0 → 0.6.0
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.
- 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]
|