wrest 2.1.9 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG +6 -0
- data/LICENCE +1 -1
- data/README.md +47 -40
- data/bin/wrest +2 -1
- data/bin/wrest_shell.rb +10 -8
- data/lib/wrest/async_request/event_machine_backend.rb +3 -1
- data/lib/wrest/async_request/thread_backend.rb +5 -2
- data/lib/wrest/async_request/thread_pool.rb +4 -2
- data/lib/wrest/async_request.rb +7 -6
- data/lib/wrest/cache_proxy.rb +39 -28
- data/lib/wrest/caching/memcached.rb +21 -18
- data/lib/wrest/caching/redis.rb +22 -22
- data/lib/wrest/caching.rb +16 -14
- data/lib/wrest/callback.rb +19 -16
- data/lib/wrest/components/container/alias_accessors.rb +51 -47
- data/lib/wrest/components/container/typecaster.rb +146 -95
- data/lib/wrest/components/container.rb +171 -152
- data/lib/wrest/components/mutators/base.rb +43 -34
- data/lib/wrest/components/mutators/camel_to_snake_case.rb +7 -3
- data/lib/wrest/components/mutators/{xml_mini_type_caster.rb → xml_type_caster.rb} +29 -16
- data/lib/wrest/components/mutators.rb +21 -19
- data/lib/wrest/components/translators/content_types.rb +20 -16
- data/lib/wrest/components/translators/json.rb +19 -16
- data/lib/wrest/components/translators/txt.rb +19 -15
- data/lib/wrest/components/translators/xml/conversions.rb +56 -0
- data/lib/wrest/components/translators/xml.rb +60 -18
- data/lib/wrest/components/translators.rb +7 -6
- data/lib/wrest/components.rb +11 -8
- data/lib/wrest/core_ext/hash/conversions.rb +10 -10
- data/lib/wrest/core_ext/hash.rb +4 -2
- data/lib/wrest/core_ext/string/conversions.rb +14 -13
- data/lib/wrest/core_ext/string.rb +5 -3
- data/lib/wrest/exceptions.rb +4 -2
- data/lib/wrest/hash_with_case_insensitive_access.rb +8 -8
- data/lib/wrest/hash_with_indifferent_access.rb +442 -0
- data/lib/wrest/http_codes.rb +20 -19
- data/lib/wrest/http_shared/headers.rb +2 -0
- data/lib/wrest/http_shared/standard_headers.rb +2 -2
- data/lib/wrest/http_shared/standard_tokens.rb +8 -6
- data/lib/wrest/http_shared.rb +5 -3
- data/lib/wrest/multipart.rb +20 -11
- data/lib/wrest/native/connection_factory.rb +15 -11
- data/lib/wrest/native/delete.rb +15 -11
- data/lib/wrest/native/get.rb +60 -55
- data/lib/wrest/native/options.rb +15 -11
- data/lib/wrest/native/patch.rb +27 -0
- data/lib/wrest/native/post.rb +15 -11
- data/lib/wrest/native/post_multipart.rb +22 -18
- data/lib/wrest/native/put.rb +16 -12
- data/lib/wrest/native/put_multipart.rb +22 -18
- data/lib/wrest/native/redirection.rb +13 -12
- data/lib/wrest/native/request.rb +144 -106
- data/lib/wrest/native/response.rb +87 -78
- data/lib/wrest/native/session.rb +49 -40
- data/lib/wrest/native.rb +14 -11
- data/lib/wrest/test/request_patches.rb +10 -3
- data/lib/wrest/test.rb +3 -1
- data/lib/wrest/uri/builders.rb +14 -12
- data/lib/wrest/uri.rb +92 -50
- data/lib/wrest/uri_template.rb +11 -7
- data/lib/wrest/utils.rb +129 -0
- data/lib/wrest/version.rb +3 -1
- data/lib/wrest.rb +31 -33
- data/lib/wrest_no_ext.rb +2 -0
- metadata +91 -56
- data/lib/wrest/components/mutators/xml_simple_type_caster.rb +0 -37
- data/lib/wrest/xml_mini/jdom/xpath_filter.rb +0 -17
- data/lib/wrest/xml_mini/jdom.rb +0 -6
- data/lib/wrest/xml_mini/libxml/xpath_filter.rb +0 -12
- data/lib/wrest/xml_mini/libxml.rb +0 -8
- data/lib/wrest/xml_mini/nokogiri/xpath_filter.rb +0 -15
- data/lib/wrest/xml_mini/nokogiri.rb +0 -7
- data/lib/wrest/xml_mini/rexml/xpath_filter.rb +0 -15
- data/lib/wrest/xml_mini/rexml.rb +0 -8
- data/lib/wrest/xml_mini.rb +0 -8
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -8,176 +10,193 @@
|
|
8
10
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
11
|
|
10
12
|
module Wrest
|
11
|
-
module Components
|
13
|
+
module Components
|
14
|
+
module Container
|
15
|
+
end
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
15
|
-
require
|
16
|
-
require
|
17
|
-
|
18
|
-
module Wrest::Components
|
19
|
-
|
20
|
-
# Adds behaviour allowing a class to
|
21
|
-
# contain attributes and providing support
|
22
|
-
# for dynamic getters, setters and query methods.
|
23
|
-
# These methods are added at runtime, on the first
|
24
|
-
# invocation and on a per instance basis.
|
25
|
-
# <tt>respond_to?</tt> however will respond as though
|
26
|
-
# they are all already present.
|
27
|
-
# This means that two different instances of the same
|
28
|
-
# Container could well have different attribute
|
29
|
-
# getters/setters/query methods.
|
30
|
-
#
|
31
|
-
# Note that the first call to a particular getter/setter/query
|
32
|
-
# method will be slower because the method is defined
|
33
|
-
# at that point; subsequent calls will be much faster.
|
34
|
-
#
|
35
|
-
# Also keep in mind that attribute getter/setter/query methods
|
36
|
-
# will _not_ override any existing methods on the class.
|
37
|
-
#
|
38
|
-
# In situations where this is a problem, such as a client consuming Rails
|
39
|
-
# REST services where <tt>id</tt> is a common attribute and clashes with
|
40
|
-
# Object#id, it is recommended to create getter/setter/query methods
|
41
|
-
# on the class (which affects all instances) using the +always_has+ macro.
|
42
|
-
#
|
43
|
-
# If you're implementing your own initialize method
|
44
|
-
# remember to delegate to the default initialize
|
45
|
-
# of Container by invoking <tt>super(attributes)</tt>
|
46
|
-
#
|
47
|
-
# Example:
|
48
|
-
# class ShenCoin
|
49
|
-
# include Wrest::Components::Container
|
50
|
-
# include Wrest::Components::Container::Typecaster
|
51
|
-
#
|
52
|
-
# always_has :id
|
53
|
-
# typecast :id => as_integer
|
54
|
-
# end
|
55
|
-
# coin = ShenCoin.new(:id => '5', :chi_count => 500, :owner => 'Kai Wren')
|
56
|
-
# coin.id # => 5
|
57
|
-
# coin.owner # => 'Kai Wren'
|
58
|
-
module Container
|
59
|
-
def self.included(klass) #:nodoc:
|
60
|
-
klass.extend Container::ClassMethods
|
61
|
-
klass.extend Container::Typecaster::Helpers
|
62
|
-
klass.class_eval do
|
63
|
-
include Container::InstanceMethods
|
64
|
-
include Container::AliasAccessors
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.build_attribute_getter(attribute_name) #:nodoc:
|
69
|
-
"def #{attribute_name};@attributes[:#{attribute_name}];end;"
|
70
|
-
end
|
19
|
+
require 'wrest/components/container/typecaster'
|
20
|
+
require 'wrest/components/container/alias_accessors'
|
71
21
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
22
|
+
module Wrest
|
23
|
+
module Components
|
24
|
+
# Adds behaviour allowing a class to
|
25
|
+
# contain attributes and providing support
|
26
|
+
# for dynamic getters, setters and query methods.
|
27
|
+
# These methods are added at runtime, on the first
|
28
|
+
# invocation and on a per instance basis.
|
29
|
+
# <tt>respond_to?</tt> however will respond as though
|
30
|
+
# they are all already present.
|
31
|
+
# This means that two different instances of the same
|
32
|
+
# Container could well have different attribute
|
33
|
+
# getters/setters/query methods.
|
34
|
+
#
|
35
|
+
# Note that the first call to a particular getter/setter/query
|
36
|
+
# method will be slower because the method is defined
|
37
|
+
# at that point; subsequent calls will be much faster.
|
38
|
+
#
|
39
|
+
# Also keep in mind that attribute getter/setter/query methods
|
40
|
+
# will _not_ override any existing methods on the class.
|
41
|
+
#
|
42
|
+
# In situations where this is a problem, such as a client consuming Rails
|
43
|
+
# REST services where <tt>id</tt> is a common attribute and clashes with
|
44
|
+
# Object#id, it is recommended to create getter/setter/query methods
|
45
|
+
# on the class (which affects all instances) using the +always_has+ macro.
|
46
|
+
#
|
47
|
+
# If you're implementing your own initialize method
|
48
|
+
# remember to delegate to the default initialize
|
49
|
+
# of Container by invoking <tt>super(attributes)</tt>
|
50
|
+
#
|
51
|
+
# Example:
|
52
|
+
# class ShenCoin
|
53
|
+
# include Wrest::Components::Container
|
54
|
+
# include Wrest::Components::Container::Typecaster
|
55
|
+
#
|
56
|
+
# always_has :id
|
57
|
+
# typecast :id => as_integer
|
58
|
+
# end
|
59
|
+
# coin = ShenCoin.new(:id => '5', :chi_count => 500, :owner => 'Kai Wren')
|
60
|
+
# coin.id # => 5
|
61
|
+
# coin.owner # => 'Kai Wren'
|
62
|
+
module Container
|
63
|
+
def self.included(klass) # :nodoc:
|
64
|
+
klass.extend Container::ClassMethods
|
65
|
+
klass.extend Container::Typecaster::Helpers
|
66
|
+
klass.class_eval do
|
67
|
+
include Container::InstanceMethods
|
68
|
+
include Container::AliasAccessors
|
95
69
|
end
|
96
70
|
end
|
97
|
-
|
98
|
-
# This is a convenience macro which includes
|
99
|
-
# Wrest::Components::Container::Typecaster into
|
100
|
-
# the class (effectively overwriting this method) before delegating to
|
101
|
-
# the actual typecast method that is a part of that module.
|
102
|
-
# This saves us the effort of explicitly doing the include. Easy to use API is king.
|
103
|
-
#
|
104
|
-
# Remember that using typecast carries a performance penalty.
|
105
|
-
# See Wrest::Components::Container::Typecaster for the actual docs.
|
106
|
-
def typecast(cast_map)
|
107
|
-
self.class_eval{ include Wrest::Components::Container::Typecaster }
|
108
|
-
self.typecast cast_map
|
109
|
-
end
|
110
|
-
|
111
|
-
# This is the name of the class in snake-case, with any parent
|
112
|
-
# module names removed.
|
113
|
-
#
|
114
|
-
# The class will use as the root element when
|
115
|
-
# serialised to xml after replacing underscores with hyphens.
|
116
|
-
#
|
117
|
-
# This method can be overidden should you need a different name.
|
118
|
-
def element_name
|
119
|
-
@element_name ||= ActiveSupport::Inflector.demodulize(self.name).underscore.underscore
|
120
|
-
end
|
121
|
-
end
|
122
71
|
|
123
|
-
|
124
|
-
|
125
|
-
# an attributes container by creating
|
126
|
-
# two variables, @attributes and @interface.
|
127
|
-
# Remember not to use these two variable names
|
128
|
-
# when using Container in your own class.
|
129
|
-
def initialize(attributes = {})
|
130
|
-
@attributes = HashWithIndifferentAccess.new(attributes)
|
131
|
-
end
|
132
|
-
|
133
|
-
# A translator is a anything that knows how to serialise a
|
134
|
-
# Hash. It must needs have a method named 'serialise' that
|
135
|
-
# accepts a hash and configuration options, and returns the serialised
|
136
|
-
# result (leaving the hash unchanged, of course).
|
137
|
-
#
|
138
|
-
# Examples for JSON and XML can be found under Wrest::Components::Translators.
|
139
|
-
# These serialised output of these translators will work out of the box for Rails
|
140
|
-
# applications; you may need to roll your own for anything else.
|
141
|
-
#
|
142
|
-
# Note: When serilising to XML, if you want the name of the class as the name of the root node
|
143
|
-
# then you should use the Container#to_xml helper.
|
144
|
-
def serialise_using(translator, options = {})
|
145
|
-
translator.serialise(@attributes, options)
|
72
|
+
def self.build_attribute_getter(attribute_name) # :nodoc:
|
73
|
+
"def #{attribute_name};@attributes[:#{attribute_name}];end;"
|
146
74
|
end
|
147
|
-
|
148
|
-
def
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
def [](key)
|
153
|
-
@attributes[key.to_sym]
|
75
|
+
|
76
|
+
def self.build_attribute_setter(attribute_name) # :nodoc:
|
77
|
+
"def #{attribute_name}=(value);@attributes[:#{attribute_name}] = value;end;"
|
154
78
|
end
|
155
79
|
|
156
|
-
def
|
157
|
-
@attributes[
|
80
|
+
def self.build_attribute_queryer(attribute_name) # :nodoc:
|
81
|
+
"def #{attribute_name}?;not @attributes[:#{attribute_name}].nil?;end;"
|
158
82
|
end
|
159
83
|
|
160
|
-
|
161
|
-
|
84
|
+
module ClassMethods
|
85
|
+
# This macro explicitly creates getter, setter and query methods on
|
86
|
+
# an Container, overriding any existing methods with the same names.
|
87
|
+
# This can be used when attribute names clash with existing method names;
|
88
|
+
# an example would be Rails REST resources which frequently make use
|
89
|
+
# an attribute named <tt>id</tt> which clashes with Object#id. Also,
|
90
|
+
# this can be used as a performance optimisation if the incoming
|
91
|
+
# attributes are known beforehand.
|
92
|
+
def always_has(*attribute_names)
|
93
|
+
attribute_names.each do |attribute_name|
|
94
|
+
class_eval(
|
95
|
+
Container.build_attribute_getter(attribute_name) +
|
96
|
+
Container.build_attribute_setter(attribute_name) +
|
97
|
+
Container.build_attribute_queryer(attribute_name)
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# This is a convenience macro which includes
|
103
|
+
# Wrest::Components::Container::Typecaster into
|
104
|
+
# the class (effectively overwriting this method) before delegating to
|
105
|
+
# the actual typecast method that is a part of that module.
|
106
|
+
# This saves us the effort of explicitly doing the include. Easy to use API is king.
|
107
|
+
#
|
108
|
+
# Remember that using typecast carries a performance penalty.
|
109
|
+
# See Wrest::Components::Container::Typecaster for the actual docs.
|
110
|
+
def typecast(cast_map)
|
111
|
+
class_eval { include Wrest::Components::Container::Typecaster }
|
112
|
+
typecast cast_map
|
113
|
+
end
|
114
|
+
|
115
|
+
# This is the name of the class in snake-case, with any parent
|
116
|
+
# module names removed.
|
117
|
+
#
|
118
|
+
# The class will use as the root element when
|
119
|
+
# serialised to xml after replacing underscores with hyphens.
|
120
|
+
#
|
121
|
+
# This method can be overidden should you need a different name.
|
122
|
+
def element_name
|
123
|
+
@element_name ||= Utils.string_underscore(Utils.string_demodulize(name))
|
124
|
+
end
|
162
125
|
end
|
163
126
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
127
|
+
module InstanceMethods
|
128
|
+
# Sets up any class to act like
|
129
|
+
# an attributes container by creating
|
130
|
+
# two variables, @attributes and @interface.
|
131
|
+
# Remember not to use these two variable names
|
132
|
+
# when using Container in your own class.
|
133
|
+
def initialize(attributes = {})
|
134
|
+
@attributes = HashWithIndifferentAccess.new(attributes)
|
135
|
+
end
|
136
|
+
|
137
|
+
# A translator is a anything that knows how to serialise a
|
138
|
+
# Hash. It must needs have a method named 'serialise' that
|
139
|
+
# accepts a hash and configuration options, and returns the serialised
|
140
|
+
# result (leaving the hash unchanged, of course).
|
141
|
+
#
|
142
|
+
# Examples for JSON and XML can be found under Wrest::Components::Translators.
|
143
|
+
# These serialised output of these translators will work out of the box for Rails
|
144
|
+
# applications; you may need to roll your own for anything else.
|
145
|
+
#
|
146
|
+
# Note: When serilising to XML, if you want the name of the class as the name of the root node
|
147
|
+
# then you should use the Container#to_xml helper.
|
148
|
+
def serialise_using(translator, options = {})
|
149
|
+
payload = {
|
150
|
+
self.class.element_name => @attributes.dup
|
151
|
+
}
|
152
|
+
translator.serialise(payload, options)
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_xml(options = {})
|
156
|
+
serialise_using(Wrest::Components::Translators::Xml, { root: self.class.element_name }.merge(options))
|
157
|
+
end
|
158
|
+
|
159
|
+
def [](key)
|
160
|
+
@attributes[key.to_sym]
|
161
|
+
end
|
162
|
+
|
163
|
+
def []=(key, value)
|
164
|
+
@attributes[key.to_sym] = value
|
165
|
+
end
|
166
|
+
|
167
|
+
def respond_to_missing?(method_name, *)
|
168
|
+
if super.respond_to?(method_name)
|
169
|
+
true
|
170
|
+
else
|
171
|
+
@attributes.include?(method_name.to_s.gsub(/(\?$)|(=$)/,
|
172
|
+
'').to_sym)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Creates getter, setter and query methods for
|
177
|
+
# attributes on the first call.
|
178
|
+
def method_missing(method_sym, *arguments)
|
179
|
+
method_name = method_sym.to_s
|
180
|
+
attribute_name = method_name.gsub(/(\?$)|(=$)/, '')
|
181
|
+
if @attributes.include?(attribute_name.to_sym) || method_name[-1] == '=' || method_name[-1] == '?'
|
182
|
+
generate_methods!(attribute_name, method_name)
|
183
|
+
send(method_sym, *arguments)
|
184
|
+
else
|
185
|
+
super(method_sym, *arguments)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
def generate_methods!(attribute_name, method_name)
|
192
|
+
case method_name[-1]
|
171
193
|
when '='
|
172
|
-
|
194
|
+
instance_eval Container.build_attribute_setter(attribute_name)
|
173
195
|
when '?'
|
174
|
-
|
196
|
+
instance_eval Container.build_attribute_queryer(attribute_name)
|
175
197
|
else
|
176
|
-
|
198
|
+
instance_eval Container.build_attribute_getter(attribute_name)
|
177
199
|
end
|
178
|
-
send(method_sym, *arguments)
|
179
|
-
else
|
180
|
-
super(method_sym, *arguments)
|
181
200
|
end
|
182
201
|
end
|
183
202
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -13,43 +15,50 @@ module Wrest
|
|
13
15
|
# hash mutator that ensures that the <tt>mutate</tt> method
|
14
16
|
# will chain to the next mutator by using a
|
15
17
|
# template method.
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# Registers all subclasses of Mutators::Base in
|
20
|
-
# Mutators::REGISTRY making it easy to reference
|
21
|
-
# and chain them later.
|
22
|
-
#
|
23
|
-
# See Mutators#chain for more information.
|
24
|
-
def self.inherited(subklass)
|
25
|
-
Wrest::Components::Mutators::REGISTRY[subklass.name.demodulize.underscore.to_sym] = subklass unless subklass.name.blank?
|
26
|
-
end
|
18
|
+
module Mutators
|
19
|
+
class Base
|
20
|
+
attr_reader :next_mutator
|
27
21
|
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
# Registers all subclasses of Mutators::Base in
|
23
|
+
# Mutators::REGISTRY making it easy to reference
|
24
|
+
# and chain them later.
|
25
|
+
#
|
26
|
+
# See Mutators#chain for more information.
|
27
|
+
def self.inherited(subklass)
|
28
|
+
super
|
29
|
+
return if Utils.string_blank?(subklass.name)
|
31
30
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
31
|
+
key = Utils.string_underscore(Utils.string_demodulize(subklass.name)).to_sym
|
32
|
+
Wrest::Components::Mutators.registry[key] = subklass
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(next_mutator = nil)
|
36
|
+
@next_mutator = next_mutator
|
37
|
+
end
|
38
|
+
|
39
|
+
# This is a template method which operates on a tuple (well, pair)
|
40
|
+
# from a hash map and guarantees mutator chaining.
|
41
|
+
#
|
42
|
+
# Iterating over any hash using <tt>each</tt> injects
|
43
|
+
# each key/value pair from the hash in the
|
44
|
+
# form of an array.
|
45
|
+
# This method expects of this form as an argument, i.e.
|
46
|
+
# an array with the structure [:key, :value]
|
47
|
+
#
|
48
|
+
# The implementation of the mutation is achieved by
|
49
|
+
# overriding the <tt>do_mutate</tt> method in a subclass.
|
50
|
+
# Note that failing to do so will result in an exception
|
51
|
+
# at runtime.
|
52
|
+
def mutate(tuple)
|
53
|
+
out_tuple = do_mutate(tuple)
|
54
|
+
next_mutator ? next_mutator.mutate(out_tuple) : out_tuple
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
49
58
|
|
50
|
-
|
51
|
-
|
52
|
-
|
59
|
+
def do_mutate(_tuple)
|
60
|
+
raise Wrest::Exceptions::MethodNotOverridden
|
61
|
+
end
|
53
62
|
end
|
54
63
|
end
|
55
64
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -13,9 +15,11 @@ module Wrest
|
|
13
15
|
#
|
14
16
|
# Example:
|
15
17
|
# Mutators::CamelToSnakeCase.new.mutate(['Spirit-Sword', 'true']) # => ['spirit_sword', 'true']**
|
16
|
-
|
17
|
-
|
18
|
-
|
18
|
+
module Mutators
|
19
|
+
class CamelToSnakeCase < Mutators::Base
|
20
|
+
def do_mutate(tuple)
|
21
|
+
[Utils.string_underscore(tuple.first), tuple.last]
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
@@ -7,36 +9,47 @@
|
|
7
9
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
10
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
11
|
|
10
|
-
|
11
12
|
module Wrest
|
12
13
|
module Components
|
13
14
|
# This mutator undertands how do type casting
|
14
15
|
# using the type data embedded in a hash
|
15
16
|
# created by deserialising an xml using
|
16
17
|
# ActiveSupport::XmlMini
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
module Mutators
|
19
|
+
class XmlTypeCaster < Mutators::Base
|
20
|
+
def do_mutate(tuple)
|
21
|
+
out_key, in_value = tuple
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
+
out_value = case in_value
|
24
|
+
when Hash
|
25
|
+
process_hash_value(in_value)
|
26
|
+
when Array
|
27
|
+
in_value.collect { |hash| hash.mutate_using(self) }
|
28
|
+
else
|
29
|
+
in_value
|
30
|
+
end
|
31
|
+
|
32
|
+
[out_key, out_value]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def process_hash_value(in_value)
|
23
38
|
if in_value['nil'] == 'true'
|
24
|
-
|
39
|
+
nil
|
25
40
|
elsif in_value.key?('type')
|
26
|
-
|
27
|
-
out_value = caster ? caster.call(in_value['__content__']) : in_value
|
41
|
+
typecast_value(in_value)
|
28
42
|
elsif in_value.key?('__content__')
|
29
|
-
|
43
|
+
in_value['__content__']
|
30
44
|
else
|
31
|
-
|
45
|
+
in_value.mutate_using(self)
|
32
46
|
end
|
33
|
-
when Array
|
34
|
-
out_value = in_value.collect{|hash| hash.mutate_using(self)}
|
35
|
-
else
|
36
|
-
out_value = in_value
|
37
47
|
end
|
38
48
|
|
39
|
-
|
49
|
+
def typecast_value(in_value)
|
50
|
+
caster = Container::Typecaster::PARSING[in_value['type']]
|
51
|
+
caster ? caster.call(in_value['__content__']) : in_value
|
52
|
+
end
|
40
53
|
end
|
41
54
|
end
|
42
55
|
end
|
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
-
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
7
|
-
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
|
-
# See the License for the specific language governing permissions and limitations under the License.
|
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 http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
9
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
9
11
|
|
10
12
|
module Wrest
|
11
13
|
module Components
|
@@ -15,26 +17,26 @@ module Wrest
|
|
15
17
|
module Mutators
|
16
18
|
# All sublasses of Mutators::Base are automatically
|
17
19
|
# registered here by underscored, symbolised class name.
|
18
|
-
|
19
|
-
|
20
|
+
def self.registry
|
21
|
+
@registry ||= {}
|
22
|
+
end
|
23
|
+
|
20
24
|
# Makes referencing and chaining mutators easy.
|
21
|
-
#
|
25
|
+
#
|
22
26
|
# Example:
|
23
|
-
# Mutators.chain(:
|
27
|
+
# Mutators.chain(:xml_type_caster, :camel_to_snake_case)
|
24
28
|
# is equivalent to
|
25
|
-
# Wrest::Components::Mutators::
|
29
|
+
# Wrest::Components::Mutators::XmlTypeCaster.new(Wrest::Components::Mutators::CamelToSnakeCase.new)
|
26
30
|
def self.chain(*mutator_keys)
|
27
31
|
mutator_key = mutator_keys.pop
|
28
|
-
mutator_keys.reverse.inject(
|
29
|
-
|
32
|
+
mutator_keys.reverse.inject(registry[mutator_key].new) do |next_instance, next_key|
|
33
|
+
registry[next_key].new(next_instance)
|
30
34
|
end
|
31
35
|
end
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
35
|
-
require
|
36
|
-
require
|
37
|
-
require
|
38
|
-
require
|
39
|
-
require "wrest/components/mutators/camel_to_snake_case"
|
40
|
-
|
39
|
+
require 'wrest/core_ext/hash'
|
40
|
+
require 'wrest/components/mutators/base'
|
41
|
+
require 'wrest/components/mutators/xml_type_caster'
|
42
|
+
require 'wrest/components/mutators/camel_to_snake_case'
|
@@ -1,21 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2009 Sidu Ponnappa
|
2
4
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
-
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
7
|
-
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
|
-
# See the License for the specific language governing permissions and limitations under the License.
|
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 http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
9
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
9
11
|
|
10
12
|
module Wrest
|
11
|
-
module Components
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
module Components
|
14
|
+
module Translators
|
15
|
+
# Maps content types to deserialisers
|
16
|
+
CONTENT_TYPES = {
|
17
|
+
'application/xml' => Wrest::Components::Translators::Xml,
|
18
|
+
'text/xml' => Wrest::Components::Translators::Xml,
|
19
|
+
'application/json' => Wrest::Components::Translators::Json,
|
20
|
+
'text/javascript' => Wrest::Components::Translators::Json,
|
21
|
+
'text/plain' => Wrest::Components::Translators::Txt
|
22
|
+
}.freeze
|
23
|
+
end
|
20
24
|
end
|
21
|
-
end
|
25
|
+
end
|