wrest 0.0.4

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 (38) hide show
  1. data/README.rdoc +104 -0
  2. data/Rakefile +230 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/wrest +22 -0
  5. data/lib/wrest/core_ext/string/conversions.rb +23 -0
  6. data/lib/wrest/core_ext/string.rb +5 -0
  7. data/lib/wrest/exceptions/unsupported_content_type_exception.rb +15 -0
  8. data/lib/wrest/exceptions.rb +1 -0
  9. data/lib/wrest/mappers/attributes_container.rb +123 -0
  10. data/lib/wrest/mappers/resource/base.rb +69 -0
  11. data/lib/wrest/mappers/resource/collection.rb +12 -0
  12. data/lib/wrest/mappers/resource.rb +17 -0
  13. data/lib/wrest/mappers/simple_resource.rb +17 -0
  14. data/lib/wrest/mappers.rb +21 -0
  15. data/lib/wrest/response.rb +38 -0
  16. data/lib/wrest/translators/content_types.rb +20 -0
  17. data/lib/wrest/translators/json.rb +21 -0
  18. data/lib/wrest/translators/typed_hash.rb +4 -0
  19. data/lib/wrest/translators/xml.rb +24 -0
  20. data/lib/wrest/translators.rb +26 -0
  21. data/lib/wrest/uri.rb +74 -0
  22. data/lib/wrest/uri_template.rb +32 -0
  23. data/lib/wrest/version.rb +22 -0
  24. data/lib/wrest.rb +41 -0
  25. data/spec/custom_matchers/custom_matchers.rb +2 -0
  26. data/spec/rcov.opts +4 -0
  27. data/spec/spec.opts +6 -0
  28. data/spec/spec_helper.rb +18 -0
  29. data/spec/wrest/mappers/attributes_container_spec.rb +184 -0
  30. data/spec/wrest/mappers/resource/base_spec.rb +158 -0
  31. data/spec/wrest/mappers/simple_resource_spec.rb +7 -0
  32. data/spec/wrest/response_spec.rb +21 -0
  33. data/spec/wrest/translators/typed_hash_spec.rb +9 -0
  34. data/spec/wrest/translators/xml_spec.rb +12 -0
  35. data/spec/wrest/translators_spec.rb +9 -0
  36. data/spec/wrest/uri_spec.rb +131 -0
  37. data/spec/wrest/uri_template_spec.rb +28 -0
  38. metadata +130 -0
