wrest 0.0.5-java → 0.0.6-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.
Files changed (35) hide show
  1. data/README.rdoc +31 -17
  2. data/Rakefile +7 -2
  3. data/VERSION.yml +1 -1
  4. data/lib/wrest/components.rb +3 -1
  5. data/lib/wrest/components/attributes_container.rb +65 -10
  6. data/lib/wrest/components/mutators.rb +2 -1
  7. data/lib/wrest/components/mutators/base.rb +27 -11
  8. data/lib/wrest/components/mutators/camel_to_snake_case.rb +20 -0
  9. data/lib/wrest/components/mutators/xml_simple_type_caster.rb +25 -21
  10. data/lib/wrest/{translators.rb → components/translators.rb} +6 -6
  11. data/lib/wrest/{translators → components/translators}/content_types.rb +5 -5
  12. data/lib/wrest/components/translators/json.rb +22 -0
  13. data/lib/wrest/{translators → components/translators}/xml.rb +19 -17
  14. data/lib/wrest/components/typecast_helpers.rb +41 -0
  15. data/lib/wrest/core_ext/hash/conversions.rb +22 -3
  16. data/lib/wrest/exceptions.rb +6 -1
  17. data/lib/wrest/{translators/json.rb → exceptions/method_not_overridden_exception.rb} +11 -15
  18. data/lib/wrest/exceptions/unsupported_content_type_exception.rb +11 -9
  19. data/lib/wrest/resource/base.rb +5 -1
  20. data/lib/wrest/response.rb +2 -2
  21. data/lib/wrest/uri.rb +3 -3
  22. data/lib/wrest/version.rb +1 -1
  23. data/spec/spec_helper.rb +2 -1
  24. data/spec/wrest/components/attributes_container_spec.rb +66 -11
  25. data/spec/wrest/components/mutators/base_spec.rb +28 -8
  26. data/spec/wrest/components/mutators/camel_to_snake_spec.rb +22 -0
  27. data/spec/wrest/components/mutators/xml_simple_type_caster_spec.rb +14 -8
  28. data/spec/wrest/{translators → components/translators}/xml_spec.rb +3 -3
  29. data/spec/wrest/components/translators_spec.rb +9 -0
  30. data/spec/wrest/core_ext/hash/conversions_spec.rb +1 -1
  31. data/spec/wrest/resource/base_spec.rb +1 -1
  32. data/spec/wrest/response_spec.rb +3 -3
  33. data/spec/wrest/uri_spec.rb +2 -2
  34. metadata +61 -56
  35. data/spec/wrest/translators_spec.rb +0 -9
@@ -1,24 +1,26 @@
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
10
  require 'xmlsimple'
11
11
 
12
- module Wrest
13
- module Translators
14
- # Knows how to deserialise xml.
15
- # Depends on the xmlsimple gem.
16
- Xml = lambda{|response|
17
- XmlSimple.xml_in(
18
- response.body,
19
- 'keeproot' => true
20
- )
21
- }
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
22
25
  end
23
26
  end
24
-
@@ -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
@@ -10,11 +10,30 @@
10
10
  module Wrest
11
11
  module CoreExt #:nodoc:
12
12
  module Hash #:nodoc:
13
- # Makes it easier to build other objects from a String
13
+ # Makes it easier to build other objects from a Hash
14
14
  module Conversions
15
15
 
16
- # A convenience method equivalent to Wrest::Uri.new(string)
17
- def to_mutated_hash(mutator)
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)
18
37
  returning({})do |mutated_hash|
19
38
  self.each{|tuple| mutated_hash.store(*mutator.mutate(tuple))}
20
39
  end
@@ -1 +1,6 @@
1
- require "#{WREST_ROOT}/wrest/exceptions/unsupported_content_type_exception"
1
+ module Wrest
2
+ module Exceptions #:nodoc:
3
+ end
4
+ end
5
+ require "#{WREST_ROOT}/wrest/exceptions/unsupported_content_type_exception"
6
+ require "#{WREST_ROOT}/wrest/exceptions/method_not_overridden_exception"
@@ -1,21 +1,17 @@
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
- require 'json'
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.
11
9
 
12
10
  module Wrest
