wrest 0.0.6-java → 0.0.7-java
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 +51 -19
- data/Rakefile +2 -3
- data/VERSION.yml +1 -1
- data/lib/wrest.rb +11 -2
- data/lib/wrest/components.rb +1 -2
- data/lib/wrest/components/attributes_container.rb +31 -69
- data/lib/wrest/components/attributes_container/typecaster.rb +121 -0
- data/lib/wrest/components/mutators.rb +18 -1
- data/lib/wrest/components/mutators/base.rb +52 -39
- data/lib/wrest/components/mutators/camel_to_snake_case.rb +7 -5
- data/lib/wrest/components/mutators/xml_mini_type_caster.rb +43 -0
- data/lib/wrest/components/mutators/xml_simple_type_caster.rb +22 -20
- data/lib/wrest/components/translators.rb +20 -17
- data/lib/wrest/components/translators/content_types.rb +2 -2
- data/lib/wrest/components/translators/json.rb +11 -8
- data/lib/wrest/components/translators/xml.rb +9 -12
- data/lib/wrest/core_ext/hash/conversions.rb +1 -1
- data/lib/wrest/resource/base.rb +25 -13
- data/lib/wrest/resource/state.rb +6 -0
- data/lib/wrest/response.rb +4 -0
- data/lib/wrest/uri.rb +5 -1
- data/lib/wrest/version.rb +1 -1
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +8 -1
- data/spec/wrest/components/attributes_container/typecaster_spec.rb +63 -0
- data/spec/wrest/components/attributes_container_spec.rb +6 -61
- data/spec/wrest/components/mutators/base_spec.rb +5 -1
- data/spec/wrest/components/mutators/xml_mini_type_caster_spec.rb +75 -0
- data/spec/wrest/components/mutators_spec.rb +21 -0
- data/spec/wrest/components/translators/xml_spec.rb +1 -1
- data/spec/wrest/components/translators_spec.rb +9 -0
- data/spec/wrest/uri_spec.rb +16 -4
- metadata +14 -15
- data/lib/wrest/components/typecast_helpers.rb +0 -41
@@ -7,16 +7,33 @@
|
|
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
|
11
11
|
module Components
|
12
12
|
# A mutator understands how to transform
|
13
13
|
# one tuple(key/value pair) from a hash
|
14
14
|
# into another
|
15
15
|
module Mutators
|
16
|
+
# All sublasses of Mutators::Base are automatically
|
17
|
+
# registered here by underscored, symbolised class name.
|
18
|
+
REGISTRY = {}
|
19
|
+
|
20
|
+
# Makes referencing and chaining mutators easy.
|
21
|
+
#
|
22
|
+
# Example:
|
23
|
+
# Mutators.chain(:xml_mini_type_caster, :camel_to_snake_case)
|
24
|
+
# is equivalent to
|
25
|
+
# Wrest::Components::Mutators::XmlMiniTypeCaster.new(Wrest::Components::Mutators::CamelToSnakeCase.new)
|
26
|
+
def self.chain(*mutator_keys)
|
27
|
+
mutator_key = mutator_keys.pop
|
28
|
+
mutator_keys.reverse.inject(REGISTRY[mutator_key].new) do |next_instance, next_key|
|
29
|
+
REGISTRY[next_key].new(next_instance)
|
30
|
+
end
|
31
|
+
end
|
16
32
|
end
|
17
33
|
end
|
18
34
|
end
|
19
35
|
|
20
36
|
require "#{WREST_ROOT}/wrest/components/mutators/base"
|
21
37
|
require "#{WREST_ROOT}/wrest/components/mutators/xml_simple_type_caster"
|
38
|
+
require "#{WREST_ROOT}/wrest/components/mutators/xml_mini_type_caster"
|
22
39
|
require "#{WREST_ROOT}/wrest/components/mutators/camel_to_snake_case"
|
@@ -1,43 +1,56 @@
|
|
1
1
|
# Copyright 2009 Sidu Ponnappa
|
2
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.
|
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
9
|
|
10
|
-
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
10
|
+
module Wrest
|
11
|
+
module Components
|
12
|
+
# This is a base implementation of a
|
13
|
+
# hash mutator that ensures that the <tt>mutate</tt> method
|
14
|
+
# will chain to the next mutator by using a
|
15
|
+
# template method.
|
16
|
+
class Mutators::Base
|
17
|
+
attr_reader :next_mutator
|
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
|
27
|
+
|
28
|
+
def initialize(next_mutator = nil)
|
29
|
+
@next_mutator = next_mutator
|
30
|
+
end
|
31
|
+
|
32
|
+
# This is a template method which operates on a tuple (well, pair)
|
33
|
+
# from a hash map and guarantees mutator chaining.
|
34
|
+
#
|
35
|
+
# Iterating over any hash using <tt>each</tt> injects
|
36
|
+
# each key/value pair from the hash in the
|
37
|
+
# form of an array.
|
38
|
+
# This method expects of this form as an argument, i.e.
|
39
|
+
# an array with the structure [:key, :value]
|
40
|
+
#
|
41
|
+
# The implementation of the mutation is achieved by
|
42
|
+
# overriding the <tt>do_mutate</tt> method in a subclass.
|
43
|
+
# Note that failing to do so will result in an exception
|
44
|
+
# at runtime.
|
45
|
+
def mutate(tuple)
|
46
|
+
out_tuple = do_mutate(tuple)
|
47
|
+
next_mutator ? next_mutator.mutate(out_tuple) : out_tuple
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
def do_mutate(tuple)
|
52
|
+
raise Wrest::Exceptions::MethodNotOverriddenException
|
53
|
+
end
|
54
|
+
end
|
42
55
|
end
|
43
|
-
end
|
56
|
+
end
|
@@ -7,14 +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
|
-
module Wrest
|
11
|
-
|
10
|
+
module Wrest
|
11
|
+
module Components
|
12
12
|
# Converts the key to snake case
|
13
13
|
#
|
14
14
|
# Example:
|
15
|
-
# Mutators::CamelToSnakeCase.new.mutate(['Spirit-Sword', 'true']) # => ['spirit_sword', 'true']
|
16
|
-
|
17
|
-
|
15
|
+
# Mutators::CamelToSnakeCase.new.mutate(['Spirit-Sword', 'true']) # => ['spirit_sword', 'true']**
|
16
|
+
class Mutators::CamelToSnakeCase < Mutators::Base
|
17
|
+
def do_mutate(tuple)
|
18
|
+
[tuple.first.underscore, tuple.last]
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -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
|
+
|
11
|
+
module Wrest
|
12
|
+
module Components
|
13
|
+
# This mutator undertands how do type casting
|
14
|
+
# using the type data embedded in a hash
|
15
|
+
# created by deserialising an xml using
|
16
|
+
# ActiveSupport::XmlMini
|
17
|
+
class Mutators::XmlMiniTypeCaster < Mutators::Base
|
18
|
+
def do_mutate(tuple)
|
19
|
+
out_key, in_value = tuple
|
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
|
+
caster = ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING[in_value['type']]
|
27
|
+
out_value = caster ? caster.call(in_value['__content__']) : in_value
|
28
|
+
elsif in_value.key?('__content__')
|
29
|
+
out_value = in_value['__content__']
|
30
|
+
else
|
31
|
+
out_value = in_value.mutate_using(self)
|
32
|
+
end
|
33
|
+
when Array
|
34
|
+
out_value = in_value.collect{|hash| hash.mutate_using(self)}
|
35
|
+
else
|
36
|
+
out_value = in_value
|
37
|
+
end
|
38
|
+
|
39
|
+
[out_key, out_value]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -7,29 +7,31 @@
|
|
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
|
-
|
18
|
-
|
19
|
-
|
10
|
+
module Wrest
|
11
|
+
module Components
|
12
|
+
# This mutator undertands how do type casting
|
13
|
+
# using the type data embedded in a hash
|
14
|
+
# created by deserialising an xml using
|
15
|
+
# xml-simple
|
16
|
+
class Mutators::XmlSimpleTypeCaster < Mutators::Base
|
17
|
+
def do_mutate(tuple)
|
18
|
+
out_key = tuple.first
|
19
|
+
in_value = tuple.last[0]
|
20
|
+
out_value = in_value
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
case in_value
|
23
|
+
when Hash
|
24
|
+
if in_value['nil'] == 'true'
|
25
|
+
out_value = nil
|
26
|
+
elsif in_value.key?('type')
|
27
|
+
out_value = ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING[in_value['type']].call(in_value['content'])
|
28
|
+
else
|
29
|
+
out_value = in_value.mutate_using(self)
|
30
|
+
end
|
29
31
|
end
|
30
|
-
end
|
31
32
|
|
32
|
-
|
33
|
+
[out_key, out_value]
|
34
|
+
end
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
@@ -1,25 +1,28 @@
|
|
1
1
|
# Copyright 2009 Sidu Ponnappa
|
2
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
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
#
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
+
|
11
|
+
module Wrest
|
12
|
+
module Components
|
13
|
+
# Contains strategies/lambdas which know how to deserialise
|
14
|
+
# different content types.
|
15
|
+
module Translators
|
16
|
+
# Loads the appropriate desirialisation strategy based on
|
17
|
+
# the content type
|
18
|
+
def self.lookup(content_type)
|
19
|
+
translator = CONTENT_TYPES[content_type]
|
20
|
+
translator || (raise Wrest::Exceptions::UnsupportedContentTypeException.new("Unsupported content type #{content_type}"))
|
21
|
+
end
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
26
|
require "#{WREST_ROOT}/wrest/components/translators/xml"
|
24
27
|
require "#{WREST_ROOT}/wrest/components/translators/json"
|
25
|
-
require "#{WREST_ROOT}/wrest/components/translators/content_types"
|
28
|
+
require "#{WREST_ROOT}/wrest/components/translators/content_types"
|
@@ -7,8 +7,8 @@
|
|
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
|
11
|
-
module Translators
|
10
|
+
module Wrest
|
11
|
+
module Components::Translators
|
12
12
|
# Maps content types to deserialisers
|
13
13
|
CONTENT_TYPES = {
|
14
14
|
'application/xml' => Wrest::Components::Translators::Xml,
|
@@ -7,16 +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::Components::Translators
|
11
|
-
module Json
|
12
|
-
extend self
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
module Wrest
|
12
|
+
module Components
|
13
|
+
module Translators::Json
|
14
|
+
extend self
|
15
|
+
|
16
|
+
def deserialise(response)
|
17
|
+
ActiveSupport::JSON.decode(response.body)
|
18
|
+
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
def serialise(hash)
|
21
|
+
ActiveSupport::JSON.encode(hash)
|
22
|
+
end
|
20
23
|
end
|
21
24
|
end
|
22
25
|
end
|
@@ -7,20 +7,17 @@
|
|
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
|
-
|
10
|
+
module Wrest
|
11
|
+
module Components::Translators
|
12
|
+
module Xml
|
13
|
+
extend self
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
+
def deserialise(response)
|
16
|
+
ActiveSupport::XmlMini.parse(response.body)
|
17
|
+
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
response.body,
|
19
|
-
'keeproot' => true
|
20
|
-
)
|
21
|
-
end
|
22
|
-
|
23
|
-
def serialise(hash)
|
19
|
+
def serialise(hash)
|
20
|
+
end
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
@@ -22,7 +22,7 @@ module Wrest
|
|
22
22
|
# Yes, the name is misleading in that respect. However, one
|
23
23
|
# hopes the absence of an exclamation mark will increase clarity.
|
24
24
|
#
|
25
|
-
# Uses include mutating the hash produced by xml
|
25
|
+
# Uses include mutating the hash produced by deserialising xml
|
26
26
|
# by using the meta data in the hash to type cast values.
|
27
27
|
#
|
28
28
|
# Example:
|
data/lib/wrest/resource/base.rb
CHANGED
@@ -12,55 +12,67 @@ module Wrest::Resource #:nodoc:
|
|
12
12
|
# It is a REST client targetted at Rails REST apps.
|
13
13
|
class Base
|
14
14
|
include Wrest::Components::AttributesContainer
|
15
|
-
|
16
|
-
|
15
|
+
include Wrest::Components::AttributesContainer::Typecaster
|
16
|
+
|
17
|
+
always_has :id
|
17
18
|
typecast :id => as_integer
|
18
19
|
attr_reader :attributes
|
19
|
-
|
20
|
+
|
20
21
|
class << self
|
21
22
|
def inherited(klass)
|
22
23
|
klass.set_resource_name klass.name
|
23
24
|
end
|
24
|
-
|
25
|
+
|
25
26
|
# Allows the resource name to be configured and creates
|
26
|
-
# a getter method for it.
|
27
|
+
# a getter method for it.
|
27
28
|
# This is a useful feature when using anonymous classes like
|
28
29
|
# we often do while writing tests.
|
29
30
|
# By default, the resource name is set to the name of the class.
|
30
31
|
def set_resource_name(resource_name)
|
31
32
|
self.class_eval "def self.resource_name; '#{resource_name}';end"
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
# Allows the host url at which the resource is found to be configured
|
35
|
-
# and creates a getter method for it.
|
36
|
+
# and creates a getter method for it.
|
36
37
|
# For example in the url
|
37
38
|
# http://localhost:3000/users/1/settings
|
38
|
-
# you would set
|
39
|
+
# you would set
|
39
40
|
# http://localhost:3000
|
40
41
|
# as the host url.
|
41
42
|
def set_host(host)
|
42
43
|
self.class_eval "def self.host; '#{host}';end"
|
43
44
|
end
|
44
45
|
|
45
|
-
def
|
46
|
+
def set_default_format(format)
|
47
|
+
self.class_eval "def self.default_format; '#{format.to_s}';end"
|
46
48
|
end
|
47
49
|
|
50
|
+
def set_redirect_handler(method_object)
|
51
|
+
end
|
52
|
+
|
48
53
|
def resource_path
|
49
54
|
@resource_path ||= "/#{resource_name.underscore.pluralize}"
|
50
55
|
end
|
51
56
|
|
52
|
-
def
|
57
|
+
def resource_collection_url
|
53
58
|
"#{host}#{resource_path}"
|
54
59
|
end
|
55
|
-
|
60
|
+
|
56
61
|
def find_all
|
57
62
|
end
|
58
63
|
|
64
|
+
def find(resource_type = [:one, :collection, :singleton], from = "")
|
65
|
+
end
|
66
|
+
|
59
67
|
def find(id)
|
60
|
-
response_hash = "#{
|
68
|
+
response_hash = "#{resource_collection_url}/#{id}.#{default_format}".to_uri.get.deserialise.mutate_using(
|
69
|
+
Wrest::Components::Mutators.chain(
|
70
|
+
:xml_mini_type_caster, :camel_to_snake_case
|
71
|
+
)
|
72
|
+
)
|
61
73
|
resource_type = response_hash.keys.first
|
62
74
|
if(resource_type.underscore.camelize == self.name)
|
63
|
-
self.new(response_hash[resource_type]
|
75
|
+
self.new(response_hash[resource_type])
|
64
76
|
else
|
65
77
|
response_hash
|
66
78
|
end
|