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,35 +1,88 @@
|
|
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
|
+
module Restfulie::Server::Cache
|
18
|
+
|
19
|
+
class Config
|
20
|
+
|
21
|
+
def allow(seconds)
|
22
|
+
@max_age = seconds
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def max_age
|
27
|
+
@max_age ||= 0
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
1
32
|
module ActionController
|
2
33
|
class Base
|
3
|
-
|
34
|
+
|
35
|
+
def self.cache
|
36
|
+
@cache_config ||= Restfulie::Server::Cache::Config.new
|
37
|
+
end
|
38
|
+
|
4
39
|
# renders an specific resource to xml
|
5
40
|
# using any extra options to render it (invoke to_xml).
|
6
41
|
def render_resource(resource, options = {}, render_options = {})
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
42
|
+
|
43
|
+
response.headers['Cache-control'] = "max-age=#{self.class.cache.max_age}"
|
44
|
+
return nil unless stale? resource.cache_info
|
45
|
+
|
46
|
+
return render(render_options) if render_options[:text]
|
47
|
+
|
48
|
+
options[:controller] = self
|
49
|
+
respond_to do |format|
|
50
|
+
add_media_responses(format, resource, options, render_options)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
# renders a resource collection, making full use of atom support
|
56
|
+
def render_collection(collection, &block)
|
57
|
+
if block
|
58
|
+
content = collection.to_atom(:title =>collection_name, :controller => self) do |item|
|
59
|
+
block.call item
|
14
60
|
end
|
61
|
+
else
|
62
|
+
content = collection.to_atom(:title => collection_name, :controller => self)
|
15
63
|
end
|
64
|
+
render_resource collection, nil, {:content_type => 'application/atom+xml', :text => content}
|
16
65
|
end
|
17
66
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
types = resource.class.media_types if resource.class.respond_to? :media_types
|
22
|
-
types.each do |media_type|
|
23
|
-
add_media_response(format, resource, media_type, options, render_options)
|
67
|
+
# returns the name of this controllers collection
|
68
|
+
def collection_name
|
69
|
+
self.class.name[/(.*)Controller/,1]
|
24
70
|
end
|
25
|
-
end
|
26
71
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
72
|
+
def add_media_responses(format, resource, options, render_options)
|
73
|
+
types = Restfulie::MediaType.default_types
|
74
|
+
types = resource.class.media_types if resource.class.respond_to? :media_types
|
75
|
+
types.each do |media_type|
|
76
|
+
add_media_response(format, resource, media_type, options, render_options)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def add_media_response(format, resource, media_type, options, render_options)
|
81
|
+
controller = self
|
82
|
+
format.send media_type.short_name.to_sym do
|
83
|
+
media_type.execute_for(controller, resource, options, render_options)
|
84
|
+
end
|
31
85
|
end
|
32
|
-
end
|
33
86
|
|
34
87
|
# adds support to rendering resources, i.e.:
|
35
88
|
# render :resource => @order, :with => { :except => [:paid_at] }
|
@@ -1,50 +1,102 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
t = Restfulie::Server::Transition.new(t[0], t[1], t[2], nil) if t.kind_of? Array
|
18
|
-
all << t
|
19
|
-
end
|
20
|
-
all
|
21
|
-
end
|
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
|
+
#
|
22
17
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
18
|
+
module Restfulie::Server::Cache
|
19
|
+
|
20
|
+
# returns specific cache information for this resource
|
21
|
+
# you may customize it and return a custom etag and last_modified fields
|
22
|
+
def cache_info
|
23
|
+
info = {:etag => self}
|
24
|
+
info[:etag] = self.etag if self.respond_to? :etag
|
25
|
+
info[:last_modified] = self.updated_at.utc if self.respond_to? :updated_at
|
26
|
+
info
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
# acts_as_restfulie instances implement this module
|
32
|
+
module Restfulie::Server::Instance
|
33
|
+
|
34
|
+
include Restfulie::Server::Cache
|
35
|
+
|
36
|
+
# checks whether this resource can execute a transition or has such a relation
|
37
|
+
def can?(what)
|
38
|
+
what = what.to_sym if what.kind_of? String
|
39
|
+
all_following_transitions.each do |t|
|
40
|
+
return true if t.name == what
|
41
|
+
end
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# returns a list of available transitions for this objects state
|
46
|
+
# TODO rename because it should never be used by the client...
|
47
|
+
def available_transitions
|
48
|
+
status_available = respond_to?(:status) && status!=nil
|
49
|
+
return {:allow => []} unless status_available
|
50
|
+
self.class.states[self.status.to_sym] || {:allow => []}
|
51
|
+
end
|
52
|
+
|
53
|
+
# returns a list containing all available transitions for this object's state
|
54
|
+
def all_following_transitions
|
55
|
+
all = [] + available_transitions[:allow]
|
56
|
+
following_transitions.each do |t|
|
57
|
+
t = Restfulie::Server::Transition.new(t) if t.kind_of? Array
|
58
|
+
all << t
|
59
|
+
end
|
60
|
+
all
|
61
|
+
end
|
40
62
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
63
|
+
# checks if its possible to execute such transition and, if it is, executes it
|
64
|
+
def move_to(name)
|
65
|
+
raise "Current state #{status} is invalid in order to execute #{name}. It must be one of #{transitions}" unless available_transitions[:allow].include? name
|
66
|
+
self.class.transitions[name].execute_at self
|
67
|
+
end
|
68
|
+
|
69
|
+
# gets all the links for each transition
|
70
|
+
def links(controller)
|
71
|
+
links = []
|
72
|
+
unless controller.nil?
|
73
|
+
all_following_transitions.each do |transition|
|
74
|
+
rel, uri = link_for(transition, controller)
|
75
|
+
links << {:rel => rel, :uri => uri}
|
46
76
|
end
|
77
|
+
end
|
78
|
+
links
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
# gets a link for this transition
|
83
|
+
def link_for(transition, controller)
|
84
|
+
transition = self.class.existing_transition(transition.to_sym) unless transition.kind_of? Restfulie::Server::Transition
|
85
|
+
transition.link_for(self, controller)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
class Array
|
91
|
+
|
92
|
+
include Restfulie::Server::Cache
|
47
93
|
|
94
|
+
def updated_at
|
95
|
+
last = nil
|
96
|
+
each do |item|
|
97
|
+
last = item.updated_at if item.respond_to?(:updated_at) && (last.nil? || item.updated_at > last)
|
48
98
|
end
|
99
|
+
last || Time.now
|
49
100
|
end
|
50
|
-
|
101
|
+
|
102
|
+
end
|
@@ -1,3 +1,19 @@
|
|
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
|
+
#
|
1
17
|
|
2
18
|
module Restfulie
|
3
19
|
|
@@ -0,0 +1,54 @@
|
|
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
|
+
module Restfulie
|
19
|
+
module OpenSearch
|
20
|
+
|
21
|
+
class Description
|
22
|
+
|
23
|
+
def self.define(attribute, xml_attribute)
|
24
|
+
|
25
|
+
define_method("#{attribute.to_s}=") do |new_value|
|
26
|
+
self.instance_variable_set(xml_attribute, new_value)
|
27
|
+
end
|
28
|
+
|
29
|
+
define_method(attribute.to_s) do |new_value|
|
30
|
+
self.instance_variable_get xml_attribute
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
define(:short_name, :@ShortName)
|
36
|
+
define(:description, :@Description)
|
37
|
+
define(:tags, :@Tags)
|
38
|
+
define(:contact, :@Contact)
|
39
|
+
|
40
|
+
def initialize(name)
|
41
|
+
short_name = name
|
42
|
+
description = name
|
43
|
+
@types = []
|
44
|
+
end
|
45
|
+
|
46
|
+
def accepts(content_type)
|
47
|
+
@types << content_type
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,18 @@
|
|
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/server/opensearch/description'
|
@@ -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
|
@@ -39,14 +56,40 @@ module Restfulie
|
|
39
56
|
head :ok
|
40
57
|
end
|
41
58
|
|
59
|
+
# updates a resouce
|
60
|
+
def update
|
61
|
+
type = model_type
|
62
|
+
|
63
|
+
@loaded = type.find(params[:id])
|
64
|
+
return head(:status => 405) unless @loaded.can? :update
|
65
|
+
|
66
|
+
return head(415) unless fits_content(type, request.headers['CONTENT_TYPE'])
|
67
|
+
|
68
|
+
@model = Hash.from_xml(request.body.string)[model_name]
|
69
|
+
pre_update(@model) if self.respond_to?(:pre_update)
|
70
|
+
|
71
|
+
if @loaded.update_attributes(@model)
|
72
|
+
render_resource @loaded
|
73
|
+
else
|
74
|
+
render :xml => @loaded.errors, :status => :unprocessable_entity
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
42
78
|
# returns the model for this controller
|
43
79
|
def model_type
|
44
80
|
self.class.name[/(.*)Controller/,1].singularize.constantize
|
45
81
|
end
|
82
|
+
|
83
|
+
# retrieves the model name
|
84
|
+
def model_name
|
85
|
+
self.class.name[/(.*)Controller/,1].singularize.underscore
|
86
|
+
end
|
46
87
|
|
47
88
|
def fits_content(type, content_type)
|
48
89
|
Restfulie::MediaType.supports?(content_type) &&
|
49
|
-
type.
|
90
|
+
(type.respond_to?(:media_type_representations) ?
|
91
|
+
type.media_type_representations.include?(content_type) :
|
92
|
+
Restfulie::MediaType.default_representations.include?(content_type))
|
50
93
|
end
|
51
94
|
|
52
95
|
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 Server
|
@@ -8,13 +25,27 @@ module Restfulie
|
|
8
25
|
attr_writer :options
|
9
26
|
attr_accessor :result
|
10
27
|
|
11
|
-
def initialize(
|
28
|
+
def initialize(*args)
|
29
|
+
args[0].kind_of?(Array) ? from_array(*args) : from(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
def from_array(array)
|
34
|
+
@name = array[0]
|
35
|
+
@options = array.length>0 ? array[1] : nil
|
36
|
+
@result = array.length>1 ? array[2] : nil
|
37
|
+
@body = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def from(name, options = {}, result = nil, body = nil)
|
12
41
|
@name = name
|
13
42
|
@options = options
|
14
43
|
@result = result
|
15
44
|
@body = body
|
16
45
|
end
|
17
46
|
|
47
|
+
public
|
48
|
+
|
18
49
|
def action
|
19
50
|
@options || {}
|
20
51
|
end
|
@@ -1,15 +1,31 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
#
|
4
|
-
# def initialize(h)
|
5
|
-
# @hash = h
|
6
|
-
# link = h['link']
|
7
|
-
# add_transitions([link]) if link.kind_of? Hash
|
8
|
-
# add_transitions(link) if link.kind_of? Array
|
9
|
-
# end
|
10
|
-
# end
|
11
|
-
# end
|
1
|
+
#
|
2
|
+
# Copyright (c) 2009 Caelum - www.caelum.com.br/opensource
|
3
|
+
# All rights reserved.
|
12
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
|
+
module Hashi
|
19
|
+
class CustomHash
|
20
|
+
def initialize(hash = {})
|
21
|
+
@internal_hash = hash
|
22
|
+
link = hash['link'] if hash.kind_of? Hash
|
23
|
+
add_transitions([link]) if link.kind_of? Hash
|
24
|
+
add_transitions(link) if link.kind_of? Array
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
13
29
|
# module Jeokkarak
|
14
30
|
# module Base
|
15
31
|
# alias_method :old_from_hash_parse, :from_hash_parse
|
@@ -27,48 +43,63 @@ module Restfulie
|
|
27
43
|
# basic code from Matt Pulver
|
28
44
|
# found at http://www.xcombinator.com/2008/08/11/activerecord-from_xml-and-from_json-part-2/
|
29
45
|
# addapted to support links
|
46
|
+
|
30
47
|
def from_hash( hash )
|
31
48
|
h = hash ? hash.dup : {}
|
32
49
|
links = nil
|
33
|
-
h.each do |key,value|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
when /\AHash(WithIndifferentAccess)?\Z/
|
43
|
-
if key=="link"
|
44
|
-
links = [h[key]]
|
45
|
-
h.delete("link")
|
50
|
+
h.each do |key, value|
|
51
|
+
if key == "link"
|
52
|
+
links = value.instance_of?(Array) ? h[key] : [h[key]]
|
53
|
+
elsif [Array, Hash].include? value.class
|
54
|
+
klazz = get_the_class(key)
|
55
|
+
if value.instance_of?(Array)
|
56
|
+
h[key].map! { |e| (klazz || Hashi::CustomHash).send(:from_hash, e) }
|
57
|
+
elsif value.instance_of?(Hash)
|
58
|
+
h[key] = klazz.array_from_hash(value)
|
46
59
|
else
|
47
|
-
h[key] =
|
60
|
+
h[key] = klazz.from_hash value
|
48
61
|
end
|
49
62
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
63
|
+
h.delete key if ["xmlns", "link"].include?(key)
|
64
|
+
end
|
65
|
+
|
66
|
+
result = make_new_object h
|
67
|
+
result.add_transitions(links) if !(links.nil?) && self.include?(Restfulie::Client::Instance)
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
# creates an array of this type based on a hash created using rails Hash.from_xml method
|
72
|
+
# because Hash.from_xml returns some no-cute hash structure when dealing with aligned elements
|
73
|
+
# we had to support it in a variety of ways.
|
74
|
+
# usage example:
|
75
|
+
#
|
76
|
+
# hash = {"player" => {"name" => "guilherme silveira"}}
|
77
|
+
# player = Player.array_from_hash(hash)
|
78
|
+
# puts player[0].name
|
79
|
+
#
|
80
|
+
# hash = {"player" => [{"name" => "guilherme silveira"}, {"name" => "andre de santi"}]}
|
81
|
+
# player = Player.array_from_hash(hash)
|
82
|
+
# puts player[0].name
|
83
|
+
# puts player[1].name
|
84
|
+
def array_from_hash(hash)
|
85
|
+
|
86
|
+
return self.from_hash(hash) unless (hash.size == 1 && hash.keys.first == self.to_s.underscore)
|
87
|
+
|
88
|
+
children = hash.values.first
|
89
|
+
|
90
|
+
return [self.from_hash(children)] unless children.instance_of?(Array)
|
64
91
|
|
65
|
-
|
92
|
+
children.map { |child| self.from_hash(child) }
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
def from_json(json)
|
66
97
|
from_hash(safe_json_decode(json).values.first)
|
67
98
|
end
|
68
99
|
|
69
100
|
# The xml has a surrounding class tag (e.g. ship-to),
|
70
101
|
# but the hash has no counterpart (e.g. 'ship_to' => {} )
|
71
|
-
def
|
102
|
+
def from_xml(xml)
|
72
103
|
hash = Hash.from_xml xml
|
73
104
|
head = hash[self.to_s.underscore]
|
74
105
|
result = self.from_hash head
|
@@ -77,9 +108,20 @@ module ActiveRecord
|
|
77
108
|
result
|
78
109
|
end
|
79
110
|
|
111
|
+
private
|
112
|
+
def make_new_object(hash = {})
|
113
|
+
obj = self.new
|
114
|
+
hash.keys.each { |key| obj.send("#{key}=", hash[key]) }
|
115
|
+
obj
|
116
|
+
end
|
117
|
+
|
118
|
+
def get_the_class(name)
|
119
|
+
respond_to?(:reflect_on_association) ? reflect_on_association(name.to_sym).klass.to_s.constantize : nil
|
120
|
+
end
|
80
121
|
end
|
81
|
-
end
|
122
|
+
end
|
82
123
|
|
124
|
+
private
|
83
125
|
def safe_json_decode(json)
|
84
126
|
return {} if !json
|
85
127
|
begin
|
data/lib/restfulie.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'
|
@@ -13,9 +32,13 @@ require 'restfulie/server/marshalling'
|
|
13
32
|
require 'restfulie/server/transition'
|
14
33
|
require 'restfulie/server/restfulie_controller'
|
15
34
|
require 'restfulie/server/atom_media_type'
|
35
|
+
require 'restfulie/unmarshalling'
|
16
36
|
|
17
|
-
|
37
|
+
# Author:: Guilherme Silveira (mailto:guilherme.silveira@caelum.com.br)
|
18
38
|
|
39
|
+
# This module controls global options for the Restfulie framework.
|
40
|
+
module Restfulie
|
41
|
+
|
19
42
|
# Sets this class as a restfulie class.
|
20
43
|
# You may pass a block defining your own transitions.
|
21
44
|
#
|
@@ -37,6 +60,8 @@ module Restfulie
|
|
37
60
|
extend Restfulie::MediaTypeControl
|
38
61
|
include Restfulie::Server::Instance
|
39
62
|
include Restfulie::Server::Marshalling
|
63
|
+
extend Restfulie::Unmarshalling #TODO still needs testing. e.g. server model has from_xml
|
64
|
+
#TODO and need to test (de)serialization with both AR and no-AR
|
40
65
|
|
41
66
|
self.send :define_method, :following_transitions do
|
42
67
|
transitions = []
|
@@ -49,4 +74,4 @@ end
|
|
49
74
|
|
50
75
|
Object.extend Restfulie
|
51
76
|
|
52
|
-
|
77
|
+
include ActiveSupport::CoreExtensions::Hash
|