13
- module Translators
14
- # Knows how to deserialise json.
15
- # Depends on the json gem.
16
- Json = lambda{|response|
17
- JSON.parse(response.body)
18
- }
11
+ module Exceptions
12
+ # Raised when a base method that should be overriden
13
+ # is invoked on a subclass that has not implemented it.
14
+ class MethodNotOverriddenException < StandardError
15
+ end
19
16
  end
20
17
  end
21
-
@@ -1,15 +1,17 @@
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
10
  module Wrest
11
- # Raised when a translator for an unregisterd response content type
12
- # is requested. See Translators.
13
- class UnsupportedContentTypeException < StandardError
11
+ module Exceptions
12
+ # Raised when a translator for an unregisterd response content type
13
+ # is requested. See Translators.
14
+ class UnsupportedContentTypeException < StandardError
15
+ end
14
16
  end
15
17
  end
@@ -14,6 +14,7 @@ module Wrest::Resource #:nodoc:
14
14
  include Wrest::Components::AttributesContainer
15
15
 
16
16
  has_attributes :id
17
+ typecast :id => as_integer
17
18
  attr_reader :attributes
18
19
 
19
20
  class << self
@@ -40,7 +41,10 @@ module Wrest::Resource #:nodoc:
40
41
  def set_host(host)
41
42
  self.class_eval "def self.host; '#{host}';end"
42
43
  end
43
-
44
+
45
+ def set_redirect_handler(method_object)
46
+ end
47
+
44
48
  def resource_path
45
49
  @resource_path ||= "/#{resource_name.underscore.pluralize}"
46
50
  end
@@ -28,11 +28,11 @@ module Wrest #:nodoc:
28
28
  end
29
29
 
30
30
  def deserialise
31
- deserialise_using(Wrest::Translators.load(@http_response.content_type))
31
+ deserialise_using(Wrest::Components::Translators.lookup(@http_response.content_type))
32
32
  end
33
33
 
34
34
  def deserialise_using(translator)
35
- translator.call(@http_response)
35
+ translator.deserialise(@http_response)
36
36
  end
37
37
  end
38
38
  end
data/lib/wrest/uri.rb CHANGED
@@ -27,7 +27,7 @@ module Wrest #:nodoc:
27
27
  end
28
28
 
29
29
  def hash
30
- self.uri.hash + self.class.object_id
30
+ self.uri.hash + 20090423
31
31
  end
32
32
 
33
33
  # Make a HTTP get request to this URI.
@@ -44,8 +44,8 @@ module Wrest #:nodoc:
44
44
  do_request 'post', @uri.request_uri, body.to_s, headers.stringify_keys
45
45
  end
46
46
 
47
- def delete(headers = {})
48
- do_request 'delete', @uri.request_uri, headers.stringify_keys
47
+ def delete(parameters = {}, headers = {})
48
+ do_request 'delete', parameters.empty? ? @uri.request_uri : "#{@uri.request_uri}?#{parameters.to_query}", headers.stringify_keys
49
49
  end
50
50
 
51
51
  def do_request(method, url, *args)
data/lib/wrest/version.rb CHANGED
@@ -12,7 +12,7 @@ module Wrest
12
12
  unless defined? MAJOR
13
13
  MAJOR = 0
14
14
  MINOR = 0
15
- TINY = 5
15
+ TINY = 6
16
16
 
17
17
  STRING = [MAJOR, MINOR, TINY].join('.')
18
18
 
data/spec/spec_helper.rb CHANGED
@@ -10,7 +10,8 @@ require 'spec'
10
10
  Wrest.logger = Logger.new(File.open("#{WREST_ROOT}/../log/test.log", 'a'))
11
11
 
12
12
  def p(*args)
13
- super *(args << caller[0])
13
+ # super *(args << caller[0])
14
+ super *(args << '<br>')
14
15
  end
15
16
 
16
17
  Spec::Runner.configure do |config|
@@ -20,6 +20,61 @@ module Wrest::Components
20
20
  lambda{ HumanBeing.new }.should_not raise_error
21
21
  end
22
22
 
