wrest 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +31 -17
- data/Rakefile +147 -134
- data/VERSION.yml +1 -1
- data/bin/jwrest +3 -0
- data/bin/wrest +1 -20
- data/bin/wrest_shell.rb +21 -0
- data/lib/wrest/components.rb +4 -1
- data/lib/wrest/components/attributes_container.rb +65 -10
- data/lib/wrest/{translators/xml.rb → components/mutators.rb} +11 -13
- data/lib/wrest/components/mutators/base.rb +43 -0
- data/lib/wrest/components/mutators/camel_to_snake_case.rb +20 -0
- data/lib/wrest/components/mutators/xml_simple_type_caster.rb +35 -0
- data/lib/wrest/{translators.rb → components/translators.rb} +6 -7
- data/lib/wrest/{translators → components/translators}/content_types.rb +5 -5
- data/lib/wrest/components/translators/json.rb +22 -0
- data/lib/wrest/components/translators/xml.rb +26 -0
- data/lib/wrest/components/typecast_helpers.rb +41 -0
- data/lib/wrest/core_ext/hash.rb +5 -0
- data/lib/wrest/core_ext/hash/conversions.rb +44 -0
- data/lib/wrest/exceptions.rb +6 -1
- data/lib/wrest/exceptions/method_not_overridden_exception.rb +17 -0
- data/lib/wrest/exceptions/unsupported_content_type_exception.rb +11 -9
- data/lib/wrest/resource/base.rb +5 -1
- data/lib/wrest/response.rb +2 -2
- data/lib/wrest/uri.rb +3 -3
- data/lib/wrest/version.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/wrest/components/attributes_container_spec.rb +66 -11
- data/spec/wrest/components/mutators/base_spec.rb +38 -0
- data/spec/wrest/components/mutators/camel_to_snake_spec.rb +22 -0
- data/spec/wrest/components/mutators/xml_simple_type_caster_spec.rb +47 -0
- data/spec/wrest/{translators → components/translators}/xml_spec.rb +3 -3
- data/spec/wrest/components/translators_spec.rb +9 -0
- data/spec/wrest/core_ext/hash/conversions_spec.rb +22 -0
- data/{lib/wrest/translators/json.rb → spec/wrest/core_ext/string/conversions_spec.rb} +4 -9
- data/spec/wrest/resource/base_spec.rb +1 -1
- data/spec/wrest/response_spec.rb +3 -3
- data/spec/wrest/uri_spec.rb +2 -2
- metadata +34 -19
- data/lib/wrest/translators/typed_hash.rb +0 -4
- data/spec/wrest/core_ext/string_spec.rb +0 -7
- data/spec/wrest/translators/typed_hash_spec.rb +0 -9
- data/spec/wrest/translators_spec.rb +0 -9
data/bin/wrest_shell.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
puts "Ruby #{RUBY_VERSION}, #{RUBY_RELEASE_DATE}, #{RUBY_PLATFORM}"
|
2
|
+
|
3
|
+
entry_point = "#{File.dirname(__FILE__)}/../lib/wrest.rb"
|
4
|
+
version = "#{File.dirname(__FILE__)}/../lib/wrest/version"
|
5
|
+
|
6
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
7
|
+
|
8
|
+
require 'optparse'
|
9
|
+
options = { :irb => irb }
|
10
|
+
OptionParser.new do |opt|
|
11
|
+
opt.banner = "Usage: console [options]"
|
12
|
+
opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
|
13
|
+
opt.parse!(ARGV)
|
14
|
+
end
|
15
|
+
|
16
|
+
libs = " -r irb/completion"
|
17
|
+
libs << " -r #{entry_point}"
|
18
|
+
|
19
|
+
require version
|
20
|
+
puts "Loading Wrest #{Wrest::VERSION::STRING}"
|
21
|
+
exec "#{options[:irb]} #{libs} --simple-prompt"
|
data/lib/wrest/components.rb
CHANGED
@@ -15,4 +15,7 @@ module Wrest #:nodoc:
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
require "#{WREST_ROOT}/wrest/components/
|
18
|
+
require "#{WREST_ROOT}/wrest/components/typecast_helpers"
|
19
|
+
require "#{WREST_ROOT}/wrest/components/attributes_container"
|
20
|
+
require "#{WREST_ROOT}/wrest/components/mutators"
|
21
|
+
require "#{WREST_ROOT}/wrest/components/translators"
|
@@ -17,26 +17,39 @@ module Wrest::Components #:nodoc:
|
|
17
17
|
# <tt>respond_to?</tt> however will respond as though
|
18
18
|
# they are all already present.
|
19
19
|
# This means that two different instances of the same
|
20
|
-
#
|
20
|
+
# AttributesContainer could well have
|
21
21
|
# different attribute getters/setters/query methods.
|
22
|
-
#
|
23
|
-
# Note that
|
22
|
+
#
|
23
|
+
# Note that the first call to a particular getter/setter/query
|
24
24
|
# method will be slower because the method is defined
|
25
25
|
# at that point; subsequent calls will be much faster.
|
26
26
|
#
|
27
|
-
# If you're implementing your own initialize method
|
28
|
-
# remember to delegate to the default initialize
|
29
|
-
# of AttributesContainer by invoking <tt>super(attributes)</tt>
|
30
27
|
# Also keep in mind that attribute getter/setter/query methods
|
31
28
|
# will _not_ override any existing methods on the class.
|
32
29
|
#
|
33
30
|
# In situations where this is a problem, such as a client consuming Rails
|
34
31
|
# REST services where <tt>id</tt> is a common attribute and clashes with
|
35
|
-
# Object#id it is recommended to create getter/setter/query methods
|
36
|
-
# on the class (which affects all instances) using the
|
32
|
+
# Object#id, it is recommended to create getter/setter/query methods
|
33
|
+
# on the class (which affects all instances) using the +has_attributes+ macro.
|
34
|
+
#
|
35
|
+
# If you're implementing your own initialize method
|
36
|
+
# remember to delegate to the default initialize
|
37
|
+
# of AttributesContainer by invoking <tt>super(attributes)</tt>
|
38
|
+
#
|
39
|
+
# Example:
|
40
|
+
# class ShenCoin
|
41
|
+
# include Wrest::Components::AttributesContainer
|
42
|
+
#
|
43
|
+
# has_attributes :id
|
44
|
+
# typecast :id => as_integer
|
45
|
+
# end
|
46
|
+
# coin = ShenCoin.new(:id => '5', :chi_count => 500, :owner => 'Kai Wren')
|
47
|
+
# coin.id # => 5
|
48
|
+
# coin.owner # => 'Kai Wren'
|
37
49
|
module AttributesContainer
|
38
50
|
def self.included(klass) #:nodoc:
|
39
51
|
klass.extend AttributesContainer::ClassMethods
|
52
|
+
klass.extend TypecastHelpers
|
40
53
|
klass.class_eval{ include AttributesContainer::InstanceMethods }
|
41
54
|
end
|
42
55
|
|
@@ -59,8 +72,7 @@ module Wrest::Components #:nodoc:
|
|
59
72
|
# an example would be Rails REST services which frequently make use
|
60
73
|
# an attribute named <tt>id</tt> which clashes with Object#id. Also,
|
61
74
|
# this can be used as a performance optimisation if the incoming
|
62
|
-
# attributes are known beforehand
|
63
|
-
# invocation is no longer necessary.
|
75
|
+
# attributes are known beforehand.
|
64
76
|
def has_attributes(*attribute_names)
|
65
77
|
attribute_names.each do |attribute_name|
|
66
78
|
self.class_eval(
|
@@ -70,6 +82,45 @@ module Wrest::Components #:nodoc:
|
|
70
82
|
)
|
71
83
|
end
|
72
84
|
end
|
85
|
+
|
86
|
+
# Accepts a set of attribute-name/lambda pairs which are used
|
87
|
+
# to typecast string values injected through the constructor.
|
88
|
+
# Typically needed when populating an +AttributesContainer+
|
89
|
+
# directly from request params. Typecasting kicks in for
|
90
|
+
# a given value _only_ if it is a string.
|
91
|
+
#
|
92
|
+
# Typcast information is inherited by subclasses; however be
|
93
|
+
# aware that explicitly invoking +typecast+ in a subclass will
|
94
|
+
# discard inherited typecast information leaving only the casts
|
95
|
+
# defined in the subclass.
|
96
|
+
#
|
97
|
+
# Common typecasts such as integer, float, datetime etc. are
|
98
|
+
# available through predefined helpers. See TypecastHelpers
|
99
|
+
# for a full list.
|
100
|
+
#
|
101
|
+
# Example:
|
102
|
+
#
|
103
|
+
# class Demon
|
104
|
+
# include Wrest::Components::AttributesContainer
|
105
|
+
# typecast :age => as_integer,
|
106
|
+
# :chi => lambda{|chi| Chi.new(chi)}
|
107
|
+
# end
|
108
|
+
# kai_wren = Demon.new('age' => '1500', 'chi' => '1024')
|
109
|
+
# kai_wren.age # => 1500
|
110
|
+
# kai_wren.chi # => #<Chi:0x113af8c @count="1024">
|
111
|
+
def typecast(cast_map)
|
112
|
+
@typecast_map = @typecast_map ? @typecast_map.merge(cast_map.symbolize_keys) : cast_map.symbolize_keys
|
113
|
+
end
|
114
|
+
|
115
|
+
def typecast_map #:nodoc:
|
116
|
+
if defined?(@typecast_map)
|
117
|
+
@typecast_map
|
118
|
+
elsif superclass != Object && superclass.respond_to?(:typecast_map)
|
119
|
+
superclass.typecast_map
|
120
|
+
else
|
121
|
+
{}
|
122
|
+
end
|
123
|
+
end
|
73
124
|
end
|
74
125
|
|
75
126
|
module InstanceMethods
|
@@ -81,6 +132,10 @@ module Wrest::Components #:nodoc:
|
|
81
132
|
# own class.
|
82
133
|
def initialize(attributes = {})
|
83
134
|
@attributes = attributes.symbolize_keys
|
135
|
+
self.class.typecast_map.each do |key, typecaster|
|
136
|
+
value = @attributes[key]
|
137
|
+
@attributes[key] = typecaster.call(value) if value.is_a?(String)
|
138
|
+
end
|
84
139
|
@interface = Module.new
|
85
140
|
self.extend @interface
|
86
141
|
end
|
@@ -7,18 +7,16 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
XmlSimple.xml_in(
|
18
|
-
response.body,
|
19
|
-
'keeproot' => true
|
20
|
-
)
|
21
|
-
}
|
10
|
+
module Wrest #:nodoc:
|
11
|
+
module Components
|
12
|
+
# A mutator understands how to transform
|
13
|
+
# one tuple(key/value pair) from a hash
|
14
|
+
# into another
|
15
|
+
module Mutators
|
16
|
+
end
|
22
17
|
end
|
23
18
|
end
|
24
|
-
|
19
|
+
|
20
|
+
require "#{WREST_ROOT}/wrest/components/mutators/base"
|
21
|
+
require "#{WREST_ROOT}/wrest/components/mutators/xml_simple_type_caster"
|
22
|
+
require "#{WREST_ROOT}/wrest/components/mutators/camel_to_snake_case"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
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.
|
9
|
+
|
10
|
+
# This is a base implementation of a
|
11
|
+
# hash mutator that ensures that the <tt>mutate</tt> method
|
12
|
+
# will chain to the next mutator by using a
|
13
|
+
# template method.
|
14
|
+
class Wrest::Components::Mutators::Base
|
15
|
+
attr_reader :next_mutator
|
16
|
+
|
17
|
+
def initialize(next_mutator = nil)
|
18
|
+
@next_mutator = next_mutator
|
19
|
+
end
|
20
|
+
|
21
|
+
# This is a template method which operates on a tuple (well, pair)
|
22
|
+
# from a hash map and guarantees mutator chaining.
|
23
|
+
#
|
24
|
+
# Iterating over any hash using <tt>each</tt> injects
|
25
|
+
# each key/value pair from the hash in the
|
26
|
+
# form of an array.
|
27
|
+
# This method expects of this form as an argument, i.e.
|
28
|
+
# an array with the structure [:key, :value]
|
29
|
+
#
|
30
|
+
# The implementation of the mutation is achieved by
|
31
|
+
# overriding the <tt>do_mutate</tt> method in a subclass.
|
32
|
+
# Note that failing to do so will result in an exception
|
33
|
+
# at runtime.
|
34
|
+
def mutate(tuple)
|
35
|
+
out_tuple = do_mutate(tuple)
|
36
|
+
next_mutator ? next_mutator.mutate(out_tuple) : out_tuple
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def do_mutate(tuple)
|
41
|
+
raise Wrest::Exceptions::MethodNotOverriddenException
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
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.
|
9
|
+
|
10
|
+
module Wrest::Components
|
11
|
+
class Mutators::CamelToSnakeCase < Mutators::Base
|
12
|
+
# Converts the key to snake case
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
# Mutators::CamelToSnakeCase.new.mutate(['Spirit-Sword', 'true']) # => ['spirit_sword', 'true']
|
16
|
+
def do_mutate(tuple)
|
17
|
+
[tuple.first.underscore, tuple.last]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
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.
|
9
|
+
|
10
|
+
# This mutator undertands how do type casting
|
11
|
+
# using the type data embedded in a hash
|
12
|
+
# created by deserialising an xml using
|
13
|
+
# xml-simple
|
14
|
+
module Wrest::Components
|
15
|
+
class Mutators::XmlSimpleTypeCaster < Mutators::Base
|
16
|
+
def do_mutate(tuple)
|
17
|
+
out_key = tuple.first
|
18
|
+
in_value = tuple.last[0]
|
19
|
+
out_value = in_value
|
20
|
+
|
21
|
+
case in_value
|
22
|
+
when Hash
|
23
|
+
if in_value['nil'] == 'true'
|
24
|
+
out_value = nil
|
25
|
+
elsif in_value.key?('type')
|
26
|
+
out_value = ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING[in_value['type']].call(in_value['content'])
|
27
|
+
else
|
28
|
+
out_value = in_value.mutate_using(self)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
[out_key, out_value]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -7,20 +7,19 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest
|
10
|
+
module Wrest::Components #:nodoc:
|
11
11
|
# Contains strategies/lambdas which know how to deserialise
|
12
12
|
# different content types.
|
13
13
|
module Translators
|
14
14
|
# Loads the appropriate desirialisation strategy based on
|
15
15
|
# the content type
|
16
|
-
def self.
|
16
|
+
def self.lookup(content_type)
|
17
17
|
translator = CONTENT_TYPES[content_type]
|
18
|
-
translator || (raise UnsupportedContentTypeException.new("Unsupported content type #{content_type}"))
|
18
|
+
translator || (raise Wrest::Exceptions::UnsupportedContentTypeException.new("Unsupported content type #{content_type}"))
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
require "#{WREST_ROOT}/wrest/translators/xml"
|
24
|
-
require "#{WREST_ROOT}/wrest/translators/json"
|
25
|
-
require "#{WREST_ROOT}/wrest/translators/content_types"
|
26
|
-
require "#{WREST_ROOT}/wrest/translators/typed_hash"
|
23
|
+
require "#{WREST_ROOT}/wrest/components/translators/xml"
|
24
|
+
require "#{WREST_ROOT}/wrest/components/translators/json"
|
25
|
+
require "#{WREST_ROOT}/wrest/components/translators/content_types"
|
@@ -7,14 +7,14 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest
|
10
|
+
module Wrest::Components
|
11
11
|
module Translators
|
12
12
|
# Maps content types to deserialisers
|
13
13
|
CONTENT_TYPES = {
|
14
|
-
'application/xml' => Wrest::Translators::Xml,
|
15
|
-
'text/xml' => Wrest::Translators::Xml,
|
16
|
-
'application/json' => Wrest::Translators::Json,
|
17
|
-
'text/javascript' => Wrest::Translators::Json
|
14
|
+
'application/xml' => Wrest::Components::Translators::Xml,
|
15
|
+
'text/xml' => Wrest::Components::Translators::Xml,
|
16
|
+
'application/json' => Wrest::Components::Translators::Json,
|
17
|
+
'text/javascript' => Wrest::Components::Translators::Json
|
18
18
|
}
|
19
19
|
end
|
20
20
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
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.
|
9
|
+
|
10
|
+
module Wrest::Components::Translators
|
11
|
+
module Json
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def deserialise(response)
|
15
|
+
ActiveSupport::JSON.decode(response.body)
|
16
|
+
end
|
17
|
+
|
18
|
+
def serialise(hash)
|
19
|
+
ActiveSupport::JSON.encode(hash)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
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.
|
9
|
+
|
10
|
+
require 'xmlsimple'
|
11
|
+
|
12
|
+
module Wrest::Components::Translators
|
13
|
+
module Xml
|
14
|
+
extend self
|
15
|
+
|
16
|
+
def deserialise(response)
|
17
|
+
XmlSimple.xml_in(
|
18
|
+
response.body,
|
19
|
+
'keeproot' => true
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def serialise(hash)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Wrest::Components #:nodoc:
|
2
|
+
# Provides helper methods which build lambdas
|
3
|
+
# to cast strings to specific types.
|
4
|
+
module TypecastHelpers
|
5
|
+
def as_base64Binary
|
6
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['base64Binary']
|
7
|
+
end
|
8
|
+
|
9
|
+
def as_boolean
|
10
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['boolean']
|
11
|
+
end
|
12
|
+
|
13
|
+
def as_decimal
|
14
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['decimal']
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_date
|
18
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['date']
|
19
|
+
end
|
20
|
+
|
21
|
+
def as_datetime
|
22
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['datetime']
|
23
|
+
end
|
24
|
+
|
25
|
+
def as_float
|
26
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['float']
|
27
|
+
end
|
28
|
+
|
29
|
+
def as_integer
|
30
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['integer']
|
31
|
+
end
|
32
|
+
|
33
|
+
def as_symbol
|
34
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['symbol']
|
35
|
+
end
|
36
|
+
|
37
|
+
def as_yaml
|
38
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['yaml']
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
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.
|
9
|
+
|
10
|
+
module Wrest
|
11
|
+
module CoreExt #:nodoc:
|
12
|
+
module Hash #:nodoc:
|
13
|
+
# Makes it easier to build other objects from a Hash
|
14
|
+
module Conversions
|
15
|
+
|
16
|
+
# This method accepts a hash mutator (found in Wrest::Compononents)
|
17
|
+
# to build a new hash map by making changes to an existing one.
|
18
|
+
#
|
19
|
+
# No, this method does not mutate the state of the hash it is invoked on,
|
20
|
+
# but rather builds a new one.
|
21
|
+
#
|
22
|
+
# Yes, the name is misleading in that respect. However, one
|
23
|
+
# hopes the absence of an exclamation mark will increase clarity.
|
24
|
+
#
|
25
|
+
# Uses include mutating the hash produced by xml-simple
|
26
|
+
# by using the meta data in the hash to type cast values.
|
27
|
+
#
|
28
|
+
# Example:
|
29
|
+
# "http://search.yahooapis.com/NewsSearchService/V1/newsSearch".to_uri.get(
|
30
|
+
# :appid => 'YahooDemo',
|
31
|
+
# :output => 'xml',
|
32
|
+
# :query => 'India',
|
33
|
+
# :results=> '3',
|
34
|
+
# :start => '1'
|
35
|
+
# ).deserialise.mutate_using(XmlSimpleTypeCaster.new)
|
36
|
+
def mutate_using(mutator)
|
37
|
+
returning({})do |mutated_hash|
|
38
|
+
self.each{|tuple| mutated_hash.store(*mutator.mutate(tuple))}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|