dm-rest-adapter 0.9.11 → 0.10.0

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.
@@ -15,9 +15,16 @@ module DataMapperRest
15
15
  # this is used to run the http verbs like http_post, http_put, http_delete etc.
16
16
  # TODO: handle nested resources, see prefix in ActiveResource
17
17
  def method_missing(method, *args)
18
- @uri.path = "/#{args[0]}.#{@format.extension}" # Should be the form of /resources
19
- if verb = method.to_s.match(/^http_(get|post|put|delete|head)$/)
20
- run_verb(verb.to_s.split("_").last, args[1])
18
+ if verb = method.to_s.match(/\Ahttp_(get|post|put|delete|head)\z/)
19
+
20
+ orig_uri, @uri = @uri, @uri.dup
21
+ begin
22
+ path, query = args[0].split('?', 2)
23
+ @uri.path = "#{path}.#{@format.extension}#{'?' << query if query}" # Should be the form of /resources
24
+ run_verb(verb.to_s.split('_').last, args[1])
25
+ ensure
26
+ @uri = orig_uri
27
+ end
21
28
  end
22
29
  end
23
30
 
@@ -25,8 +32,8 @@ module DataMapperRest
25
32
 
26
33
  def run_verb(verb, data = nil)
27
34
  request do |http|
28
- mod = Net::HTTP::module_eval(Inflection.camelize(verb))
29
- request = mod.new(@uri.to_s, @format.header)
35
+ klass = Net::HTTP.find_const(Inflection.camelize(verb))
36
+ request = klass.new(@uri.to_s, @format.header)
30
37
  request.basic_auth(@uri.user, @uri.password) if @uri.user && @uri.password
31
38
  result = http.request(request, data)
32
39
 
@@ -44,9 +44,9 @@ module DataMapperRest
44
44
  # 409 Conflict
45
45
  class ResourceConflict < ClientError; end # :nodoc:
46
46
 
47
- # 422
47
+ # 422 Unprocessable Entity
48
48
  class ResourceInvalid < ClientError; # :nodoc:
49
- # On this case, we could try to retrieve the validation_errors from message body:
49
+ # On this case, we could try to retrieve the validation_errors from message body:
50
50
  attr_reader :body
51
51
  def initialize(response, message = nil)
52
52
  super(response, message)
@@ -9,7 +9,7 @@ module DataMapperRest
9
9
  end
10
10
 
11
11
  def header
12
- {'Content-Type' => @mime}
12
+ { 'Content-Type' => @mime }
13
13
  end
14
14
 
15
15
  end
@@ -1,3 +1,3 @@
1
1
  module DataMapperRest
2
- VERSION = '0.9.11'
2
+ VERSION = '0.10.0'.freeze
3
3
  end
@@ -0,0 +1,8 @@
1
+ class Book
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :created_at, DateTime
6
+ property :title, String
7
+ property :author, String
8
+ end
@@ -1,4 +1,3 @@
1
- $LOAD_PATH << File.dirname(__FILE__)
2
1
  require 'spec_helper'
3
2
 
4
3
  describe 'A Connection instance' do
@@ -6,15 +5,14 @@ describe 'A Connection instance' do
6
5
  before do
7
6
  @username = "admin"
8
7
  @password = "tot@ls3crit"
9
- @uri = DataObjects::URI.parse(Addressable::URI.new(
10
- :scheme => 'http',
11
- :adapter => 'rest',
12
- :user => @username,
13
- :password => @password,
14
- :host => 'localhost',
15
- :port => '4000',
16
- :query => nil
17
- ))
8
+ @uri = Addressable::URI.new(
9
+ :scheme => 'http',
10
+ :user => @username,
11
+ :password => @password,
12
+ :host => 'localhost',
13
+ :port => '4000',
14
+ :query => nil
15
+ )
18
16
  @connection = DataMapperRest::Connection.new(@uri, "xml")
19
17
  end
20
18
 
