kaiwren-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 +203 -0
  3. data/VERSION.yml +4 -0
  4. data/bin/wrest +22 -0
  5. data/lib/wrest.rb +41 -0
  6. data/lib/wrest/core_ext/string.rb +5 -0
  7. data/lib/wrest/core_ext/string/conversions.rb +23 -0
  8. data/lib/wrest/exceptions.rb +1 -0
  9. data/lib/wrest/exceptions/unsupported_content_type_exception.rb +15 -0
  10. data/lib/wrest/mappers.rb +21 -0
  11. data/lib/wrest/mappers/attributes_container.rb +123 -0
  12. data/lib/wrest/mappers/resource.rb +17 -0
  13. data/lib/wrest/mappers/resource/base.rb +69 -0
  14. data/lib/wrest/mappers/resource/collection.rb +12 -0
  15. data/lib/wrest/mappers/simple_resource.rb +17 -0
  16. data/lib/wrest/response.rb +38 -0
  17. data/lib/wrest/translators.rb +26 -0
  18. data/lib/wrest/translators/content_types.rb +20 -0
  19. data/lib/wrest/translators/json.rb +21 -0
  20. data/lib/wrest/translators/typed_hash.rb +4 -0
  21. data/lib/wrest/translators/xml.rb +24 -0
  22. data/lib/wrest/uri.rb +74 -0
  23. data/lib/wrest/uri_template.rb +32 -0
  24. data/lib/wrest/version.rb +22 -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 +128 -0