23
+ describe 'typecast' do
24
+ before :each do
25
+ @Demon = Class.new
26
+ @Demon.class_eval{include AttributesContainer}
27
+ end
28
+
29
+ it "should know how to apply a lambda to the string value of a given key casting it to a new type" do
30
+ @Demon.class_eval{ typecast :age => lambda{|id_string| id_string.to_i} }
31
+ kai_wren = @Demon.new('age' => '1')
32
+ kai_wren.age.should == 1
33
+ end
34
+
35
+ it "should not apply a lambda to the value of a given key if it is not a string" do
36
+ @Demon.class_eval{ typecast :age => lambda{|id_string| id_string.to_i} }
37
+ kai_wren = @Demon.new('age' => :ooga)
38
+ kai_wren.age.should == :ooga
39
+ end
40
+
41
+ it "should leave nils unchanged" do
42
+ @Demon.class_eval{ typecast :age => lambda{|id_string| id_string.to_i} }
43
+ kai_wren = @Demon.new('age' => nil)
44
+ kai_wren.age.should be_nil
45
+ end
46
+
47
+ it "should provide helpers for typcasting common types" do
48
+ @Demon.class_eval{ typecast :age => as_integer }
49
+ kai_wren = @Demon.new('age' => '1500')
50
+ kai_wren.age.should == 1500
51
+ end
52
+
53
+ describe 'in subclasses' do
54
+ before :each do
55
+ @Sidhe = Class.new
56
+ @Sidhe.class_eval{
57
+ include AttributesContainer
58
+ typecast :age => as_integer
59
+ }
60
+ end
61
+
62
+ it "should inherit all defined typecasts" do
63
+ @ChineseSidhe = Class.new(@Sidhe)
64
+ kai_wren = @ChineseSidhe.new('age' => '1500')
65
+ kai_wren.age.should == 1500
66
+ end
67
+
68
+ it "should discard all typecasts from parent if defined in child" do
69
+ @ChineseSidhe = Class.new(@Sidhe)
70
+ @ChineseSidhe.class_eval{ typecast :born_in => as_integer }
71
+ kai_wren = @ChineseSidhe.new('age' => '1500', 'born_in' => '509')
72
+ kai_wren.age.should == '1500'
73
+ kai_wren.born_in.should == 509
74
+ end
75
+ end
76
+ end
77
+
23
78
  describe 'has_attributes' do
24
79
  describe 'method creation' do
25
80
  before :each do
