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
data/README.rdoc ADDED
@@ -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
data/Rakefile ADDED
@@ -0,0 +1,230 @@
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.summary = "REST client library for Ruby."
52
+ 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."
53
+ gemspec.authors = ["Sidu Ponnappa"]
54
+ gemspec.email = "ckponnappa@gmail.com"
55
+ gemspec.homepage = "http://github.com/kaiwren/wrest"
56
+ gemspec.has_rdoc = true
57
+ gemspec.rubyforge_project = 'wrest'
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
+ begin
72
+ require 'rake/contrib/sshpublisher'
73
+ namespace :rubyforge do
74
+
75
+ desc "Release gem and RDoc documentation to RubyForge"
76
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
77
+
78
+ namespace :release do
79
+ desc "Publish RDoc to RubyForge."
80
+ task :docs => [:rdoc] do
81
+ config = YAML.load(
82
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
83
+ )
84
+
85
+ host = "#{config['username']}@rubyforge.org"
86
+ remote_dir = "/var/www/gforge-projects/the-perfect-gem/"
87
+ local_dir = 'rdoc'
88
+
89
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
90
+ end
91
+ end
92
+ end
93
+ rescue LoadError
94
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
95
+ end
96
+
97
+
98
+ namespace (:benchmark) do
99
+ desc "Create classes to be used in Wrest::Resource vs. ActiveResource"
100
+ task :setup_test_classes do
101
+ require 'active_resource'
102
+ require 'wrest'
103
+
104
+ class Ooga < Wrest::Mappers::Resource::Base;end
105
+ class Booga < ActiveResource::Base; self.site='';end
106
+ end
107
+
108
+ desc "Benchmark when objects are created each time before getting data; i.e there are few queries per instantiation"
109
+ task :create_and_get => :setup_test_classes do |t|
110
+
111
+ n = 10000
112
+ puts "Running #{n} times per report"
113
+ Benchmark.bmbm(10) do |rpt|
114
+ rpt.report("Wrest::Resource") do
115
+ n.times {
116
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
117
+ ooga.profession
118
+ ooga.profession?
119
+ ooga.enhanced_by
120
+ ooga.enhanced_by?
121
+ }
122
+ end
123
+
124
+ rpt.report("ActiveResource") do
125
+ n.times {
126
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
127
+ booga.profession
128
+ booga.profession?
129
+ booga.enhanced_by
130
+ booga.enhanced_by?
131
+ }
132
+ end
133
+ end
134
+ end
135
+
136
+ desc "Benchmark when objects are created beforehand; i.e there are many queries per instantiation"
137
+ task :create_once_and_get => :setup_test_classes do |t|
138
+
139
+ n = 10000
140
+ puts "Running #{n} times per report"
141
+
142
+ Benchmark.bmbm(10) do |rpt|
143
+ rpt.report("Wrest::Resource") do
144
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
145
+
146
+ n.times {
147
+ ooga.profession
148
+ ooga.profession?
149
+ ooga.enhanced_by
150
+ ooga.enhanced_by?
151
+ }
152
+ end
153
+
154
+ rpt.report("ActiveResource") do
155
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
156
+
157
+ n.times {
158
+ booga.profession
159
+ booga.profession?
160
+ booga.enhanced_by
161
+ booga.enhanced_by?
162
+ }
163
+ end
164
+ end
165
+ end
166
+
167
+ desc "Benchmark objects respond_to? performance without invocation"
168
+ task :responds_to_before => :setup_test_classes do |t|
169
+
170
+ n = 10000
171
+ puts "Running #{n} times per report"
172
+
173
+ Benchmark.bmbm(10) do |rpt|
174
+ rpt.report("Wrest::Resource") do
175
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
176
+
177
+ n.times {
178
+ ooga.respond_to?(:profession)
179
+ ooga.respond_to?(:profession?)
180
+ ooga.respond_to?(:profession=)
181
+ }
182
+ end
183
+
184
+ rpt.report("ActiveResource") do
185
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
186
+
187
+ n.times {
188
+ booga.respond_to?(:profession)
189
+ booga.respond_to?(:profession?)
190
+ booga.respond_to?(:profession=)
191
+ }
192
+ end
193
+ end
194
+ end
195
+
196
+ desc "Benchmark objects respond_to? performance after invocation"
197
+ task :responds_to_after => :setup_test_classes do |t|
198
+
199
+ n = 10000
200
+ puts "Running #{n} times per report"
201
+
202
+ Benchmark.bmbm(10) do |rpt|
203
+ rpt.report("Wrest::Resource") do
204
+ ooga = Ooga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
205
+ ooga.profession
206
+ ooga.profession?
207
+ ooga.profession = ''
208
+
209
+ n.times {
210
+ ooga.respond_to?(:profession)
211
+ ooga.respond_to?(:profession?)
212
+ ooga.respond_to?(:profession=)
213
+ }
214
+ end
215
+
216
+ rpt.report("ActiveResource") do
217
+ booga = Booga.new(:id => 5, :profession => 'Natural Magician', :enhanced_by => 'Kai Wren')
218
+ booga.profession
219
+ booga.profession?
220
+ booga.profession = ''
221
+
222
+ n.times {
223
+ booga.respond_to?(:profession)
224
+ booga.respond_to?(:profession?)
225
+ booga.respond_to?(:profession=)
226
+ }
227
+ end
228
+ end
229
+ end
230
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 4
3
+ :minor: 0
4
+ :major: 0
data/bin/wrest ADDED
@@ -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,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,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,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 @@
1
+ require "#{WREST_ROOT}/wrest/exceptions/unsupported_content_type_exception"
@@ -0,0 +1,123 @@
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::Mappers #:nodoc:
11
+
12
+ # Adds behaviour allowing a class to
13
+ # contain attributes and providing support
14
+ # for dynamic getters, setters and query methods.
15
+ # These methods are added at runtime, on the first
16
+ # invocation and on a per instance basis.
17
+ # <tt>respond_to?</tt> however will respond as though
18
+ # they are all already present.
19
+ # This means that two different instances of the same
20
+ # <tt>AttributesContainer</tt> could well have
21
+ # different attribute getters/setters/query methods.
22
+ #
23
+ # Note that this means the first call to a particular
24
+ # method will be slower because the method is defined
25
+ # at that point; subsequent calls will be much faster.
26
+ #
27
+ # If you're implementing your own initialize method
28
+ # remember to delegate to the default initialize
29
+ # of AttributesContainer by invoking <tt>super(attributes)</tt>
30
+ # Also keep in mind that attribute getter/setter/query methods
31
+ # will _not_ override any existing methods on the class.
32
+ #
33
+ # In situations where this is a problem, such as a client consuming Rails
34
+ # REST services where <tt>id</tt> is a common attribute and clashes with
35
+ # Object#id it is recommended to create getter/setter/query methods
36
+ # on the class (which affects all instances) using the <tt>has_attributes</tt> macro.
37
+ module AttributesContainer
38
+ def self.included(klass) #:nodoc:
39
+ klass.extend AttributesContainer::ClassMethods
40
+ klass.class_eval{ include AttributesContainer::InstanceMethods }
41
+ end
42
+
43
+ def self.build_attribute_getter(attribute_name) #:nodoc:
44
+ "def #{attribute_name};@attributes[:#{attribute_name}];end;"
45
+ end
46
+
47
+ def self.build_attribute_setter(attribute_name) #:nodoc:
48
+ "def #{attribute_name}=(value);@attributes[:#{attribute_name}] = value;end;"
49
+ end
50
+
51
+ def self.build_attribute_queryer(attribute_name) #:nodoc:
52
+ "def #{attribute_name}?;not @attributes[:#{attribute_name}].nil?;end;"
53
+ end
54
+
55
+ module ClassMethods
56
+ # This macro explicitly creates getter, setter and query methods on
57
+ # a class, overriding any exisiting methods with the same names.
58
+ # This can be used when attribute names clash with method names;
59
+ # an example would be Rails REST services which frequently make use
60
+ # an attribute named <tt>id</tt> which clashes with Object#id. Also,
61
+ # this can be used as a performance optimisation if the incoming
62
+ # attributes are known beforehand, as defining methods on the first
63
+ # invocation is no longer necessary.
64
+ def has_attributes(*attribute_names)
65
+ attribute_names.each do |attribute_name|
66
+ self.class_eval(
67
+ AttributesContainer.build_attribute_getter(attribute_name) +
68
+ AttributesContainer.build_attribute_setter(attribute_name) +
69
+ AttributesContainer.build_attribute_queryer(attribute_name)
70
+ )
71
+ end
72
+ end
73
+ end
74
+
75
+ module InstanceMethods
76
+ # Sets up any class to act like
77
+ # an attributes container by creating
78
+ # two variables, @attributes and @interface.
79
+ # Remember not to use these two variable names
80
+ # when using AttributesContainer in your
81
+ # own class.
82
+ def initialize(attributes = {})
83
+ @attributes = attributes.symbolize_keys
84
+ @interface = Module.new
85
+ self.extend @interface
86
+ end
87
+
88
+ def [](key)
89
+ @attributes[key.to_sym]
90
+ end
91
+
92
+ def []=(key, value)
93
+ @attributes[key.to_sym] = value
94
+ end
95
+
96
+ def respond_to?(method_name, include_private = false)
97
+ super(method_name, include_private) ? true : @attributes.include?(method_name.to_s.gsub(/(\?$)|(=$)/, '').to_sym)
98
+ end
99
+
100
+ # Creates getter, setter and query methods for
101
+ # attributes on the first call.
102
+ def method_missing(method_sym, *arguments)
103
+ method_name = method_sym.to_s
104
+ attribute_name = method_name.gsub(/(\?$)|(=$)/, '')
105
+
106
+ if @attributes.include?(attribute_name.to_sym) || method_name.last == '='
107
+ case method_name.last
108
+ when '='
109
+ @interface.module_eval AttributesContainer.build_attribute_setter(attribute_name)
110
+ when '?'
111
+ @interface.module_eval AttributesContainer.build_attribute_queryer(attribute_name)
112
+ else
113
+ @interface.module_eval AttributesContainer.build_attribute_getter(attribute_name)
114
+ end
115
+ send(method_sym, *arguments)
116
+ else
117
+ super(method_sym, *arguments)
118
+ end
119
+ end
120
+
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,69 @@
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::Mappers::Resource #:nodoc:
11
+ # Resource::Base is the equivalent of ActiveResource::Base.
12
+ # It is a REST client targetted at Rails REST apps.
13
+ class Base
14
+ include Wrest::Mappers::AttributesContainer
15
+
16
+ has_attributes :id
17
+ attr_reader :attributes
18
+
19
+ class << self
20
+ def inherited(klass)
21
+ klass.set_resource_name klass.name
22
+ end
23
+
24
+ # Allows the resource name to be configured and creates
25
+ # a getter method for it.
26
+ # This is a useful feature when using anonymous classes like
27
+ # we often do while writing tests.
28
+ # By default, the resource name is set to the name of the class.
29
+ def set_resource_name(resource_name)
30
+ self.class_eval "def self.resource_name; '#{resource_name}';end"
31
+ end
32
+
33
+ # Allows the host url at which the resource is found to be configured
34
+ # and creates a getter method for it.
35
+ # For example in the url
36
+ # http://localhost:3000/users/1/settings
37
+ # you would set
38
+ # http://localhost:3000
39
+ # as the host url.
40
+ def set_host(host)
41
+ self.class_eval "def self.host; '#{host}';end"
42
+ end
43
+
44
+ def resource_path
45
+ @resource_path ||= "/#{resource_name.underscore.pluralize}"
46
+ end
47
+
48
+ def resource_url
49
+ "#{host}#{resource_path}"
50
+ end
51
+
52
+ def find_all
53
+ end
54
+
55
+ def find(id)
56
+ response_hash = "#{resource_url}/#{id}".to_uri.get.deserialise
57
+ resource_type = response_hash.keys.first
58
+ if(resource_type.underscore.camelize == self.name)
59
+ self.new(response_hash[resource_type].first)
60
+ else
61
+ response_hash
62
+ end
63
+ end
64
+
65
+ def objectify(hash)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,12 @@
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
+ # Understands how to contain a collection of Wrest::Resources
11
+ class Wrest::Mappers::Resource::Collection
12
+ end
@@ -0,0 +1,17 @@
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 Mappers
12
+ module Resource
13
+ end
14
+ end
15
+ end
16
+
17
+ require "#{WREST_ROOT}/wrest/mappers/resource/base"
@@ -0,0 +1,17 @@
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 Mappers
12
+ class SimpleResource
13
+ include Wrest::Mappers::AttributesContainer
14
+ attr_reader :attributes
15
+ end
16
+ end
17
+ 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"