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,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
|