@@ -0,0 +1,104 @@
1
+ = Wrest
2
+
3
+ (c) Copyright 2009 {Sidu Ponnappa}[http://blog.sidu.in]. All Rights Reserved.
4
+
5
+ Wrest is a ruby REST client library which allows you to quickly build object oriented wrappers around any web service. It has two components - Wrest Core and Wrest::Resource.
6
+
7
+ == Installation
8
+
9
+ The source is available at git://github.com/kaiwren/wrest.git
10
+
11
+ To install as a Rails plugin, do <tt>script/plugin install git://github.com/kaiwren/wrest.git</tt>
12
+
13
+ To install the Wrest gem, you'll need to add GitHub to you gem sources if you haven't already done so:
14
+
15
+ gem sources -a http://gems.github.com
16
+
17
+ Then to install Wrest and its dependencies:
18
+
19
+ sudo gem install kaiwren-wrest
20
+
21
+
22
+ == Wrest Core
23
+
24
+ * Designed to be used as a library, not just a command line REST client
25
+ * Provides basic infrastructure (including an interactive shell) and convenient HTTP wrappers
26
+ * Makes it easy to extend and modify both serialisation, deserialisation and object creation
27
+ * Isn't coupled to Rails (usable in a pure Ruby application to consume any REST api)
28
+ * Can be used both stand alone as well as to build object oriented abstractions around web services (Wrest::Resource is an example of the latter)
29
+
30
+ === Usage: Shell
31
+
32
+ You can launch the interactive Wrest shell by running bin/wrest if you have the source or invoking <tt>wrest</tt> from your prompt if you've installed the gem.
33
+ $ wrest
34
+ >> "http://search.yahooapis.com/NewsSearchService/V1/newsSearch?appid=YahooDemo&output=json&query=India&results=3&start=1".to_uri.get
35
+
36
+ === Usage: Library
37
+
38
+ require 'rubygems'
39
+ require 'wrest'
40
+ y "http://search.yahooapis.com/NewsSearchService/V1/newsSearch".to_uri.get(
41
+ :appid => 'YahooDemo',
42
+ :output => 'xml',
43
+ :query => 'India',
44
+ :results=> '3',
45
+ :start => '1'
46
+ )
47
+ === Basic Http Calls
48
+
49
+ ==== Get
50
+
51
+ A couple of ways to get the Yahoo news as hash map (needs the JSON gem - gem install json).
52
+
53
+ * This example simply does a get on a uri and figures out the appropriate deserialiser using the content-type (in this case 'text/javascript', which uses Wrest::Translators::Json). See content_types.rb under lib/wrest/mappers/translators.
54
+ "http://search.yahooapis.com/NewsSearchService/V1/newsSearch?appid=YahooDemo&output=json&query=India&results=3&start=1".to_uri.get.deserialise
55
+
56
+ * This example does a get on a base uri with several parameters passed to it, resulting in a uri essentially the same as the one above. It also shows how you can use a custom deserialiser to produce a hash-map from the response.
57
+ "http://search.yahooapis.com/NewsSearchService/V1/newsSearch".to_uri.get(
58
+ :appid => 'YahooDemo',
59
+ :output => 'xml',
60
+ :query => 'India',
61
+ :results=> '3',
62
+ :start => '1'
63
+ ).deserialise_using(Wrest::Translators::Xml)
64
+
65
+
66
+ === Logging
67
+
68
+ The Wrest logger can be set and accessed through Wrest.logger and is configured by default to log to STDOUT. If you're using Wrest in a Rails application, you can configure logging by placing the following line in your environment file:
69
+ Wrest.logger = ActiveRecord::Base.logger
70
+
71
+ === Build
72
+
73
+ Standard options are available and can be listed using <tt>rake -T</tt>. Use rake:rcov for coverage and rake:rdoc to generate documentation.
74
+
75
+ == Wrest::Resource
76
+
77
+ Wrest::Resource is an alternative to ActiveResource which targets Rails REST services; it is currently under development.
78
+
79
+ * Out of the box support for collections
80
+ * Out of the box support for collection pagination (including support for WillPaginate), both header based and xml attribute based
81
+ * Out of the box support for operations on all the records on the collection
82
+ * Out of the box support for nested resources
83
+ * Out of the box support for cached resources
84
+ * Out of the box support for type-casting data that comes in as parameter strings
85
+ * More natural mapping of deserialised entities to existing classes
86
+ * No communication via exceptions for http error status codes
87
+ * Better extensibility - allows access to request/response objects, avoids class variables, favours symbols over strings etc.
88
+
89
+ == Dependencies
90
+
91
+ * gems
92
+ * xmlsimple
93
+ * json
94
+ * rspec
95
+ * rcov
96
+ * active_support
97
+
98
+ == Support
99
+
100
+ This project uses Assembla for ticketing: http://www.assembla.com/spaces/wrest/tickets
101
+
102
+ == Licence
103
+
104
+ Wrest is released under the Apache 2.0 licence
@@ -0,0 +1,203 @@
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
+ gem 'rspec'
11
+ require 'rake'
12
+ require 'rake/rdoctask'
13
+ require 'spec'
14
+ require 'spec/rake/spectask'
15
+ require 'rcov'
16
+ require 'rcov/rcovtask'
17
+
18
+ desc 'Default: run spec tests.'
19
+ task :default => :spec
20
+
21
+ desc "Run all specs"
22
+ Spec::Rake::SpecTask.new(:spec) do |task|
23
+ task.spec_files = FileList['spec/wrest/**/*_spec.rb']
24
+ task.spec_opts = ['--options', 'spec/spec.opts']
25
+ end
26
+
27
+ desc 'Generate documentation for Wrest'
28
+ Rake::RDocTask.new(:rdoc) do |rdoc|
29
+ rdoc.rdoc_dir = 'doc'
30
+ rdoc.title = 'WRest'
31
+ rdoc.options << '--line-numbers' << '--inline-source'
32
+ rdoc.rdoc_files.include('README.rdoc')
33
+ rdoc.rdoc_files.include('lib/**/*.rb')
34
+ end
35
+
36
+ desc "Run all specs in spec directory with RCov"
37
+ Spec::Rake::SpecTask.new(:rcov) do |t|
38
+ t.spec_opts = ['--options', "spec/spec.opts"]
39
+ t.spec_files = FileList["spec/wrest/**/*_spec.rb"]
40
+ t.rcov = true
41
+ t.rcov_opts = lambda do
42
+ IO.readlines("spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
43
+ end
44
+ # t.verbose = true
45
+ end
46
+
47
+ begin
48
+ require 'jeweler'
49
+ Jeweler::Tasks.new do |gemspec|
50
+ gemspec.name = "wrest"
51
+ gemspec.version = "0.0.3"
52
+ gemspec.summary = "REST client library for Ruby."
53
+ gemspec.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."
54
+ gemspec.authors = ["Sidu Ponnappa"]
55
+ gemspec.email = "ckponnappa@gmail.com"
56
+ gemspec.homepage = "http://github.com/kaiwren/wrest"
57
+ gemspec.has_rdoc = true
58
+ gemspec.platform = Gem::Platform::RUBY
59
+ gemspec.executables = ['wrest']
60
+ gemspec.require_path = "lib"
61
+ gemspec.files.exclude 'spec/wrest/meh_spec.rb'
62
+ gemspec.test_files.exclude 'spec/wrest/meh_spec.rb'
63
+ gemspec.add_dependency('activesupport', '>= 2.1.0')
64
+ gemspec.add_dependency('json', '>= 1.1.3')
65
+ gemspec.add_dependency('xml-simple', '>= 1.0.11')
66
+ end
67
+ rescue LoadError
68
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
69
+ end
70
+
71
+ namespace (:benchmark) do
72
+ desc "Create classes to be used in Wrest::Resource vs. ActiveResource"
73
+ task :setup_test_classes do
74
+ require 'active_resource'
75
+ require 'wrest'
76
+
77
+ class Ooga < Wrest::Mappers::Resource::Base;end
78
+ class Booga < ActiveResource::Base; self.site='';end
79
+ end
80
+
81
+ desc "Benchmark when objects are created each time before getting data; i.e there are few queries per instantiation"
82
+ task :create_and_get => :setup_test_classes do |t|
83
+
84
+ n = 10000
85
+ puts "Running #{n} times per report"
86
+ Benchmark.bmbm(10) do |rpt|
87
+ rpt.report("Wrest::Resource") do
88
+ n.times {
89
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
90
+ ooga.profession
91
+ ooga.profession?
92
+ ooga.enhanced_by
93
+ ooga.enhanced_by?
94
+ }
95
+ end
96
+
97
+ rpt.report("ActiveResource") do
98
+ n.times {
99
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
100
+ booga.profession
101
+ booga.profession?
102
+ booga.enhanced_by
103
+ booga.enhanced_by?
104
+ }
105
+ end
106
+ end
107
+ end
108
+
109
+ desc "Benchmark when objects are created beforehand; i.e there are many queries per instantiation"
110
+ task :create_once_and_get => :setup_test_classes do |t|
111
+
112
+ n = 10000
113
+ puts "Running #{n} times per report"
114
+
115
+ Benchmark.bmbm(10) do |rpt|
116
+ rpt.report("Wrest::Resource") do
117
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
118
+
119
+ n.times {
120
+ ooga.profession
121
+ ooga.profession?
122
+ ooga.enhanced_by
123
+ ooga.enhanced_by?
124
+ }
125
+ end
126
+
127
+ rpt.report("ActiveResource") do
128
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
129
+
130
+ n.times {
131
+ booga.profession
132
+ booga.profession?
133
+ booga.enhanced_by
134
+ booga.enhanced_by?
135
+ }
136
+ end
137
+ end
138
+ end
139
+
140
+ desc "Benchmark objects respond_to? performance without invocation"
141
+ task :responds_to_before => :setup_test_classes do |t|
142
+
143
+ n = 10000
144
+ puts "Running #{n} times per report"
145
+
146
+ Benchmark.bmbm(10) do |rpt|
147
+ rpt.report("Wrest::Resource") do
148
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
149
+
150
+ n.times {
151
+ ooga.respond_to?(:profession)
152
+ ooga.respond_to?(:profession?)
153
+ ooga.respond_to?(:profession=)
154
+ }
155
+ end
156
+
157
+ rpt.report("ActiveResource") do
158
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
159
+
160
+ n.times {
161
+ booga.respond_to?(:profession)
162
+ booga.respond_to?(:profession?)
163
+ booga.respond_to?(:profession=)
164
+ }
165
+ end
166
+ end
167
+ end
168
+
169
+ desc "Benchmark objects respond_to? performance after invocation"
170
+ task :responds_to_after => :setup_test_classes do |t|
171
+
172
+ n = 10000
173
+ puts "Running #{n} times per report"
174
+
175
+ Benchmark.bmbm(10) do |rpt|
176
+ rpt.report("Wrest::Resource") do
177
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
178
+ ooga.profession
179
+ ooga.profession?
180
+ ooga.profession = ''
181
+
182
+ n.times {
183
+ ooga.respond_to?(:profession)
184
+ ooga.respond_to?(:profession?)
185
+ ooga.respond_to?(:profession=)
186
+ }
187
+ end
188
+
189
+ rpt.report("ActiveResource") do
190
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
191
+ booga.profession
192
+ booga.profession?
193
+ booga.profession = ''
194
+
195
+ n.times {
196
+ booga.respond_to?(:profession)
197
+ booga.respond_to?(:profession?)
198
+ booga.respond_to?(:profession=)
199
+ }
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 4
3
+ :minor: 0
4
+ :major: 0
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #!/usr/bin/env ruby
4
+ entry_point = "#{File.dirname(__FILE__)}/../lib/wrest.rb"
5
+ version = "#{File.dirname(__FILE__)}/../lib/wrest/version"
6
+
7
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
8
+
9
+ require 'optparse'
10
+ options = { :irb => irb }
11
+ OptionParser.new do |opt|
12
+ opt.banner = "Usage: console [options]"
13
+ opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
14
+ opt.parse!(ARGV)
15
+ end
16
+
17
+ libs = " -r irb/completion"
18
+ libs << " -r #{entry_point}"
19
+
20
+ require version
21
+ puts "Loading (Wrest #{Wrest::VERSION::STRING})"
22
+ exec "#{options[:irb]} #{libs} --simple-prompt"
@@ -0,0 +1,41 @@
1
+ # Copyright 2009 Sidu Ponnappa
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
5
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
6
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7
+ # See the License for the specific language governing permissions and limitations under the License.
8
+
9
+ require 'rubygems'
10
+ require 'net/http'
11
+ require 'net/https'
12
+ require 'forwardable'
13
+ require 'date'
14
+ require 'cgi'
15
+ require 'base64'
16
+ require 'logger'
17
+ require 'benchmark'
18
+ require 'active_support'
19
+
20
+ WREST_ROOT = File.dirname(__FILE__)
21
+
22
+ module Wrest
23
+ def self.logger=(logger)
24
+ @logger = logger
25
+ end
26
+
27
+ def self.logger
28
+ @logger
29
+ end
30
+ end
31
+
32
+ Wrest.logger = Logger.new(STDOUT)
33
+ Wrest.logger.level = Logger::DEBUG
34
+
35
+ source_dirs = ["/wrest/core_ext/*.rb", "/wrest/*.rb"]
36
+
37
+ source_dirs.each{|directory|
38
+ Dir["#{File.expand_path(File.dirname(__FILE__) + directory)}"].each { |file|
39
+ require file
40
+ }
41
+ }
@@ -0,0 +1,5 @@
1
+ require "#{WREST_ROOT}/wrest/core_ext/string/conversions"
2
+
3
+ class String #:nodoc:
4
+ include Wrest::CoreExt::String::Conversions
5
+ end
@@ -0,0 +1,23 @@
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
+ module Wrest
11
+ module CoreExt #:nodoc:
12
+ module String #:nodoc:
13
+ # Makes it easier to build other objects from a String
14
+ module Conversions
15
+
16
+ # A convenience method equivalent to Wrest::Uri.new(string)
17
+ def to_uri
18
+ Wrest::Uri.new(self)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1 @@
1
+ require "#{WREST_ROOT}/wrest/exceptions/unsupported_content_type_exception"
@@ -0,0 +1,15 @@
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
+ module Wrest
11
+ # Raised when a translator for an unregisterd response content type
12
+ # is requested. See Translators.
13
+ class UnsupportedContentTypeException < StandardError
14
+ end
15
+ end
@@ -0,0 +1,21 @@
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
+ module Wrest #:nodoc:
11
+ # A Mapper is anything that constructs an object
12
+ # or object graph from a hash map. This hash map
13
+ # is typically obtained by using a Translator to
14
+ # deserialise a Response.
15
+ module Mappers
16
+ end
17
+ end
18
+
19
+ require "#{WREST_ROOT}/wrest/mappers/attributes_container"
20
+ require "#{WREST_ROOT}/wrest/mappers/simple_resource"
21
+ require "#{WREST_ROOT}/wrest/mappers/resource"