@@ -68,7 +123,7 @@ module Wrest::Components
68
123
  @Demon.class_eval{
69
124
  include AttributesContainer
70
125
  has_attributes :trainer
71
-
126
+
72
127
  def method_missing(method_name, *args)
73
128
  # Ensuring that the instance level
74
129
  # attribute methods don't kick in
@@ -107,16 +162,6 @@ module Wrest::Components
107
162
  @li_piao['profession'].should == "Natural Magician"
108
163
  end
109
164
 
110
- it "should provide a generic key based getter that understands symbols" do
111
- @li_piao[:enhanced_by] = "Viss"
112
- @li_piao.instance_variable_get('@attributes')[:enhanced_by].should == "Viss"
113
- end
114
-
115
- it "should provide a generic key based getter that translates strings to symbols" do
116
- @li_piao['enhanced_by'] = "Viss"
117
- @li_piao.instance_variable_get('@attributes')[:enhanced_by].should == "Viss"
118
- end
119
-
120
165
  it "should fail when getter methods for attributes that don't exist are invoked" do
121
166
  lambda{ @li_piao.ooga }.should raise_error(NoMethodError)
122
167
  end
@@ -135,6 +180,16 @@ module Wrest::Components
135
180
  @li_piao.should_not respond_to(:gods)
136
181
  end
137
182
 
183
+ it "should provide a generic key based setter that understands symbols" do
184
+ @li_piao[:enhanced_by] = "Viss"
185
+ @li_piao.instance_variable_get('@attributes')[:enhanced_by].should == "Viss"
186
+ end
187
+
188
+ it "should provide a generic key based setter that translates strings to symbols" do
189
+ @li_piao['enhanced_by'] = "Viss"
190
+ @li_piao.instance_variable_get('@attributes')[:enhanced_by].should == "Viss"
191
+ end
192
+
138
193
  it "should create a setter method when one is invoked for attributes that don't exist" do
139
194
  @li_piao.niece = 'Li Plum'
140
195
  @li_piao.instance_variable_get('@attributes')[:niece].should == 'Li Plum'
@@ -1,18 +1,38 @@
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
10
  require File.dirname(__FILE__) + '/../../../spec_helper'
11
11
 
12
12
  module Wrest::Components
13
13
  describe Mutators::Base do
14
- it "should return a tuple unchanged" do
15
- Mutators::Base.new.mutate([:ooga, :booga]).should == [:ooga, :booga]
14
+ it "should raise an exception if mutate is invoked without do_mutate being implemented in a subclass" do
15
+ lambda{ Class.new(Mutators::Base).new.mutate([]) }.should raise_error(Wrest::Exceptions::MethodNotOverriddenException)
16
16
  end
17
+
18
+ it "should ensure that the next mutator is invoked for a subclass" do
19
+ next_mutator = mock('Mutator')
20
+ mutator = Mutators::CamelToSnakeCase.new(next_mutator)
21
+
22
+ next_mutator.should_receive(:mutate).with(['a', 1]).and_return([:a, '1'])
23
+
24
+ mutator.mutate(['a', 1]).should == [:a, '1']
25
+ end
26
+
27
+ it "should know how to chain mutators recursively" do
28
+ mutator = Mutators::XmlSimpleTypeCaster.new(Mutators::CamelToSnakeCase.new)
29
+ mutator.mutate(
30
+ ["Result", [{
31
+ "Publish-Date"=>["1240326000"],
32
+ "News-Source"=>[{"Online" => ["PC via News"], "Unique-Id" => [{"type"=>"integer", "content"=>"1"}]}]
33
+ }]]
34
+ ).should == ["result", {"publish_date" => "1240326000", "news_source" => {"online"=>"PC via News", "unique_id"=>1}}]
35
+ end
36
+
17
37
  end
18
38
  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
+ require File.dirname(__FILE__) + '/../../../spec_helper'
11
+
12
+ module Wrest::Components
13
+ describe Mutators::CamelToSnakeCase do
14
+ before(:each) do
15
+ @mutator = Mutators::CamelToSnakeCase.new
16
+ end
17
+
18
+ it "should underscore the key in a tuple" do
19
+ @mutator.mutate(["universe-id", "1"]).should == ["universe_id", "1"]
20
+ end
21
+ end
22
+ end
@@ -16,26 +16,32 @@ module Wrest::Components
16
16
  end
17
17
 
18
18
  # {"lead-bottle"=>[{"name"=>["Wooz"], "universe-id"=>[{"type"=>"integer", "nil"=>"true"}], "id"=>[{"type"=>"integer", "content"=>"1"}]}]}
19
- it "should underscore the key in a tuple" do
20
- @mutator.mutate(["universe-id", ["1"]]).should == ["universe_id", "1"]
21
- end
22
19
 
23
20
  it "should typecast a nil value in a tuple" do
24
21
  @mutator.mutate(
25
- ["universe-id", [{"type"=>"integer", "nil"=>"true"}]]
26
- ).should == ["universe_id", nil]
22
+ ["universe-id", [{"type"=>"integer", "nil"=>"true"}]]
23
+ ).should == ["universe-id", nil]
27
24
  end
28
25
 
29
26
  it "should leave a string value in a tuple unchanged" do
30
27
  @mutator.mutate(
31
- ["name", ["Wooz"]]
28
+ ["name", ["Wooz"]]
32
29
  ).should == ["name", "Wooz"]
33
30
  end
34
-
31
+
35
32
  it "should cast an integer value in a tuple" do
36
33
  @mutator.mutate(
37
- ["id", [{"type"=>"integer", "content"=>"1"}]]
34
+ ["id", [{"type"=>"integer", "content"=>"1"}]]
38
35
  ).should == ["id", 1]
39
36
  end
37
+
38
+ it "should step into a value if it is a hash" do
39
+ @mutator.mutate(
40
+ ["Result", [{
41
+ "PublishDate"=>["1240326000"],
42
+ "NewsSource"=>[{"Online" => ["PC via News"], "UniqueId" => [{"type"=>"integer", "content"=>"1"}]}]
43
+ }]]
44
+ ).should == ["Result", {"PublishDate" => "1240326000", "NewsSource" => {"Online"=>"PC via News", "UniqueId"=>1}}]
45
+ end
40
46
  end
41
47
  end