wrest 0.0.5-java → 0.0.6-java

Sign up to get free protection for your applications and to get access to all the features.
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