restfulie 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +21 -0
- data/README.textile +10 -9
- data/Rakefile +12 -5
- data/lib/restfulie/client/base.rb +10 -6
- data/lib/restfulie/client/http/adapter.rb +48 -33
- data/lib/restfulie/client/http/atom_ext.rb +3 -68
- data/lib/restfulie/client/http/core_ext/http.rb +19 -0
- data/lib/restfulie/client/http/core_ext.rb +6 -0
- data/lib/restfulie/client/http/error.rb +3 -6
- data/lib/restfulie/client/http/marshal.rb +35 -49
- data/lib/restfulie/client/http/xml_ext.rb +7 -0
- data/lib/restfulie/client/http.rb +2 -2
- data/lib/restfulie/client/mikyung/concatenator.rb +15 -0
- data/lib/restfulie/client/mikyung/core.rb +44 -0
- data/lib/restfulie/client/mikyung/languages.rb +29 -0
- data/lib/restfulie/client/mikyung/rest_process_model.rb +114 -0
- data/lib/restfulie/client/mikyung/steady_state_walker.rb +32 -0
- data/lib/restfulie/client/mikyung/then_condition.rb +33 -0
- data/lib/restfulie/client/mikyung/when_condition.rb +53 -0
- data/lib/restfulie/client/mikyung.rb +19 -0
- data/lib/restfulie/client.rb +1 -0
- data/lib/restfulie/common/converter/atom/builder.rb +109 -0
- data/lib/restfulie/common/converter/atom/helpers.rb +9 -0
- data/lib/restfulie/common/converter/atom.rb +87 -0
- data/lib/restfulie/common/converter/values.rb +29 -0
- data/lib/restfulie/common/converter.rb +11 -0
- data/lib/restfulie/common/core_ext/proc.rb +48 -0
- data/lib/restfulie/common/core_ext.rb +5 -0
- data/lib/restfulie/common/errors.rb +6 -0
- data/lib/restfulie/common/representation/atom/atom.rng +597 -0
- data/lib/restfulie/common/representation/atom/base.rb +375 -0
- data/lib/restfulie/common/representation/atom/entry.rb +107 -0
- data/lib/restfulie/common/representation/atom/feed.rb +106 -0
- data/lib/restfulie/common/representation/atom.rb +43 -33
- data/lib/restfulie/common/representation/json.rb +1 -2
- data/lib/restfulie/common/representation/xml.rb +209 -23
- data/lib/restfulie/common/representation.rb +0 -1
- data/lib/restfulie/common.rb +2 -3
- data/lib/restfulie/server/action_controller/base.rb +21 -2
- data/lib/restfulie/server/action_controller/params_parser.rb +16 -16
- data/lib/restfulie/server/action_controller/restful_responder.rb +3 -3
- data/lib/restfulie/server/action_controller/routing/patch.rb +6 -0
- data/lib/restfulie/server/action_view/helpers.rb +8 -8
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +3 -2
- data/lib/restfulie/server/core_ext/array.rb +13 -12
- metadata +51 -34
- data/lib/restfulie/client/http/link.rb +0 -39
- data/lib/restfulie/client/http/xml.rb +0 -4
- data/lib/restfulie/common/builder/builder_base.rb +0 -73
- data/lib/restfulie/common/builder/helpers.rb +0 -22
- data/lib/restfulie/common/builder/marshalling/atom.rb +0 -197
- data/lib/restfulie/common/builder/marshalling/base.rb +0 -12
- data/lib/restfulie/common/builder/marshalling/json.rb +0 -2
- data/lib/restfulie/common/builder/marshalling/xml.rb +0 -183
- data/lib/restfulie/common/builder/marshalling.rb +0 -16
- data/lib/restfulie/common/builder/rules/collection_rule.rb +0 -10
- data/lib/restfulie/common/builder/rules/custom_attributes.rb +0 -24
- data/lib/restfulie/common/builder/rules/link.rb +0 -20
- data/lib/restfulie/common/builder/rules/links.rb +0 -9
- data/lib/restfulie/common/builder/rules/member_rule.rb +0 -8
- data/lib/restfulie/common/builder/rules/namespace.rb +0 -35
- data/lib/restfulie/common/builder/rules/rules_base.rb +0 -77
- data/lib/restfulie/common/builder.rb +0 -17
- data/lib/vendor/atom/configuration.rb +0 -24
- data/lib/vendor/atom/pub.rb +0 -250
- data/lib/vendor/atom/xml/parser.rb +0 -373
- data/lib/vendor/atom.rb +0 -771
@@ -1,73 +0,0 @@
|
|
1
|
-
class Restfulie::Common::Builder::Base
|
2
|
-
attr_accessor :rules_blocks
|
3
|
-
attr_accessor :object
|
4
|
-
|
5
|
-
# TODO: Configurable
|
6
|
-
OPTIONS_DEFAULT = {
|
7
|
-
:eagerload => true,
|
8
|
-
:default_rule => true
|
9
|
-
}
|
10
|
-
|
11
|
-
def initialize(object, rules_blocks = [], options = {})
|
12
|
-
@options = OPTIONS_DEFAULT.merge(options)
|
13
|
-
@object = object
|
14
|
-
@rules_blocks = rules_blocks
|
15
|
-
end
|
16
|
-
|
17
|
-
# Remove to_json from ActiveSupport in the class
|
18
|
-
# I want my own to_json
|
19
|
-
undef_method :to_json if respond_to?(:to_json)
|
20
|
-
|
21
|
-
def respond_to?(symbol, include_private = false)
|
22
|
-
marshalling_class(symbol) || super
|
23
|
-
end
|
24
|
-
|
25
|
-
def method_missing(symbol, *args)
|
26
|
-
unless (marshalling = marshalling_class!(symbol)).nil?
|
27
|
-
return builder(marshalling, *args)
|
28
|
-
end
|
29
|
-
super
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def builder(marshalling, options = {})
|
35
|
-
@object.class.ancestors.include?(Enumerable) ? builder_collection(marshalling, options) : builder_member(marshalling, options)
|
36
|
-
end
|
37
|
-
|
38
|
-
def builder_member(marshalling, options = {})
|
39
|
-
marshalling.new(@object, rules_blocks).builder_member(@options.merge(options))
|
40
|
-
end
|
41
|
-
|
42
|
-
def builder_collection(marshalling, options = {})
|
43
|
-
marshalling.new(@object, rules_blocks).builder_collection(@options.merge(options))
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.marshalling_classes(media_type)
|
47
|
-
{"application/atom+xml" => Restfulie::Common::Builder::Marshalling::Atom,
|
48
|
-
"application/xml" => Restfulie::Common::Builder::Marshalling::Xml::Marshaller,
|
49
|
-
"application/json" => Restfulie::Common::Builder::Marshalling::Json,
|
50
|
-
"atom" => Restfulie::Common::Builder::Marshalling::Atom, # test only
|
51
|
-
"xml" => Restfulie::Common::Builder::Marshalling::Xml::Marshaller # test only
|
52
|
-
}[media_type.downcase]
|
53
|
-
end
|
54
|
-
|
55
|
-
def marshalling_class(method)
|
56
|
-
if (marshalling_name = method.to_s.match(/to_(.*)/))
|
57
|
-
marshalling = marshalling_name[1].downcase
|
58
|
-
Restfulie::Common::Builder::Base.marshalling_classes(marshalling)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def marshalling_class!(method)
|
63
|
-
if marshalling_name = method.to_s.match(/to_(.*)/)
|
64
|
-
marshalling = marshalling_name[1].downcase
|
65
|
-
if (marshaller = Restfulie::Common::Builder::Base.marshalling_classes(marshalling))
|
66
|
-
marshaller
|
67
|
-
else
|
68
|
-
raise Restfulie::Common::Error::UndefinedMarshallingError.new("Marshalling #{marshalling} not found.")
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Restfulie::Common::Builder::Helpers
|
2
|
-
|
3
|
-
def describe_member(member, options = {}, &block)
|
4
|
-
create_builder(member, options, &block)
|
5
|
-
end
|
6
|
-
|
7
|
-
def describe_collection(collection, options = {}, &block)
|
8
|
-
create_builder(collection, options, &block)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Helper to create objects link
|
12
|
-
def link(*args)
|
13
|
-
Restfulie::Common::Builder::Rules::Link.new(*args)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def create_builder(object, options, &block)
|
19
|
-
Restfulie::Common::Builder::Base.new(object, block_given? ? [block] : [], options)
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
@@ -1,197 +0,0 @@
|
|
1
|
-
class Restfulie::Common::Builder::Marshalling::Atom < Restfulie::Common::Builder::Marshalling::Base
|
2
|
-
include ActionController::UrlWriter
|
3
|
-
include Restfulie::Common::Builder::Helpers
|
4
|
-
include Restfulie::Common::Error
|
5
|
-
|
6
|
-
ATOM_ATTRIBUTES = [
|
7
|
-
:title, :id, :updated, # Required
|
8
|
-
:author, :links, # Recommended
|
9
|
-
:category, :contributor, :rights # Optional
|
10
|
-
]
|
11
|
-
|
12
|
-
ATOM_ATTRIBUTES_ENTRY = ATOM_ATTRIBUTES + [
|
13
|
-
:content, :summary, # Required
|
14
|
-
:published, :source # Optional
|
15
|
-
]
|
16
|
-
|
17
|
-
ATOM_ATTRIBUTES_FEED = ATOM_ATTRIBUTES + [
|
18
|
-
:generator, :icon, :logo, :subtitle # Optional
|
19
|
-
]
|
20
|
-
|
21
|
-
ATTRIBUTES_ALREADY_IN_ATOM_SPEC = [
|
22
|
-
"id", "created_at", "updated_at", "title"
|
23
|
-
]
|
24
|
-
|
25
|
-
def initialize(object, rules)
|
26
|
-
@object = object
|
27
|
-
@rules = rules
|
28
|
-
end
|
29
|
-
|
30
|
-
def builder_collection(options = {})
|
31
|
-
builder_feed(@object, @rules, options).to_xml
|
32
|
-
end
|
33
|
-
|
34
|
-
def builder_member(options = {})
|
35
|
-
builder_entry(@object, @rules, options).to_xml
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
|
40
|
-
def builder_feed(objects, rules_blocks, options = {})
|
41
|
-
rule = Restfulie::Common::Builder::CollectionRule.new(rules_blocks)
|
42
|
-
|
43
|
-
rule.blocks.unshift(default_collection_rule) if options[:default_rule]
|
44
|
-
rule.metaclass.send(:attr_accessor, *ATOM_ATTRIBUTES_FEED)
|
45
|
-
rule.apply(objects, options)
|
46
|
-
|
47
|
-
atom = ::Atom::Feed.new do |feed|
|
48
|
-
# Set values
|
49
|
-
(ATOM_ATTRIBUTES_FEED - [:links]).each do |field|
|
50
|
-
feed.send("#{field}=".to_sym, rule.send(field)) unless rule.send(field).nil?
|
51
|
-
end
|
52
|
-
|
53
|
-
# Namespaces
|
54
|
-
builder_namespaces(rule.namespaces, feed)
|
55
|
-
|
56
|
-
# Transitions
|
57
|
-
rule.links.each do |link|
|
58
|
-
atom_link = {:rel => link.rel, :href => link.href, :type => (link.type || 'application/atom+xml')}
|
59
|
-
feed.links << ::Atom::Link.new(atom_link) unless atom_link[:href].nil?
|
60
|
-
end
|
61
|
-
|
62
|
-
# Entries
|
63
|
-
options.delete(:values)
|
64
|
-
member_options = options.merge(rule.members_options || {})
|
65
|
-
objects.each do |member|
|
66
|
-
feed.entries << builder_entry(member, rule.members_blocks || [], member_options)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
# TODO: Validate of the required fields
|
72
|
-
def default_collection_rule
|
73
|
-
Proc.new do |collection_rule, objects, options|
|
74
|
-
# Passed values
|
75
|
-
(options[:values] || {}).each { |key, value| collection_rule.send("#{key}=".to_sym, value)}
|
76
|
-
|
77
|
-
# Default values
|
78
|
-
collection_rule.id ||= options[:self]
|
79
|
-
collection_rule.title ||= "#{objects.first.class.to_s.pluralize.demodulize} feed"
|
80
|
-
collection_rule.updated ||= updated_collection(objects)
|
81
|
-
|
82
|
-
# Transitions
|
83
|
-
collection_rule.links << link(:rel => :self, :href => options[:self]) unless options[:self].nil?
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def builder_entry(object, rules_blocks, options = {})
|
88
|
-
rule = Restfulie::Common::Builder::MemberRule.new(rules_blocks)
|
89
|
-
options = namespace_enhance(options)
|
90
|
-
|
91
|
-
rule.blocks.unshift(default_member_rule) if options[:default_rule]
|
92
|
-
rule.metaclass.send(:attr_accessor, *ATOM_ATTRIBUTES_ENTRY)
|
93
|
-
rule.apply(object, options)
|
94
|
-
|
95
|
-
atom = ::Atom::Entry.new do |entry|
|
96
|
-
# Set values
|
97
|
-
(ATOM_ATTRIBUTES_ENTRY - [:links]).each do |field|
|
98
|
-
entry.send("#{field}=".to_sym, rule.send(field)) unless rule.send(field).nil?
|
99
|
-
end
|
100
|
-
|
101
|
-
# Namespaces
|
102
|
-
builder_namespaces(rule.namespaces, entry)
|
103
|
-
|
104
|
-
# Transitions
|
105
|
-
rule.links.each do |link|
|
106
|
-
atom_link = {:rel => link.rel, :href => link.href, :type => link.type}
|
107
|
-
|
108
|
-
# Self
|
109
|
-
if link.href.nil?
|
110
|
-
if link.rel == "self"
|
111
|
-
path = object
|
112
|
-
else
|
113
|
-
association = object.class.reflect_on_all_associations.find { |a| a.name.to_s == link.rel }
|
114
|
-
path = (association.macro == :has_many) ? [object, association.name] : object.send(association.name) unless association.nil?
|
115
|
-
end
|
116
|
-
atom_link[:href] = polymorphic_url(path, :host => host) rescue nil
|
117
|
-
atom_link[:type] = link.type || 'application/atom+xml'
|
118
|
-
end
|
119
|
-
|
120
|
-
entry.links << ::Atom::Link.new(atom_link) unless atom_link[:href].nil?
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
def default_member_rule
|
126
|
-
Proc.new do |member_rule, object, options|
|
127
|
-
# Passed values
|
128
|
-
(options[:values] || {}).each { |key, value| set_attribute(member_rule, key, value) }
|
129
|
-
|
130
|
-
# Default values
|
131
|
-
member_rule.id ||= polymorphic_url(object, :host => host) rescue nil
|
132
|
-
member_rule.title ||= object.respond_to?(:title) && !object.title.nil? ? object.title : "Entry about #{object.class.to_s.demodulize}"
|
133
|
-
member_rule.updated ||= object.updated_at if object.respond_to?(:updated_at)
|
134
|
-
|
135
|
-
# Namespace
|
136
|
-
unless options[:namespace].nil?
|
137
|
-
member_rule.namespace(object, options[:namespace][:uri], options[:namespace])
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def updated_collection(objects)
|
143
|
-
objects.map { |item| item.updated_at if item.respond_to?(:updated_at) }.compact.max || Time.now
|
144
|
-
end
|
145
|
-
|
146
|
-
def builder_namespaces(namespaces, atom)
|
147
|
-
kclass = atom.class
|
148
|
-
namespaces.each do |ns|
|
149
|
-
register_namespace(ns.namespace, ns.uri, kclass)
|
150
|
-
ns.each do |key, value|
|
151
|
-
unless ATTRIBUTES_ALREADY_IN_ATOM_SPEC.include?(key.to_s)
|
152
|
-
register_element(ns.namespace, key, kclass)
|
153
|
-
atom.send("#{ns.namespace}_#{key}=".to_sym, value)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def host
|
160
|
-
# TODO: If we split restfulie into 2 separate gems, we may need not to use Restfulie::Server
|
161
|
-
# inside Restfulie::Common
|
162
|
-
Restfulie::Server::Configuration.host
|
163
|
-
end
|
164
|
-
|
165
|
-
def register_namespace(namespace, uri, klass)
|
166
|
-
klass.add_extension_namespace(namespace, uri) unless klass.known_namespaces.include? uri
|
167
|
-
end
|
168
|
-
|
169
|
-
def register_element(namespace, attribute, klass)
|
170
|
-
attribute = "#{namespace}:#{attribute}"
|
171
|
-
klass.element(attribute) if element_unregistered?(attribute, klass)
|
172
|
-
end
|
173
|
-
|
174
|
-
def element_unregistered?(element, klass)
|
175
|
-
klass.element_specs.select { |k,v| v.name == element }.empty?
|
176
|
-
end
|
177
|
-
|
178
|
-
# TODO : Move error handling to class rule, maybe?
|
179
|
-
def set_attribute(rule, attribute, value)
|
180
|
-
begin
|
181
|
-
rule.send("#{attribute}=".to_sym, value)
|
182
|
-
rescue NoMethodError
|
183
|
-
raise AtomMarshallingError.new("Attribute #{attribute} unsupported in Atom #{rule_type_name(rule)}.")
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def rule_type_name(rule)
|
188
|
-
rule.kind_of?(Restfulie::Common::Builder::MemberRule) ? 'Entry' : 'Feed'
|
189
|
-
end
|
190
|
-
|
191
|
-
def namespace_enhance(options)
|
192
|
-
if options[:namespace] && options[:namespace].kind_of?(String)
|
193
|
-
options[:namespace] = { :uri => options[:namespace], :eager_load => true }
|
194
|
-
end
|
195
|
-
options
|
196
|
-
end
|
197
|
-
end
|
@@ -1,12 +0,0 @@
|
|
1
|
-
class Restfulie::Common::Builder::Marshalling::Base
|
2
|
-
def initialize(*args)
|
3
|
-
end
|
4
|
-
|
5
|
-
def builder_member(options = {})
|
6
|
-
"#{self.class.to_s.demodulize} Marshalling not implemented"
|
7
|
-
end
|
8
|
-
|
9
|
-
def builder_collection(options = {})
|
10
|
-
"#{self.class.to_s.demodulize} Marshalling not implemented"
|
11
|
-
end
|
12
|
-
end
|
@@ -1,183 +0,0 @@
|
|
1
|
-
# support xml serialization for custom attributes
|
2
|
-
module Restfulie::Common::Builder::Rules::CustomAttributes
|
3
|
-
|
4
|
-
def to_xml(writer)
|
5
|
-
custom_attributes.each do |key, value|
|
6
|
-
writer.tag!(key, value)
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
module Restfulie::Common::Builder::Marshalling::Xml
|
13
|
-
end
|
14
|
-
|
15
|
-
# Xml collection rule answering to to_xml and allowing any custom element to be inserted
|
16
|
-
# All links will be automatically inserted.
|
17
|
-
class Restfulie::Common::Builder::Marshalling::Xml::CollectionRule < Restfulie::Common::Builder::CollectionRule
|
18
|
-
|
19
|
-
include Restfulie::Common::Builder::Rules::CustomAttributes
|
20
|
-
|
21
|
-
def to_xml(writer)
|
22
|
-
super(writer)
|
23
|
-
links.each do |link|
|
24
|
-
writer.link(:rel => link.rel, :href => link.href, :type => (link.type || 'application/xml')) if link.href
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
# Xml member rule answering to to_xml and allowing any custom element to be inserted.
|
31
|
-
# All links will be automatically inserted.
|
32
|
-
class Restfulie::Common::Builder::Marshalling::Xml::MemberRule < Restfulie::Common::Builder::MemberRule
|
33
|
-
|
34
|
-
include ActionController::UrlWriter
|
35
|
-
include Restfulie::Common::Builder::Rules::CustomAttributes
|
36
|
-
|
37
|
-
def to_xml(object, writer)
|
38
|
-
super(writer)
|
39
|
-
# Transitions
|
40
|
-
links.each do |link|
|
41
|
-
atom_link = {:rel => link.rel, :href => link.href, :type => link.type}
|
42
|
-
|
43
|
-
# Self
|
44
|
-
if link.href.nil?
|
45
|
-
if link.rel == "self"
|
46
|
-
path = object
|
47
|
-
else
|
48
|
-
association = object.class.reflect_on_all_associations.find { |a| a.name.to_s == link.rel }
|
49
|
-
path = (association.macro == :has_many) ? [object, association.name] : object.send(association.name) unless association.nil?
|
50
|
-
end
|
51
|
-
atom_link[:href] = polymorphic_url(path, :host => host) rescue nil
|
52
|
-
atom_link[:type] = link.type || 'application/xml'
|
53
|
-
end
|
54
|
-
writer.link(:rel => atom_link[:rel], :href => atom_link[:href], :type => (link.type || 'application/xml')) if atom_link[:href]
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
private
|
60
|
-
def host
|
61
|
-
# TODO: If we split restfulie into 2 separate gems, we may need not to use Restfulie::Server
|
62
|
-
# inside Restfulie::Common
|
63
|
-
Restfulie::Server::Configuration.host
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
class Restfulie::Common::Builder::Marshalling::Xml::Marshaller < Restfulie::Common::Builder::Marshalling::Base
|
69
|
-
include ActionController::UrlWriter
|
70
|
-
include Restfulie::Common::Builder::Helpers
|
71
|
-
include Restfulie::Common::Error
|
72
|
-
|
73
|
-
def initialize(object, rules)
|
74
|
-
@object = object
|
75
|
-
@rules = rules
|
76
|
-
end
|
77
|
-
|
78
|
-
def builder_collection(options = {})
|
79
|
-
builder_feed(@object, @rules, options)
|
80
|
-
end
|
81
|
-
|
82
|
-
def builder_member(options = {})
|
83
|
-
options[:indent] ||= 2
|
84
|
-
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
85
|
-
options[:skip_types] = true
|
86
|
-
builder_entry(@object, options[:builder], @object.class.name.underscore, @rules, options)
|
87
|
-
end
|
88
|
-
|
89
|
-
private
|
90
|
-
|
91
|
-
def builder_feed(objects, rules_blocks, options = {})
|
92
|
-
rule = Restfulie::Common::Builder::Marshalling::Xml::CollectionRule.new(rules_blocks)
|
93
|
-
|
94
|
-
rule.blocks.unshift(default_collection_rule) if options[:default_rule]
|
95
|
-
rule.apply(objects, options)
|
96
|
-
|
97
|
-
# setup code from Rails to_xml
|
98
|
-
|
99
|
-
options[:root] ||= objects.all? { |e| e.is_a?(objects.first.class) && objects.first.class.to_s != "Hash" } ? objects.first.class.to_s.underscore.pluralize : "records"
|
100
|
-
options[:children] ||= options[:root].singularize
|
101
|
-
options[:indent] ||= 2
|
102
|
-
options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
103
|
-
|
104
|
-
root = options.delete(:root).to_s
|
105
|
-
children = options.delete(:children)
|
106
|
-
|
107
|
-
if !options.has_key?(:dasherize) || options[:dasherize]
|
108
|
-
root = root.dasherize
|
109
|
-
end
|
110
|
-
|
111
|
-
options[:builder].instruct! unless options.delete(:skip_instruct)
|
112
|
-
|
113
|
-
opts = options.merge({ :root => children })
|
114
|
-
|
115
|
-
writer = options[:builder]
|
116
|
-
|
117
|
-
# Entries
|
118
|
-
options.delete(:values)
|
119
|
-
member_options = options.merge(rule.members_options || {})
|
120
|
-
member_options[:skip_instruct] = true
|
121
|
-
start_with_namespace(rule.namespaces, writer, root, options[:skip_types] ? {} : {}) do
|
122
|
-
rule.to_xml(writer)
|
123
|
-
yield writer if block_given?
|
124
|
-
|
125
|
-
objects.each { |e|
|
126
|
-
builder_entry(e, writer, children, rule.members_blocks || [], member_options)
|
127
|
-
}
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
def start_with_namespace(namespaces, writer, root, condition, &block)
|
133
|
-
spaces = condition.dup
|
134
|
-
namespaces.each do |ns|
|
135
|
-
ns.each do |key, value|
|
136
|
-
spaces["xmlns:#{ns.namespace}"] = ns.uri
|
137
|
-
end if ns.uri
|
138
|
-
end
|
139
|
-
result = writer.tag!(root, spaces) do |inner|
|
140
|
-
namespaces.each do |ns|
|
141
|
-
ns.each do |key, value|
|
142
|
-
tag = ns.namespace ? "#{key}" : "#{ns.namespace}:#{key}"
|
143
|
-
inner.tag! tag, value
|
144
|
-
end
|
145
|
-
end
|
146
|
-
block.call inner
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def default_collection_rule
|
151
|
-
Proc.new do |collection_rule, objects, options|
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def builder_entry(object, xml, children, rules_blocks, options)
|
156
|
-
rule = Restfulie::Common::Builder::Marshalling::Xml::MemberRule.new(rules_blocks)
|
157
|
-
options = namespace_enhance(options)
|
158
|
-
|
159
|
-
rule.blocks.unshift(default_member_rule) if options[:default_rule]
|
160
|
-
rule.apply(object, options)
|
161
|
-
|
162
|
-
start_with_namespace(rule.namespaces, xml, children, {}) do |inner_xml|
|
163
|
-
rule.to_xml(object, inner_xml)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def default_member_rule
|
168
|
-
Proc.new do |member_rule, object, options|
|
169
|
-
if options[:namespace]
|
170
|
-
member_rule.namespace(object, options[:namespace][:uri], options[:namespace])
|
171
|
-
else
|
172
|
-
member_rule.namespace(object, nil, options[:namespace] || {})
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def namespace_enhance(options)
|
178
|
-
if !options[:namespace].nil? && options[:namespace].kind_of?(String)
|
179
|
-
options[:namespace] = { :uri => options[:namespace], :eager_load => true }
|
180
|
-
end
|
181
|
-
options
|
182
|
-
end
|
183
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Restfulie::Common::Builder::Marshalling
|
2
|
-
class << self
|
3
|
-
def add_autoload_path(path)
|
4
|
-
if File.directory?(path)
|
5
|
-
Dir["#{path}/*.rb"].each do |file|
|
6
|
-
marshalling_class = File.basename(file, ".rb").downcase.classify.to_sym
|
7
|
-
self.autoload(marshalling_class, file) if !self.const_defined?(marshalling_class) && self.autoload?(marshalling_class).nil?
|
8
|
-
end
|
9
|
-
else
|
10
|
-
raise Restfulie::Common::Error::MarshallingError.new("#{path} is not a path.")
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
self.add_autoload_path(File.join(File.dirname(__FILE__), 'marshalling'))
|
16
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
class Restfulie::Common::Builder::CollectionRule < Restfulie::Common::Builder::Rules::Base
|
2
|
-
attr_reader :members_blocks
|
3
|
-
attr_reader :members_options
|
4
|
-
|
5
|
-
def describe_members(options = {}, &block)
|
6
|
-
@members_blocks = block_given? ? [block] : []
|
7
|
-
@members_options = options
|
8
|
-
end
|
9
|
-
|
10
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# Rules that allow any type of content shall extend this one and provide valid serialization methods. i.e.: to_xml
|
2
|
-
module Restfulie::Common::Builder::Rules::CustomAttributes
|
3
|
-
|
4
|
-
# returns true if it's a valid attribute evaluation or
|
5
|
-
def method_missing(sym, *args)
|
6
|
-
if sym.to_s.last=="=" && args.size==1
|
7
|
-
custom_attributes[sym.to_s.chop] = args[0]
|
8
|
-
elsif custom_attributes[sym.to_s]
|
9
|
-
custom_attributes[sym.to_s]
|
10
|
-
else
|
11
|
-
super(sym, *args)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def respond_to?(sym)
|
16
|
-
super(sym) || (sym.to_s.last == "=") || custom_attributes[sym.to_s]
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def custom_attributes
|
22
|
-
@custom_attributes ||= {}
|
23
|
-
end
|
24
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
class Restfulie::Common::Builder::Rules::Link
|
2
|
-
# Required
|
3
|
-
attr_accessor :href
|
4
|
-
|
5
|
-
# Optional
|
6
|
-
attr_accessor :rel, :type
|
7
|
-
attr_accessor :hreflang, :title, :length
|
8
|
-
|
9
|
-
# TODO: Inline resource and collection support
|
10
|
-
def initialize(options = {})
|
11
|
-
options = { :rel => options } unless options.kind_of?(Hash)
|
12
|
-
options.each do |k, i|
|
13
|
-
self.send("#{k}=".to_sym, i)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
def rel=(value)
|
18
|
-
@rel = value.kind_of?(String) ? value : value.to_s
|
19
|
-
end
|
20
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# Representation of a namespace. Allows any type of attribute setting and grabbing, i.e.:
|
2
|
-
#
|
3
|
-
# collection.namespace(:basket, "http://openbuy.com/basket") do |ns|
|
4
|
-
# ns.price = @basket.cost
|
5
|
-
# end
|
6
|
-
#
|
7
|
-
# or
|
8
|
-
#
|
9
|
-
# collection.describe_members(:namespaces => "http://localhost:3000/items") do |member, item|
|
10
|
-
# member.links << link( :rel => :self, :href => item_url(item))
|
11
|
-
# end
|
12
|
-
class Restfulie::Common::Builder::Rules::Namespace < Hash
|
13
|
-
attr_reader :namespace
|
14
|
-
attr_reader :uri
|
15
|
-
|
16
|
-
def initialize(ns, uri, *args)
|
17
|
-
@namespace = ns.to_sym
|
18
|
-
self.uri = uri
|
19
|
-
super(*args)
|
20
|
-
end
|
21
|
-
|
22
|
-
def uri=(value)
|
23
|
-
@uri = value
|
24
|
-
end
|
25
|
-
|
26
|
-
def method_missing(symbol, *args)
|
27
|
-
if ((key = symbol.to_s.match(/(.*)=/)) && args.size >= 1)
|
28
|
-
self[key[1].to_sym] = args.first
|
29
|
-
elsif(keys.include?(symbol))
|
30
|
-
self[symbol]
|
31
|
-
else
|
32
|
-
super
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|