@@ -0,0 +1,224 @@
1
+ require 'spec_helper'
2
+
3
+ describe DataMapper::Adapters::RestAdapter do
4
+ before :all do
5
+ @adapter = DataMapper::Repository.adapters[:default]
6
+ end
7
+
8
+ after :all do
9
+ FakeWeb.clean_registry
10
+ end
11
+
12
+ describe '#create' do
13
+ describe 'when provided a Resource' do
14
+ before :all do
15
+ body = <<-XML.compress_lines
16
+ <book>
17
+ <id type='datamapper::types::serial'>1</id>
18
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
19
+ <title>DataMapper</title>
20
+ <author>Dan Kubb</author>
21
+ </book>
22
+ XML
23
+
24
+ headers = { 'Content-Length' => body.respond_to?(:bytesize) ? body.bytesize : body.size }
25
+
26
+ FakeWeb.register_uri(:post, 'http://admin:secret@localhost:4000/books.xml', :status => 200, :headers => headers, :body => body)
27
+ end
28
+
29
+ before :all do
30
+ @resource = Book.new(:created_at => DateTime.parse('2009-05-17T22:38:42-07:00'), :title => 'DataMapper', :author => 'Dan Kubb')
31
+ @resources = [ @resource ]
32
+
33
+ @response = @adapter.create(@resources)
34
+ end
35
+
36
+ it 'should return an Array containing the Resource' do
37
+ @response.should equal(@resources)
38
+ end
39
+
40
+ it 'should set the identity field' do
41
+ @resource.id.should == 1
42
+ end
43
+ end
44
+ end
45
+
46
+ describe '#read' do
47
+ describe 'with unscoped query' do
48
+ before :all do
49
+ body = <<-XML.compress_lines
50
+ <books>
51
+ <book>
52
+ <id type='datamapper::types::serial'>1</id>
53
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
54
+ <title>DataMapper</title>
55
+ <author>Dan Kubb</author>
56
+ </book>
57
+ </books>
58
+ XML
59
+
60
+ headers = { 'Content-Length' => body.respond_to?(:bytesize) ? body.bytesize : body.size }
61
+
62
+ FakeWeb.register_uri(:get, 'http://admin:secret@localhost:4000/books.xml', :status => 200, :headers => headers, :body => body)
63
+ end
64
+
65
+ before :all do
66
+ @query = Book.all.query
67
+
68
+ @response = @adapter.read(@query)
69
+ end
70
+
71
+ it 'should return an Array with the matching Records' do
72
+ @response.should == [ { 'id' => 1, 'created_at' => DateTime.parse('2009-05-17T22:38:42-07:00'), 'title' => 'DataMapper', 'author' => 'Dan Kubb' } ]
73
+ end
74
+ end
75
+
76
+ describe 'with query scoped by a key' do
77
+ before :all do
78
+
79
+ end
80
+
81
+
82
+ before :all do
83
+ @query = Book.all(:id => 1, :limit => 1).query
84
+
85
+ body = <<-XML.compress_lines
86
+ <book>
87
+ <id type='datamapper::types::serial'>1</id>
88
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
89
+ <title>DataMapper</title>
90
+ <author>Dan Kubb</author>
91
+ </book>
92
+ XML
93
+
94
+ headers = { 'Content-Length' => body.respond_to?(:bytesize) ? body.bytesize : body.size }
95
+
96
+ FakeWeb.register_uri(:get, 'http://admin:secret@localhost:4000/books/1.xml', :status => 200, :headers => headers, :body => body)
97
+
98
+ @response = @adapter.read(@query)
99
+ end
100
+
101
+ it 'should return an Array with the matching Records' do
102
+ @response.should == [ { 'id' => 1, 'created_at' => DateTime.parse('2009-05-17T22:38:42-07:00'), 'title' => 'DataMapper', 'author' => 'Dan Kubb' } ]
103
+ end
104
+ end
105
+
106
+ describe 'with query scoped by a non-key' do
107
+ before :all do
108
+ body = <<-XML.compress_lines
109
+ <books>
110
+ <book>
111
+ <id type='datamapper::types::serial'>1</id>
112
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
113
+ <title>DataMapper</title>
114
+ <author>Dan Kubb</author>
115
+ </book>
116
+
117
+ <!-- provide an extra resource, which should be filtered out -->
118
+ <book>
119
+ <id type='datamapper::types::serial'>2</id>
120
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
121
+ <title>DataMapper</title>
122
+ <author>John Doe</author>
123
+ </book>
124
+ </books>
125
+ XML
126
+
127
+ headers = { 'Content-Length' => body.respond_to?(:bytesize) ? body.bytesize : body.size }
128
+
129
+ FakeWeb.register_uri(:get, 'http://admin:secret@localhost:4000/books.xml?author=Dan+Kubb', :status => 200, :headers => headers, :body => body)
130
+ end
131
+
132
+ before :all do
133
+ @query = Book.all(:author => 'Dan Kubb').query
134
+
135
+ @response = @adapter.read(@query)
136
+ end
137
+
138
+ it 'should return an Array with the matching Records' do
139
+ @response.should == [ { 'id' => 1, 'created_at' => DateTime.parse('2009-05-17T22:38:42-07:00'), 'title' => 'DataMapper', 'author' => 'Dan Kubb' } ]
140
+ end
141
+ end
142
+ end
143
+
144
+ describe '#update' do
145
+ before :all do
146
+ body = <<-XML.compress_lines
147
+ <books>
148
+ <book>
149
+ <id type='datamapper::types::serial'>1</id>
150
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
151
+ <title>DataMapper</title>
152
+ <author>Dan Kubb</author>
153
+ </book>
154
+ </books>
155
+ XML
156
+
157
+ headers = { 'Content-Length' => body.respond_to?(:bytesize) ? body.bytesize : body.size }
158
+
159
+ FakeWeb.register_uri(:get, 'http://admin:secret@localhost:4000/books.xml', :status => 200, :headers => headers, :body => body)
160
+ end
161
+
162
+ before :all do
163
+ body = <<-XML.compress_lines
164
+ <book>
165
+ <id type='datamapper::types::serial'>1</id>
166
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
167
+ <title>DataMapper</title>
168
+ <author>John Doe</author>
169
+ </book>
170
+ XML
171
+
172
+ headers = { 'Content-Length' => body.respond_to?(:bytesize) ? body.bytesize : body.size }
173
+
174
+ FakeWeb.register_uri(:put, 'http://admin:secret@localhost:4000/books/1.xml', :status => 200, :headers => headers, :body => body)
175
+ end
176
+
177
+ before :all do
178
+ @resources = Book.all
179
+
180
+ @response = @adapter.update({ Book.properties[:author] => 'John Doe' }, @resources)
181
+ end
182
+
183
+ it 'should return the number of updated Resources' do
184
+ @response.should == 1
185
+ end
186
+
187
+ it 'should modify the Resource' do
188
+ @resources.first.author.should == 'John Doe'
189
+ end
190
+ end
191
+
192
+ describe '#delete' do
193
+ before :all do
194
+ body = <<-XML.compress_lines
195
+ <books>
196
+ <book>
197
+ <id type='datamapper::types::serial'>1</id>
198
+ <created_at type='datetime'>2009-05-17T22:38:42-07:00</created_at>
199
+ <title>DataMapper</title>
200
+ <author>Dan Kubb</author>
201
+ </book>
202
+ </books>
203
+ XML
204
+
205
+ headers = { 'Content-Length' => body.respond_to?(:bytesize) ? body.bytesize : body.size }
206
+
207
+ FakeWeb.register_uri(:get, 'http://admin:secret@localhost:4000/books.xml', :status => 200, :headers => headers, :body => body)
208
+ end
209
+
210
+ before :all do
211
+ FakeWeb.register_uri(:delete, 'http://admin:secret@localhost:4000/books/1.xml', :status => 204)
212
+ end
213
+
214
+ before :all do
215
+ @resources = Book.all
216
+
217
+ @response = @adapter.delete(@resources)
218
+ end
219
+
220
+ it 'should return the number of updated Resources' do
221
+ @response.should == 1
222
+ end
223
+ end
224
+ end
@@ -1 +1,2 @@
1
1
  --colour
