wrest 0.0.6-java → 0.0.7-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/README.rdoc +51 -19
  2. data/Rakefile +2 -3
  3. data/VERSION.yml +1 -1
  4. data/lib/wrest.rb +11 -2
  5. data/lib/wrest/components.rb +1 -2
  6. data/lib/wrest/components/attributes_container.rb +31 -69
  7. data/lib/wrest/components/attributes_container/typecaster.rb +121 -0
  8. data/lib/wrest/components/mutators.rb +18 -1
  9. data/lib/wrest/components/mutators/base.rb +52 -39
  10. data/lib/wrest/components/mutators/camel_to_snake_case.rb +7 -5
  11. data/lib/wrest/components/mutators/xml_mini_type_caster.rb +43 -0
  12. data/lib/wrest/components/mutators/xml_simple_type_caster.rb +22 -20
  13. data/lib/wrest/components/translators.rb +20 -17
  14. data/lib/wrest/components/translators/content_types.rb +2 -2
  15. data/lib/wrest/components/translators/json.rb +11 -8
  16. data/lib/wrest/components/translators/xml.rb +9 -12
  17. data/lib/wrest/core_ext/hash/conversions.rb +1 -1
  18. data/lib/wrest/resource/base.rb +25 -13
  19. data/lib/wrest/resource/state.rb +6 -0
  20. data/lib/wrest/response.rb +4 -0
  21. data/lib/wrest/uri.rb +5 -1
  22. data/lib/wrest/version.rb +1 -1
  23. data/spec/spec.opts +1 -1
  24. data/spec/spec_helper.rb +8 -1
  25. data/spec/wrest/components/attributes_container/typecaster_spec.rb +63 -0
  26. data/spec/wrest/components/attributes_container_spec.rb +6 -61
  27. data/spec/wrest/components/mutators/base_spec.rb +5 -1
  28. data/spec/wrest/components/mutators/xml_mini_type_caster_spec.rb +75 -0
  29. data/spec/wrest/components/mutators_spec.rb +21 -0
  30. data/spec/wrest/components/translators/xml_spec.rb +1 -1
  31. data/spec/wrest/components/translators_spec.rb +9 -0
  32. data/spec/wrest/uri_spec.rb +16 -4
  33. metadata +14 -15
  34. 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 #:nodoc:
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
- # 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
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::Components
11
- class Mutators::CamelToSnakeCase < Mutators::Base
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
- def do_mutate(tuple)
17
- [tuple.first.underscore, tuple.last]
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
- # 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
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
- 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)
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
- [out_key, out_value]
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
- module Wrest::Components #:nodoc:
11
- # Contains strategies/lambdas which know how to deserialise
12
- # different content types.
13
- module Translators
14
- # Loads the appropriate desirialisation strategy based on
15
- # the content type
16
- def self.lookup(content_type)
17
- translator = CONTENT_TYPES[content_type]
18
- translator || (raise Wrest::Exceptions::UnsupportedContentTypeException.new("Unsupported content type #{content_type}"))
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::Components
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
- def deserialise(response)
15
- ActiveSupport::JSON.decode(response.body)
16
- end
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
- def serialise(hash)
19
- ActiveSupport::JSON.encode(hash)
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
- require 'xmlsimple'
10
+ module Wrest
11
+ module Components::Translators
12
+ module Xml
13
+ extend self
11
14
 
12
- module Wrest::Components::Translators
13
- module Xml
14
- extend self
15
+ def deserialise(response)
16
+ ActiveSupport::XmlMini.parse(response.body)
17
+ end
15
18
 
16
- def deserialise(response)
17
- XmlSimple.xml_in(
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-simple
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:
@@ -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
- has_attributes :id
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 set_redirect_handler(method_object)
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 resource_url
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 = "#{resource_url}/#{id}".to_uri.get.deserialise
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].first)
75
+ self.new(response_hash[resource_type])
64
76
  else
65
77
  response_hash
66
78
  end