wrest 3.0.0 → 4.0.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.
- checksums.yaml +5 -5
- data/CHANGELOG +3 -0
- data/LICENCE +1 -1
- data/README.md +29 -28
- 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 -96
- 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 -56
- data/lib/wrest/native/options.rb +15 -11
- data/lib/wrest/native/patch.rb +16 -12
- 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 -108
- data/lib/wrest/native/response.rb +87 -78
- data/lib/wrest/native/session.rb +49 -40
- data/lib/wrest/native.rb +14 -12
- 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 +70 -52
- 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 +98 -48
- 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
|