2
+ --loadby random
@@ -1,20 +1,31 @@
1
- require 'pathname'
2
1
  require 'rubygems'
2
+ require 'pathname'
3
+ require 'fakeweb'
4
+
5
+ # use local dm-core if running from a typical dev checkout.
6
+ lib = File.join('..', '..', '..', 'dm-core', 'lib')
7
+ $LOAD_PATH.unshift(lib) if File.directory?(lib)
8
+ require 'dm-core'
9
+
10
+ # use local dm-validations if running from a typical dev checkout.
11
+ lib = File.join('..', '..', 'dm-validations', 'lib')
12
+ $LOAD_PATH.unshift(lib) if File.directory?(lib)
13
+ require 'dm-validations'
14
+
15
+ # use local dm-serializer if running from a typical dev checkout.
16
+ lib = File.join('..', '..', 'dm-serializer', 'lib')
17
+ $LOAD_PATH.unshift(lib) if File.directory?(lib)
18
+ require 'dm-serializer'
19
+
20
+ # Support running specs with 'rake spec' and 'spec'
21
+ $LOAD_PATH.unshift('lib') unless $LOAD_PATH.include?('lib')
3
22
 
4
- ROOT = Pathname(__FILE__).dirname.parent.expand_path
23
+ require 'rest_adapter'
5
24
 
6
- # use local dm-serializer if running from dm-more directly
7
- lib = ROOT.parent.parent.join('dm-serializer', 'lib').expand_path
8
- $LOAD_PATH.unshift(lib) if lib.directory?
25
+ ROOT = Pathname(__FILE__).dirname.parent
9
26
 
10
- require ROOT + 'lib/rest_adapter'
27
+ DataMapper.setup(:default, 'rest://admin:secret@localhost:4000/?format=xml')
11
28
 