@@ -0,0 +1,158 @@
1
+ require File.dirname(__FILE__) + '/../../../spec_helper'
2
+
3
+ class Glassware < Wrest::Mappers::Resource::Base
4
+ set_host "http://localhost:3000"
5
+ end
6
+
7
+ class BottledUniverse < Glassware
8
+ set_host "http://localhost:3001"
9
+ end
10
+
11
+ module Wrest::Mappers
12
+ describe Resource::Base do
13
+ it "should not affect other classes when setting up its macros" do
14
+ Class.should_not respond_to(:host=)
15
+ Object.should_not respond_to(:host=)
16
+ end
17
+
18
+ it "should not affect itself when subclasses use its macros" do
19
+ Resource::Base.should_not respond_to(:host)
20
+ end
21
+
22
+ describe 'subclasses' do
23
+ before(:each) do
24
+ @BottledUniverse = Class.new(Resource::Base)
25
+ @BottledUniverse.class_eval do
26
+ set_resource_name 'BottledUniverse'
27
+ end
28
+ end
29
+
30
+ it "should know its name as a resource by default" do
31
+ BottledUniverse.resource_name.should == 'BottledUniverse'
32
+ end
33
+
34
+ it "should allow its name as a resource to be configured for anonymous classes" do
35
+ @BottledUniverse.resource_name.should == 'BottledUniverse'
36
+ end
37
+
38
+ it "should know how to create an instance using deserialised attributes" do
39
+ # Json => {"lead_bottle"=>{"name"=>"Wooz", "id"=>1, "universe_id"=>nil}}
40
+ # Xml => {"lead-bottle"=>[{"name"=>["Wooz"], "universe-id"=>[{"type"=>"integer", "nil"=>"true"}], "id"=>[{"type"=>"integer", "content"=>"1"}]}]}
41
+ universe = @BottledUniverse.new "name"=>"Wooz", "id"=>1, "universe_id"=>nil, 'owner_id'=>nil
42
+ universe.name.should == "Wooz"
43
+ universe.owner_id.should be_nil
44
+ universe.id.should == 1
45
+ end
46
+
47
+ it "should allow instantiation with no attributes" do
48
+ lambda{ @BottledUniverse.new }.should_not raise_error
49
+ end
50
+
51
+ it "should have a method to set the host url" do
52
+ @BottledUniverse.should respond_to(:set_host)
53
+ end
54
+
55
+ it "should have a method to retrive the host url after it is set" do
56
+ @BottledUniverse.class_eval{ set_host "http://localhost:3000" }
57
+ @BottledUniverse.should respond_to(:host)
58
+ end
59
+
60
+ it "should know what its site is" do
61
+ @BottledUniverse.class_eval{ set_host "http://localhost:3000" }
62
+ @BottledUniverse.host.should == "http://localhost:3000"
63
+ end
64
+
65
+ it "should not use the same string" do
66
+ url = "http://localhost:3000"
67
+ @BottledUniverse.class_eval{ set_host url }
68
+ url.upcase!
69
+ @BottledUniverse.host.should == "http://localhost:3000"
70
+ end
71
+
72
+ it "should know its resource path" do
73
+ Glassware.resource_path.should == '/glasswares'
74
+ end
75
+ end
76
+
77
+ describe 'subclasses of sublasses' do
78
+ it "should configure its host without affecting its superclass" do
79
+ Glassware.host.should == "http://localhost:3000"
80
+ BottledUniverse.host.should == "http://localhost:3001"
81
+ end
82
+
83
+ it "should know its resource path when it is a subclass of a subclass" do
84
+ BottledUniverse.resource_path.should == '/bottled_universes'
85
+ end
86
+ end
87
+
88
+ describe 'attribute interface' do
89
+ it "should fail when getter methods for attributes that don't exist are invoked" do
90
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
91
+ lambda{ universe.ooga }.should raise_error(NoMethodError)
92
+ end
93
+
94
+ it "should provide getter methods for attributes" do
95
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
96
+ universe.owner.should == 'Kai Wren'
97
+ universe.guardian.should == 'Lung Shan'
98
+ end
99
+
100
+ it "should respond to getter methods for attributes" do
101
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
102
+ universe.should respond_to(:owner)
103
+ universe.should respond_to(:guardian)
104
+ end
105
+
106
+ it "should not respond to getter methods for attributes that don't exist" do
107
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
108
+ universe.should_not respond_to(:theronic)
109
+ end
110
+
111
+ it "should create a setter method when one is invoked for attributes that don't exist" do
112
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
113
+ universe.fu_dog = 'Shiriki'
114
+ universe.attributes[:fu_dog].should == 'Shiriki'
115
+ universe.fu_dog.should == 'Shiriki'
116
+ end
117
+
118
+ it "should provide setter methods for attributes" do
119
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
120
+ universe.guardian = 'Effervescent Tiger'
121
+ universe.attributes[:guardian].should == 'Effervescent Tiger'
122
+ end
123
+
124
+ it "should respond to setter methods for attributes" do
125
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
126
+ universe.should respond_to(:owner=)
127
+ universe.should respond_to(:guardian=)
128
+ end
129
+
130
+ it "should not respond to setter methods for attributes that don't exist" do
131
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
132
+ universe.should_not respond_to(:theronic=)
133
+ end
134
+
135
+ it "should fail when query methods for attributes that don't exist are invoked" do
136
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
137
+ lambda{ universe.ooga? }.should raise_error(NoMethodError)
138
+ end
139
+
140
+ it "should provide query methods for attributes" do
141
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => nil)
142
+ universe.owner?.should be_true
143
+ universe.guardian?.should be_false
144
+ end
145
+
146
+ it "should respond to query methods for attributes" do
147
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
148
+ universe.should respond_to(:owner?)
149
+ universe.should respond_to(:guardian?)
150
+ end
151
+
152
+ it "should not respond to query methods for attributes that don't exist" do
153
+ universe = Glassware.new(:owner => 'Kai Wren', :guardian => 'Lung Shan')
154
+ universe.should_not respond_to(:theronic?)
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module Wrest::Mappers
4
+ describe SimpleResource do
5
+ it "should do something"
6
+ end
7
+ end
@@ -0,0 +1,21 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ module Wrest
4
+ describe Response do
5
+ it "should know how to delegate to a translator" do
6
+ http_response = mock('response')
7
+ Translators::Xml.should_receive(:call).with(http_response)
8
+ Response.new(http_response).deserialise_using(Translators::Xml)
9
+ end
10
+
11
+ it "should know how to load a translator based on content type" do
12
+ http_response = mock('response')
13
+ http_response.should_receive(:content_type).and_return('application/xml')
14
+
15
+ response = Response.new(http_response)
16
+ response.should_receive(:deserialise_using).with(Translators::Xml)
17
+
18
+ response.deserialise
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module Wrest::Translators
4
+ describe TypedHash do
5
+ it "should description" do
6
+
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ module Wrest::Translators
4
+ describe Xml do
5
+ it "should know how to convert xml to a hashmap" do
6
+ http_response = mock('Http Reponse')
7
+ http_response.should_receive(:body).and_return("<ooga><age>12</age></ooga>")
8
+
9
+ Xml.call(http_response).should == {"ooga"=>[{"age"=>["12"]}]}
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ module Wrest
4
+ describe Translators do
5
+ it "should know how to raise an exception if the mime type doesn't exist" do
6
+ lambda{ Translators.load('weird/unknown')}.should raise_error(UnsupportedContentTypeException)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,131 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ module Wrest
4
+ describe Uri do
5
+ def build_ok_response(body = '')
6
+ returning mock(Net::HTTPOK) do |response|
7
+ response.stub!(:code).and_return('200')
8
+ response.stub!(:message).and_return('OK')
9
+ response.stub!(:body).and_return(body)
10
+ end
11
+ end
12
+
13
+ it "should respond to the four http actions" do
14
+ uri = Uri.new('http://localhost')
15
+ uri.should respond_to(:get)
16
+ uri.should respond_to(:post)
17
+ uri.should respond_to(:put)
18
+ uri.should respond_to(:delete)
19
+ end
20
+
21
+ it "should know when it is https" do
22
+ Uri.new('https://localhost:3000').should be_https
23
+ end
24
+
25
+ it "should know when it is not https" do
26
+ Uri.new('http://localhost:3000').should_not be_https
27
+ end
28
+
29
+ it "should understand equality" do
30
+ Uri.new('https://localhost:3000/ooga').should_not == 'https://localhost:3000/ooga'
31
+ Uri.new('https://localhost:3000/ooga').should_not == Uri.new('https://localhost:3000/booga')
32
+ Uri.new('https://localhost:3000').should_not == Uri.new('https://localhost:3500')
33
+ Uri.new('https://localhost:3000').should_not == Uri.new('http://localhost:3000')
34
+ Uri.new('http://localhost:3000').should == Uri.new('http://localhost:3000')
35
+ end
36
+
37
+
38
+ it "should have the same hash code if it is the same uri" do
39
+ Uri.new('https://localhost:3000').hash.should == Uri.new('https://localhost:3000').hash
40
+ Uri.new('https://localhost:3001').hash.should_not == Uri.new('https://localhost:3000').hash
41
+ end
42
+
43
+ describe 'Get' do
44
+ it "should know how to get" do
45
+ uri = "http://localhost:3000/glassware".to_uri
46
+ uri.should_not be_https
47
+
48
+ http = mock(Net::HTTP)
49
+ Net::HTTP.should_receive(:new).with('localhost', 3000).and_return(http)
50
+
51
+ http.should_receive(:get).with('/glassware', {}).and_return(build_ok_response)
52
+
53
+ uri.get
54
+ end
55
+
56
+ it "should know how to get with parameters" do
57
+ uri = "http://localhost:3000/glassware".to_uri
58
+ uri.should_not be_https
59
+
60
+ http = mock(Net::HTTP)
61
+ Net::HTTP.should_receive(:new).with('localhost', 3000).and_return(http)
62
+
63
+ http.should_receive(:get).with('/glassware?owner=Kai&type=bottle', 'page' => '2', 'per_page' => '5').and_return(build_ok_response)
64
+
65
+ uri.get({:owner => 'Kai', :type => 'bottle'}, :page => '2', :per_page => '5')
66
+ end
67
+
68
+ it "should know how to get with parameters but without any headers" do
69
+ uri = "http://localhost:3000/glassware".to_uri
70
+ uri.should_not be_https
71
+
72
+ http = mock(Net::HTTP)
73
+ Net::HTTP.should_receive(:new).with('localhost', 3000).and_return(http)
74
+
75
+ http.should_receive(:get).with('/glassware?owner=Kai&type=bottle', {}).and_return(build_ok_response)
76
+
77
+ uri.get(:owner => 'Kai', :type => 'bottle')
78
+ end
79
+ end
80
+
81
+ it "should know how to post" do
82
+ uri = "http://localhost:3000/glassware".to_uri
83
+ uri.should_not be_https
84
+
85
+ http = mock(Net::HTTP)
86
+ Net::HTTP.should_receive(:new).with('localhost', 3000).and_return(http)
87
+
88
+ http.should_receive(:post).with('/glassware', '<ooga>Booga</ooga>', {'page' => '2', 'per_page' => '5'}).and_return(build_ok_response)
89
+
90
+ uri.post '<ooga>Booga</ooga>', :page => '2', :per_page => '5'
91
+ end
92
+
93
+ it "should know how to put" do
94
+ uri = "http://localhost:3000/glassware".to_uri
95
+ uri.should_not be_https
96
+
97
+ http = mock(Net::HTTP)
98
+ Net::HTTP.should_receive(:new).with('localhost', 3000).and_return(http)
99
+
100
+ http.should_receive(:put).with('/glassware', '<ooga>Booga</ooga>', {'page' => '2', 'per_page' => '5'}).and_return(build_ok_response)
101
+
102
+ uri.put '<ooga>Booga</ooga>', :page => '2', :per_page => '5'
103
+ end
104
+
105
+ it "should know how to delete" do
106
+ uri = "http://localhost:3000/glassware".to_uri
107
+ uri.should_not be_https
108
+
109
+ http = mock(Net::HTTP)
110
+ Net::HTTP.should_receive(:new).with('localhost', 3000).and_return(http)
111
+
112
+ http.should_receive(:delete).with('/glassware', {'page' => '2', 'per_page' => '5'}).and_return(build_ok_response(nil))
113
+
114
+ uri.delete(:page => '2', :per_page => '5')
115
+ end
116
+
117
+ it "should not mutate state of the uri across requests" do
118
+ uri = "http://localhost:3000/glassware".to_uri
119
+ uri.should_not be_https
120
+
121
+ http = mock(Net::HTTP)
122
+ Net::HTTP.should_receive(:new).with('localhost', 3000).any_number_of_times.and_return(http)
123
+
124
+ http.should_receive(:get).with('/glassware?owner=Kai&type=bottle', 'page' => '2', 'per_page' => '5').and_return(build_ok_response)
125
+ http.should_receive(:post).with('/glassware', '<ooga>Booga</ooga>', {'page' => '2', 'per_page' => '5'}).and_return(build_ok_response)
126
+
127
+ uri.get({:owner => 'Kai', :type => 'bottle'}, :page => '2', :per_page => '5')
128
+ uri.post '<ooga>Booga</ooga>', :page => '2', :per_page => '5'
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,28 @@
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
13
+ describe UriTemplate do
14
+ it "should not maintain a reference to the string it is initialized with" do
15
+ url_pattern = "http://localhost:3000/:resource/:id.:format"
16
+ template = UriTemplate.new(url_pattern)
17
+ url_pattern.gsub!(':', '!')
18
+ template.uri_pattern.should == "http://localhost:3000/:resource/:id.:format"
19
+ end
20
+
21
+ it "should know how to build a Wrest::Uri from the pattern given a set of replacement options" do
22
+ template = UriTemplate.new("http://localhost:3000/:resource/:id.:format")
23
+ template.to_uri(
24
+ :resource => 'shen_coins', :id => 5, :format => :json
25
+ ).should == "http://localhost:3000/shen_coins/5.json".to_uri
26
+ end
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wrest
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Sidu Ponnappa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-04-19 00:00:00 +05:30
13
+ default_executable: wrest
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.1.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.3
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: xml-simple
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.11
44
+ version:
45
+ description: Wrest is a REST client library which allows you to quickly build object oriented wrappers around any web service. It has two main components - Wrest Core and Wrest::Resource.
46
+ email: ckponnappa@gmail.com
47
+ executables:
48
+ - wrest
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README.rdoc
53
+ files:
54
+ - README.rdoc
55
+ - Rakefile
56
+ - VERSION.yml
57
+ - bin/wrest
58
+ - lib/wrest.rb
59
+ - lib/wrest/core_ext/string.rb
60
+ - lib/wrest/core_ext/string/conversions.rb
61
+ - lib/wrest/exceptions.rb
62
+ - lib/wrest/exceptions/unsupported_content_type_exception.rb
63
+ - lib/wrest/mappers.rb
64
+ - lib/wrest/mappers/attributes_container.rb
65
+ - lib/wrest/mappers/resource.rb
66
+ - lib/wrest/mappers/resource/base.rb
67
+ - lib/wrest/mappers/resource/collection.rb
68
+ - lib/wrest/mappers/simple_resource.rb
69
+ - lib/wrest/response.rb
70
+ - lib/wrest/translators.rb
71
+ - lib/wrest/translators/content_types.rb
72
+ - lib/wrest/translators/json.rb
73
+ - lib/wrest/translators/typed_hash.rb
74
+ - lib/wrest/translators/xml.rb
75
+ - lib/wrest/uri.rb
76
+ - lib/wrest/uri_template.rb
77
+ - lib/wrest/version.rb
78
+ - spec/custom_matchers/custom_matchers.rb
79
+ - spec/rcov.opts
80
+ - spec/spec.opts
81
+ - spec/spec_helper.rb
82
+ - spec/wrest/mappers/attributes_container_spec.rb
83
+ - spec/wrest/mappers/resource/base_spec.rb
84
+ - spec/wrest/mappers/simple_resource_spec.rb
85
+ - spec/wrest/response_spec.rb
86
+ - spec/wrest/translators/typed_hash_spec.rb
87
+ - spec/wrest/translators/xml_spec.rb
88
+ - spec/wrest/translators_spec.rb
89
+ - spec/wrest/uri_spec.rb
90
+ - spec/wrest/uri_template_spec.rb
91
+ has_rdoc: true
92
+ homepage: http://github.com/kaiwren/wrest
93
+ licenses: []
94
+
95
+ post_install_message:
96
+ rdoc_options:
97
+ - --charset=UTF-8
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: "0"
105
+ version:
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: "0"
111
+ version:
112
+ requirements: []
113
+
114
+ rubyforge_project: wrest
115
+ rubygems_version: 1.3.2
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: REST client library for Ruby.
119
+ test_files:
120
+ - spec/custom_matchers/custom_matchers.rb
121
+ - spec/spec_helper.rb
122
+ - spec/wrest/mappers/attributes_container_spec.rb
123
+ - spec/wrest/mappers/resource/base_spec.rb
124
+ - spec/wrest/mappers/simple_resource_spec.rb
125
+ - spec/wrest/response_spec.rb
126
+ - spec/wrest/translators/typed_hash_spec.rb
127
+ - spec/wrest/translators/xml_spec.rb
128
+ - spec/wrest/translators_spec.rb
129
+ - spec/wrest/uri_spec.rb
130
+ - spec/wrest/uri_template_spec.rb