restfulie 1.0.0.beta1 → 1.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +8 -10
- data/Gemfile.lock +59 -85
- data/README.textile +22 -57
- data/Rakefile +1 -3
- data/lib/restfulie/client/cache/basic.rb +7 -5
- data/lib/restfulie/client/cache/restrictions.rb +2 -0
- data/lib/restfulie/client/dsl.rb +7 -22
- data/lib/restfulie/client/entry_point.rb +1 -1
- data/lib/restfulie/client/ext/link_ext.rb +11 -0
- data/lib/restfulie/client/ext/open_search_ext.rb +26 -0
- data/lib/restfulie/client/ext.rb +3 -0
- data/lib/restfulie/client/feature/base_request.rb +2 -2
- data/lib/restfulie/client/feature/cache.rb +2 -2
- data/lib/restfulie/client/feature/conneg_when_unaccepted.rb +25 -0
- data/lib/restfulie/client/feature/enhance_response.rb +2 -2
- data/lib/restfulie/client/feature/follow_request.rb +2 -2
- data/lib/restfulie/client/feature/history_request.rb +2 -2
- data/lib/restfulie/client/feature/retry_when_unavailable.rb +25 -0
- data/lib/restfulie/client/feature/serialize_body.rb +7 -4
- data/lib/restfulie/client/feature/setup_header.rb +2 -2
- data/lib/restfulie/client/feature/throw_error.rb +2 -2
- data/lib/restfulie/client/http/link_header.rb +39 -0
- data/lib/restfulie/client/http/response_holder.rb +2 -2
- data/lib/restfulie/client/stack_navigator.rb +39 -0
- data/lib/restfulie/client.rb +3 -5
- data/lib/restfulie/common.rb +5 -6
- data/lib/restfulie/server/action_controller/base.rb +1 -1
- data/lib/restfulie/server/core_ext/array.rb +1 -27
- data/lib/restfulie/server/tokamak.rb +6 -0
- data/lib/restfulie/server.rb +11 -10
- data/lib/restfulie/version.rb +1 -1
- metadata +24 -95
- data/lib/restfulie/client/ext/atom_ext.rb +0 -14
- data/lib/restfulie/client/ext/json_ext.rb +0 -16
- data/lib/restfulie/common/converter/atom/base.rb +0 -91
- data/lib/restfulie/common/converter/atom/builder.rb +0 -111
- data/lib/restfulie/common/converter/atom/helpers.rb +0 -17
- data/lib/restfulie/common/converter/atom.rb +0 -12
- data/lib/restfulie/common/converter/form_url_encoded.rb +0 -16
- data/lib/restfulie/common/converter/json/base.rb +0 -87
- data/lib/restfulie/common/converter/json/builder.rb +0 -102
- data/lib/restfulie/common/converter/json/helpers.rb +0 -17
- data/lib/restfulie/common/converter/json.rb +0 -12
- data/lib/restfulie/common/converter/open_search/descriptor.rb +0 -32
- data/lib/restfulie/common/converter/open_search.rb +0 -16
- data/lib/restfulie/common/converter/values.rb +0 -33
- data/lib/restfulie/common/converter/xml/base.rb +0 -63
- data/lib/restfulie/common/converter/xml/builder.rb +0 -113
- data/lib/restfulie/common/converter/xml/helpers.rb +0 -17
- data/lib/restfulie/common/converter/xml/link.rb +0 -30
- data/lib/restfulie/common/converter/xml/links.rb +0 -21
- data/lib/restfulie/common/converter/xml.rb +0 -14
- data/lib/restfulie/common/converter.rb +0 -43
- data/lib/restfulie/common/core_ext/hash.rb +0 -18
- data/lib/restfulie/common/core_ext.rb +0 -1
- data/lib/restfulie/common/links.rb +0 -9
- data/lib/restfulie/common/representation/atom/atom.rng +0 -597
- data/lib/restfulie/common/representation/atom/base.rb +0 -142
- data/lib/restfulie/common/representation/atom/category.rb +0 -41
- data/lib/restfulie/common/representation/atom/entry.rb +0 -59
- data/lib/restfulie/common/representation/atom/factory.rb +0 -43
- data/lib/restfulie/common/representation/atom/feed.rb +0 -110
- data/lib/restfulie/common/representation/atom/link.rb +0 -68
- data/lib/restfulie/common/representation/atom/person.rb +0 -48
- data/lib/restfulie/common/representation/atom/source.rb +0 -59
- data/lib/restfulie/common/representation/atom/tag_collection.rb +0 -38
- data/lib/restfulie/common/representation/atom/xml.rb +0 -90
- data/lib/restfulie/common/representation/atom.rb +0 -20
- data/lib/restfulie/common/representation/generic.rb +0 -22
- data/lib/restfulie/common/representation/json/base.rb +0 -27
- data/lib/restfulie/common/representation/json/keys_as_methods.rb +0 -74
- data/lib/restfulie/common/representation/json/link.rb +0 -29
- data/lib/restfulie/common/representation/json/link_collection.rb +0 -23
- data/lib/restfulie/common/representation/json.rb +0 -13
- data/lib/restfulie/common/representation/links.rb +0 -11
- data/lib/restfulie/common/representation.rb +0 -3
- data/lib/restfulie/server/action_view/helpers.rb +0 -50
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +0 -21
- data/lib/restfulie/server/action_view/template_handlers.rb +0 -30
- data/lib/restfulie/server/action_view.rb +0 -10
@@ -1,111 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Atom
|
5
|
-
class Builder
|
6
|
-
attr_accessor :atom_type
|
7
|
-
def initialize(atom_type, obj)
|
8
|
-
@doc = Nokogiri::XML::Document.new
|
9
|
-
@obj = obj
|
10
|
-
@parent = @doc.create_element(atom_type.to_s)
|
11
|
-
@parent.add_namespace_definition(nil, "http://www.w3.org/2005/Atom")
|
12
|
-
@parent.parent = @doc
|
13
|
-
end
|
14
|
-
|
15
|
-
def values(options = {}, &block)
|
16
|
-
options.each do |key,value|
|
17
|
-
attr = key.to_s
|
18
|
-
if attr =~ /^xmlns(:\w+)?$/
|
19
|
-
ns = attr.split(":", 2)[1]
|
20
|
-
@parent.add_namespace_definition(ns, value)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
yield Values.new(self)
|
24
|
-
end
|
25
|
-
|
26
|
-
def members(options = {}, &block)
|
27
|
-
collection = options[:collection] || @obj
|
28
|
-
raise Error::BuilderError.new("Members method require a collection to execute") unless collection.respond_to?(:each)
|
29
|
-
collection.each do |member|
|
30
|
-
entry = @doc.create_element("entry")
|
31
|
-
entry.parent = @parent
|
32
|
-
@parent = entry
|
33
|
-
block.call(self, member)
|
34
|
-
@parent = entry.parent
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def link(relationship, uri, options = {})
|
39
|
-
options["rel"] = relationship.to_s
|
40
|
-
options["href"] = uri
|
41
|
-
options["type"] ||= "application/atom+xml"
|
42
|
-
insert_value("link", nil, options)
|
43
|
-
end
|
44
|
-
|
45
|
-
def insert_value(name, prefix, *args, &block)
|
46
|
-
node = create_element(name.to_s, prefix, *args)
|
47
|
-
node.parent = @parent
|
48
|
-
if block_given?
|
49
|
-
@parent = node
|
50
|
-
block.call
|
51
|
-
@parent = node.parent
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def representation
|
56
|
-
Representation::Atom::Factory.create(@doc)
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def create_element(node, prefix, *args)
|
62
|
-
node = @doc.create_element(node) do |n|
|
63
|
-
if prefix
|
64
|
-
if namespace = prefix_valid?(prefix)
|
65
|
-
# Adding namespace prefix
|
66
|
-
n.namespace = namespace
|
67
|
-
namespace = nil
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
args.each do |arg|
|
72
|
-
case arg
|
73
|
-
# Adding XML attributes
|
74
|
-
when Hash
|
75
|
-
arg.each { |k,v|
|
76
|
-
key = k.to_s
|
77
|
-
if key =~ /^xmlns(:\w+)?$/
|
78
|
-
ns_name = key.split(":", 2)[1]
|
79
|
-
n.add_namespace_definition(ns_name, v)
|
80
|
-
next
|
81
|
-
end
|
82
|
-
n[k.to_s] = v.to_s
|
83
|
-
}
|
84
|
-
# Adding XML node content
|
85
|
-
else
|
86
|
-
arg.kind_of?(Time) || arg.kind_of?(DateTime) ? content = arg.xmlschema : content = arg
|
87
|
-
n.content = content
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def prefix_valid?(prefix)
|
94
|
-
ns = @parent.namespace_definitions.find { |x| x.prefix == prefix.to_s }
|
95
|
-
|
96
|
-
unless ns
|
97
|
-
@parent.ancestors.each do |a|
|
98
|
-
next if a == @doc
|
99
|
-
ns = a.namespace_definitions.find { |x| x.prefix == prefix.to_s }
|
100
|
-
break if ns
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
return ns
|
105
|
-
#TODO: raise ArgumentError, "Namespace #{prefix} has not been defined" if wanted
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Atom
|
5
|
-
module Helpers
|
6
|
-
def collection(obj, *args, &block)
|
7
|
-
Restfulie::Common::Converter::Atom.to_atom(obj, :atom_type => :feed, &block)
|
8
|
-
end
|
9
|
-
|
10
|
-
def member(obj, *args, &block)
|
11
|
-
Restfulie::Common::Converter::Atom.to_atom(obj, :atom_type => :entry, &block)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Atom
|
5
|
-
autoload :Base, 'restfulie/common/converter/atom/base'
|
6
|
-
autoload :Builder, 'restfulie/common/converter/atom/builder'
|
7
|
-
autoload :Helpers, 'restfulie/common/converter/atom/helpers'
|
8
|
-
extend Base::ClassMethods
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
class Restfulie::Common::Converter::FormUrlEncoded < Restfulie::Common::Representation::Generic
|
2
|
-
def self.marshal(content, rel)
|
3
|
-
if content.kind_of? Hash
|
4
|
-
content.map { |key, value| "#{key}=#{value}" }.join("&")
|
5
|
-
else
|
6
|
-
content
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.unmarshal(content)
|
11
|
-
def content.links
|
12
|
-
[]
|
13
|
-
end
|
14
|
-
content
|
15
|
-
end
|
16
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Json
|
5
|
-
module Base
|
6
|
-
module ClassMethods
|
7
|
-
mattr_reader :media_type_name
|
8
|
-
@@media_type_name = 'application/json'
|
9
|
-
|
10
|
-
mattr_reader :headers
|
11
|
-
@@headers = {
|
12
|
-
:get => { 'Accept' => media_type_name },
|
13
|
-
:post => { 'Content-Type' => media_type_name }
|
14
|
-
}
|
15
|
-
|
16
|
-
mattr_reader :recipes
|
17
|
-
@@recipes = {}
|
18
|
-
|
19
|
-
def describe_recipe(recipe_name, options={}, &block)
|
20
|
-
raise 'Undefined recipe' unless block_given?
|
21
|
-
raise 'Undefined recipe_name' unless recipe_name
|
22
|
-
@@recipes[recipe_name] = block
|
23
|
-
end
|
24
|
-
|
25
|
-
def to_json(obj = nil, options = {:root => {}}, &block)
|
26
|
-
# just instantiate the string with the atom factory
|
27
|
-
return Restfulie::Common::Representation::Json.create(obj) if obj.kind_of?(String)
|
28
|
-
|
29
|
-
if block_given?
|
30
|
-
recipe = block
|
31
|
-
else
|
32
|
-
recipe = options[:recipe]
|
33
|
-
end
|
34
|
-
|
35
|
-
# Check if the object is already an json
|
36
|
-
unless recipe
|
37
|
-
if obj.kind_of?(Hash) || obj.kind_of?(Array)
|
38
|
-
return Restfulie::Common::Representation::Json.create(obj)
|
39
|
-
else
|
40
|
-
raise Restfulie::Common::Error::ConverterError.new("Recipe required")
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Get recipe already described
|
45
|
-
recipe = @@recipes[recipe] unless recipe.respond_to?(:call)
|
46
|
-
|
47
|
-
# Create representation and proxy
|
48
|
-
builder = Restfulie::Common::Converter::Json::Builder.new(obj, (options[:root] || {}))
|
49
|
-
|
50
|
-
# Check recipe arity size before calling it
|
51
|
-
recipe.call(*[builder, obj, options][0,recipe.arity])
|
52
|
-
|
53
|
-
builder.representation
|
54
|
-
end
|
55
|
-
|
56
|
-
alias_method :unmarshal, :to_json
|
57
|
-
|
58
|
-
def to_hash(obj)
|
59
|
-
return obj if obj.kind_of?(Hash) || obj.kind_of?(Array)
|
60
|
-
|
61
|
-
if obj.kind_of?(::String)
|
62
|
-
Restfulie::Common::Representation::Json.create(obj)
|
63
|
-
else
|
64
|
-
raise Restfulie::Common::Error::ConverterError.new("It was not possible to convert this object to a Hash")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_s(obj)
|
69
|
-
return obj if obj.kind_of?(String)
|
70
|
-
Restfulie::Common::Representation::Json.create(obj).to_s
|
71
|
-
end
|
72
|
-
|
73
|
-
def marshal(obj, options = nil)
|
74
|
-
return obj if obj.kind_of? String
|
75
|
-
to_json(obj, options).to_json
|
76
|
-
end
|
77
|
-
|
78
|
-
# returns the current helper
|
79
|
-
def helper
|
80
|
-
Helpers
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Json
|
5
|
-
class Builder
|
6
|
-
def initialize(obj, initial_obj = {})
|
7
|
-
@doc = initial_obj
|
8
|
-
@obj = obj
|
9
|
-
@current = @doc
|
10
|
-
end
|
11
|
-
|
12
|
-
def values(options = nil, &block)
|
13
|
-
yield Values.new(self)
|
14
|
-
end
|
15
|
-
|
16
|
-
def members(options = {}, &block)
|
17
|
-
collection = options[:collection] || @obj
|
18
|
-
raise Error::BuilderError.new("Members method require a collection to execute") unless collection.respond_to?(:each)
|
19
|
-
root = options[:root] || Restfulie::Common::Converter.root_element_for(collection)
|
20
|
-
|
21
|
-
collection.each do |member|
|
22
|
-
node = {}
|
23
|
-
|
24
|
-
parent = @current
|
25
|
-
@current = node
|
26
|
-
block.call(self, member)
|
27
|
-
@current = parent
|
28
|
-
|
29
|
-
add_to_current(root, node)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def link(relationship, uri, options = {})
|
34
|
-
options["rel"] = relationship.to_s
|
35
|
-
options["href"] = uri
|
36
|
-
options["type"] ||= "application/json"
|
37
|
-
insert_value("link", nil, options)
|
38
|
-
end
|
39
|
-
|
40
|
-
def insert_value(name, prefix, *args, &block)
|
41
|
-
node = create_element(block_given?, *args)
|
42
|
-
|
43
|
-
if block_given?
|
44
|
-
parent = @current
|
45
|
-
@current = node
|
46
|
-
block.call
|
47
|
-
@current = parent
|
48
|
-
end
|
49
|
-
|
50
|
-
add_to_current(name, node)
|
51
|
-
end
|
52
|
-
|
53
|
-
def representation
|
54
|
-
Representation::Json.create(@doc).to_json
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def create_element(has_block, *args)
|
60
|
-
vals = []
|
61
|
-
hashes = []
|
62
|
-
|
63
|
-
args.each do |arg|
|
64
|
-
arg.kind_of?(Hash) ? hashes << arg : vals << arg
|
65
|
-
end
|
66
|
-
|
67
|
-
if hashes.empty?
|
68
|
-
# only simple values
|
69
|
-
unless vals.empty?
|
70
|
-
vals = vals.first if vals.size == 1
|
71
|
-
node = has_block ? {} : vals
|
72
|
-
else
|
73
|
-
node = has_block ? {} : nil
|
74
|
-
end
|
75
|
-
else
|
76
|
-
# yes we have hashes
|
77
|
-
node = {}
|
78
|
-
hashes.each { |hash| node.merge!(hash) }
|
79
|
-
unless vals.empty?
|
80
|
-
vals = vals.first if vals.size == 1
|
81
|
-
node = has_block ? {} : [node, vals]
|
82
|
-
end
|
83
|
-
node
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def add_to_current(name, value)
|
88
|
-
if @current[name]
|
89
|
-
if @current[name].kind_of?(Array)
|
90
|
-
@current[name] << value
|
91
|
-
else
|
92
|
-
@current[name] = [@current[name], value]
|
93
|
-
end
|
94
|
-
else
|
95
|
-
@current[name] = value
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Json
|
5
|
-
module Helpers
|
6
|
-
def collection(obj, *args, &block)
|
7
|
-
Restfulie::Common::Converter::Json.to_json(obj, &block)
|
8
|
-
end
|
9
|
-
|
10
|
-
def member(obj, *args, &block)
|
11
|
-
Restfulie::Common::Converter::Json.to_json(obj, &block)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Json
|
5
|
-
autoload :Base, 'restfulie/common/converter/json/base'
|
6
|
-
autoload :Builder, 'restfulie/common/converter/json/builder'
|
7
|
-
autoload :Helpers, 'restfulie/common/converter/json/helpers'
|
8
|
-
extend Base::ClassMethods
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
class Restfulie::Common::Converter::OpenSearch::Descriptor
|
2
|
-
|
3
|
-
def initialize(hash)
|
4
|
-
@hash = hash["OpenSearchDescription"]
|
5
|
-
end
|
6
|
-
|
7
|
-
def urls
|
8
|
-
uris = @hash["Url"]
|
9
|
-
uris.kind_of?(Array) ? uris : [uris]
|
10
|
-
end
|
11
|
-
|
12
|
-
def use(content_type)
|
13
|
-
uri = urls.find do |url|
|
14
|
-
url["type"]==content_type
|
15
|
-
end
|
16
|
-
return nil if uri.nil?
|
17
|
-
|
18
|
-
base_uri, params_pattern = extract_uri(uri)
|
19
|
-
Restfulie.at(base_uri).accepts(content_type).open_search.with_pattern(params_pattern)
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
def extract_uri(uri)
|
24
|
-
uri = uri["template"]
|
25
|
-
interrogation = uri.index("?")
|
26
|
-
params = uri[interrogation+1..uri.size]
|
27
|
-
base_uri = uri[0..interrogation-1]
|
28
|
-
[base_uri, params]
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
class Converter::OpenSearch#:nodoc:
|
4
|
-
autoload :Descriptor, 'restfulie/common/converter/open_search/descriptor'
|
5
|
-
end
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class Restfulie::Common::Converter::OpenSearch
|
10
|
-
|
11
|
-
def self.unmarshal(xml)
|
12
|
-
hash = Hash.from_xml(xml)
|
13
|
-
descriptor = Descriptor.new(hash)
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
# This is a Blank Slate class to support the renderization of the values block for Resource Representation Interfaces
|
5
|
-
# Every Media type should implement a Builder with a insert_value method that renders the values block to a specific format
|
6
|
-
class Values
|
7
|
-
attr_accessor :builder
|
8
|
-
|
9
|
-
# BlankSlate
|
10
|
-
instance_methods.each do |m|
|
11
|
-
undef_method m unless m.to_s =~ /\[\]|method_missing|respond_to\?|^__/
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(builder)
|
15
|
-
@builder = builder
|
16
|
-
@current_prefix = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
def [](prefix)
|
20
|
-
@current_prefix = prefix
|
21
|
-
self
|
22
|
-
end
|
23
|
-
|
24
|
-
def method_missing(symbol, *args, &block)
|
25
|
-
name = symbol.to_s
|
26
|
-
prefix = @current_prefix
|
27
|
-
@current_prefix = nil
|
28
|
-
@builder.insert_value(name, prefix, *args, &block)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,63 +0,0 @@
|
|
1
|
-
require 'active_support/core_ext/hash/conversions'
|
2
|
-
|
3
|
-
module Restfulie
|
4
|
-
module Common
|
5
|
-
module Converter
|
6
|
-
module Xml
|
7
|
-
module Base
|
8
|
-
module ClassMethods
|
9
|
-
mattr_reader :media_type_name
|
10
|
-
@@media_type_name = 'application/xml'
|
11
|
-
|
12
|
-
mattr_reader :headers
|
13
|
-
@@headers = {
|
14
|
-
:post => { 'Content-Type' => media_type_name }
|
15
|
-
}
|
16
|
-
|
17
|
-
def marshal(entity, options = {})
|
18
|
-
to_xml(entity, options)
|
19
|
-
end
|
20
|
-
|
21
|
-
def unmarshal(string)
|
22
|
-
Hash.from_xml string
|
23
|
-
end
|
24
|
-
|
25
|
-
mattr_reader :recipes
|
26
|
-
@@recipes = {}
|
27
|
-
|
28
|
-
def describe_recipe(recipe_name, options={}, &block)
|
29
|
-
raise 'Undefined recipe' unless block_given?
|
30
|
-
raise 'Undefined recipe_name' unless recipe_name
|
31
|
-
@@recipes[recipe_name] = block
|
32
|
-
end
|
33
|
-
|
34
|
-
def to_xml(obj, options = {}, &block)
|
35
|
-
return obj if obj.kind_of?(String)
|
36
|
-
|
37
|
-
if block_given?
|
38
|
-
recipe = block
|
39
|
-
elsif options[:recipe]
|
40
|
-
recipe = @@recipes[options[:recipe]]
|
41
|
-
elsif obj.kind_of?(Hash) && obj.size==1
|
42
|
-
return obj.values.first.to_xml(:root => obj.keys.first)
|
43
|
-
else
|
44
|
-
return obj.to_xml
|
45
|
-
end
|
46
|
-
|
47
|
-
# Create representation and proxy
|
48
|
-
builder = Builder.new(obj, options)
|
49
|
-
|
50
|
-
# Check recipe arity size before calling it
|
51
|
-
recipe.call(*[builder, obj, options][0,recipe.arity])
|
52
|
-
builder.doc.to_xml
|
53
|
-
end
|
54
|
-
|
55
|
-
def helper
|
56
|
-
Helpers
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Xml
|
5
|
-
# Implements the interface for marshal Xml media type requests (application/xml)
|
6
|
-
class Builder
|
7
|
-
attr_reader :doc
|
8
|
-
def initialize(obj, options = {})
|
9
|
-
@doc = Nokogiri::XML::Document.new
|
10
|
-
@obj = obj
|
11
|
-
root = options[:root] || Restfulie::Common::Converter.root_element_for(obj)
|
12
|
-
@parent = @doc.create_element(root)
|
13
|
-
@parent.parent = @doc
|
14
|
-
end
|
15
|
-
|
16
|
-
def values(options = {}, &block)
|
17
|
-
options.each do |key,value|
|
18
|
-
attr = key.to_s
|
19
|
-
if attr =~ /^xmlns(:\w+)?$/
|
20
|
-
ns = attr.split(":", 2)[1]
|
21
|
-
@parent.add_namespace_definition(ns, value)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
yield Values.new(self)
|
25
|
-
end
|
26
|
-
|
27
|
-
def insert_value(name, prefix, *args, &block)
|
28
|
-
node = create_element(name.to_s, prefix, *args)
|
29
|
-
node.parent = @parent
|
30
|
-
|
31
|
-
if block_given?
|
32
|
-
@parent = node
|
33
|
-
block.call
|
34
|
-
@parent = node.parent
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def link(relationship, uri, options = {})
|
39
|
-
options["rel"] = relationship.to_s
|
40
|
-
options["href"] = uri
|
41
|
-
options["type"] ||= "application/xml"
|
42
|
-
insert_value("link", nil, options)
|
43
|
-
end
|
44
|
-
|
45
|
-
def members(a_collection = nil, options = {}, &block)
|
46
|
-
collection = a_collection || @obj
|
47
|
-
raise Error::BuilderError("Members method require a collection to execute") unless collection.respond_to?(:each)
|
48
|
-
collection.each do |member|
|
49
|
-
root = options[:root] || Restfulie::Common::Converter.root_element_for(member)
|
50
|
-
entry = @doc.create_element(root)
|
51
|
-
entry.parent = @parent
|
52
|
-
@parent = entry
|
53
|
-
block.call(self, member)
|
54
|
-
@parent = entry.parent
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def create_element(node, prefix, *args)
|
61
|
-
node = @doc.create_element(node) do |n|
|
62
|
-
if prefix
|
63
|
-
if namespace = prefix_valid?(prefix)
|
64
|
-
# Adding namespace prefix
|
65
|
-
n.namespace = namespace
|
66
|
-
namespace = nil
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
args.each do |arg|
|
71
|
-
case arg
|
72
|
-
# Adding XML attributes
|
73
|
-
when Hash
|
74
|
-
arg.each { |k,v|
|
75
|
-
key = k.to_s
|
76
|
-
if key =~ /^xmlns(:\w+)?$/
|
77
|
-
ns_name = key.split(":", 2)[1]
|
78
|
-
n.add_namespace_definition(ns_name, v)
|
79
|
-
next
|
80
|
-
end
|
81
|
-
n[k.to_s] = v.to_s
|
82
|
-
}
|
83
|
-
# Adding XML node content
|
84
|
-
else
|
85
|
-
content = if arg.kind_of?(Time) || arg.kind_of?(DateTime)
|
86
|
-
arg.xmlschema
|
87
|
-
else
|
88
|
-
arg
|
89
|
-
end
|
90
|
-
n.content = content
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def prefix_valid?(prefix)
|
97
|
-
ns = @parent.namespace_definitions.find { |x| x.prefix == prefix.to_s }
|
98
|
-
|
99
|
-
unless ns
|
100
|
-
@parent.ancestors.each do |a|
|
101
|
-
next if a == @doc
|
102
|
-
ns = a.namespace_definitions.find { |x| x.prefix == prefix.to_s }
|
103
|
-
break if ns
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
return ns
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Xml
|
5
|
-
module Helpers
|
6
|
-
def collection(obj, opts = {}, &block)
|
7
|
-
Xml.to_xml(obj, opts, &block)
|
8
|
-
end
|
9
|
-
|
10
|
-
def member(obj, opts = {}, &block)
|
11
|
-
Xml.to_xml(obj, opts, &block)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Restfulie
|
2
|
-
module Common
|
3
|
-
module Converter
|
4
|
-
module Xml
|
5
|
-
class Link
|
6
|
-
def initialize(options = {})
|
7
|
-
@options = options
|
8
|
-
end
|
9
|
-
def href
|
10
|
-
@options["href"]
|
11
|
-
end
|
12
|
-
def rel
|
13
|
-
@options["rel"]
|
14
|
-
end
|
15
|
-
def content_type
|
16
|
-
@options["type"]
|
17
|
-
end
|
18
|
-
def type
|
19
|
-
content_type
|
20
|
-
end
|
21
|
-
def follow
|
22
|
-
r = Restfulie.at(href)
|
23
|
-
r = r.as(content_type) if content_type
|
24
|
-
r
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|