12
- load ROOT + 'config/database.rb.example'
29
+ Dir[ROOT / 'spec' / 'fixtures' / '**' / '*.rb'].each { |rb| require rb }
13
30
 
14
- class Book
15
- include DataMapper::Resource
16
- property :author, String
17
- property :created_at, DateTime
18
- property :id, Integer, :serial => true
19
- property :title, String
20
- end
31
+ FakeWeb.allow_net_connect = false
@@ -4,7 +4,7 @@ end
4
4
 
5
5
  desc "Install #{GEM_NAME} #{GEM_VERSION}"
6
6
  task :install => [ :package ] do
7
- sudo_gem "install --local pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
7
+ sudo_gem "install pkg/#{GEM_NAME}-#{GEM_VERSION} --no-update-sources"
8
8
  end
9
9
 
10
10
  desc "Uninstall #{GEM_NAME} #{GEM_VERSION}"
@@ -1,6 +1,4 @@
1
1
  begin
2
- gem 'rspec', '~>1.2'
3
- require 'spec'
4
2
  require 'spec/rake/spectask'
5
3
 
6
4
  task :default => [ :spec ]
@@ -8,16 +6,18 @@ begin
8
6
  desc 'Run specifications'
9
7
  Spec::Rake::SpecTask.new(:spec) do |t|
10
8
  t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
11
- t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s).map { |f| f.to_s }
9
+ t.libs << 'lib' << 'spec' # needed for CI rake spec task, duplicated in spec_helper
12
10
 
13
11
  begin
14
- gem 'rcov', '~>0.8'
12
+ require 'rcov'
15
13
  t.rcov = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
16
14
  t.rcov_opts << '--exclude' << 'spec'
17
15
  t.rcov_opts << '--text-summary'
18
16
  t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
19
17
  rescue LoadError
20
18
  # rcov not installed
19
+ rescue SyntaxError
20
+ # rcov syntax invalid
21
21
  end
22
22
  end
23
23
  rescue LoadError
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-rest-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.11
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Burton @ Joyent Inc
@@ -9,19 +9,10 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-29 00:00:00 -07:00
12
+ date: 2009-09-16 00:00:00 -07:00
13
13
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: dm-core
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - "="
22
- - !ruby/object:Gem::Version
23
- version: 0.9.11
24
- version:
14
+ dependencies: []
15
+
25
16
  description: REST Adapter for DataMapper
26
17
  email:
27
18
  - scott.burton [a] joyent [d] com
@@ -30,39 +21,38 @@ executables: []
30
21
  extensions: []
31
22
 
32
23
  extra_rdoc_files:
33
- - README.txt
24
+ - README.rdoc
34
25
  - LICENSE
35
26
  - TODO
36
- - History.txt
27
+ - History.rdoc
37
28
  files:
38
- - History.txt
29
+ - History.rdoc
39
30
  - LICENSE
40
31
  - Manifest.txt
41
- - README.markdown
42
- - README.txt
32
+ - README.rdoc
43
33
  - Rakefile
44
34
  - TODO
45
- - config/database.rb.example
46
- - dm-rest-adapter.gemspec
47
35
  - lib/rest_adapter.rb
48
36
  - lib/rest_adapter/adapter.rb
49
37
  - lib/rest_adapter/connection.rb
50
38
  - lib/rest_adapter/exceptions.rb
51
39
  - lib/rest_adapter/formats.rb
52
40
  - lib/rest_adapter/version.rb
53
- - spec/connection_spec.rb
54
- - spec/crud_spec.rb
55
- - spec/ruby_forker.rb
41
+ - spec/fixtures/book.rb
42
+ - spec/semipublic/connection_spec.rb
43
+ - spec/semipublic/rest_adapter_spec.rb
56
44
  - spec/spec.opts
57
45
  - spec/spec_helper.rb
58
46
  - tasks/install.rb
59
47
  - tasks/spec.rb
60
48
  has_rdoc: true
61
49
  homepage: http://github.com/datamapper/dm-more/tree/master/adapters/dm-rest-adapter
50
+ licenses: []
51
+
62
52
  post_install_message:
63
53
  rdoc_options:
64
54
  - --main
65
- - README.txt
55
+ - README.rdoc
66
56
  require_paths:
67
57
  - lib
68
58
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -80,9 +70,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
70
  requirements: []
81
71
 
82
72
  rubyforge_project: datamapper
83
- rubygems_version: 1.3.1
73
+ rubygems_version: 1.3.5
84
74
  signing_key:
85
- specification_version: 2
75
+ specification_version: 3
86
76
  summary: REST Adapter for DataMapper
87
77
  test_files: []
88
78