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.
data/README.txt DELETED
@@ -1,47 +0,0 @@
1
- = dm-rest-adapter
2
-
3
- A DataMapper adapter for REST Web Services
4
-
5
- == Usage
6
-
7
- DM Rest Adapter requires the use of a model which is the same name as the resource you are using. For example, if you have a resource named "posts" you will create a standard datamapper object called post.rb in app/models. The only difference in this model is you will need to define the rest adapter for the model. The following is an example of a post model, where the host settings point to the app you are running the resource on. In addition I have included a basic auth login which will be used if your resource requires auth:
8
-
9
- DataMapper.setup(:default, {
10
- :adapter => 'rest',
11
- :format => 'xml',
12
- :host => 'localhost',
13
- :port => 4000,
14
- :login => 'user',
15
- :password => 'verys3crit'
16
- })
17
-
18
- class Post
19
-
20
- include DataMapper::Resource
21
-
22
- property :id, Serial
23
- property :title, String
24
- property :body, Text
25
-
26
- end
27
-
28
-
29
- If you notice this looks exactly like a normal datmapper model. Every property you define will map itself with the xml returned or posted from/to the resource.
30
-
31
- == Code
32
-
33
- Now for some code examples. DM Rest Adapter uses the same methods as datamapper including during creation.
34
-
35
- Post.first => returns the object from the resouce
36
- Post.get(1) => returns the object from the resource
37
- p = Post.new(:title => "My awesome blog post", :body => "I really have nothing to say...")
38
- p.save => saves the resource on the remote
39
-
40
- == Caveat
41
-
42
- Posts do not honor RESTful HTTP status codes. I might fix this...
43
-
44
- == TODO:
45
-
46
- Nested resources
47
- Put verb actions
@@ -1,8 +0,0 @@
1
- DataMapper.setup(:default, {
2
- :adapter => 'rest',
3
- :format => 'xml',
4
- :host => 'localhost',
5
- :port => '4000',
6
- :username => 'admin',
7
- :password => 'secret'
8
- })
@@ -1,34 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
- Gem::Specification.new do |s|
4
- s.name = %q{dm-rest-adapter}
5
- s.version = "0.9.11"
6
-
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Scott Burton @ Joyent Inc"]
9
- s.date = %q{2009-03-23}
10
- s.description = %q{REST Adapter for DataMapper}
11
- s.email = ["scott.burton [a] joyent [d] com"]
12
- s.extra_rdoc_files = ["README.txt", "LICENSE", "TODO", "History.txt"]
13
- s.files = ["History.txt", "LICENSE", "Manifest.txt", "README.markdown", "README.txt", "Rakefile", "TODO", "config/database.rb.example", "dm-rest-adapter.gemspec", "lib/rest_adapter.rb", "lib/rest_adapter/adapter.rb", "lib/rest_adapter/connection.rb", "lib/rest_adapter/exceptions.rb", "lib/rest_adapter/formats.rb", "lib/rest_adapter/version.rb", "spec/connection_spec.rb", "spec/crud_spec.rb", "spec/ruby_forker.rb", "spec/spec.opts", "spec/spec_helper.rb", "tasks/install.rb", "tasks/spec.rb"]
14
- s.has_rdoc = true
15
- s.homepage = %q{http://github.com/datamapper/dm-more/tree/master/adapters/dm-rest-adapter}
16
- s.rdoc_options = ["--main", "README.txt"]
17
- s.require_paths = ["lib"]
18
- s.rubyforge_project = %q{datamapper}
19
- s.rubygems_version = %q{1.3.1}
20
- s.summary = %q{REST Adapter for DataMapper}
21
-
22
- if s.respond_to? :specification_version then
23
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
- s.specification_version = 2
25
-
26
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
- s.add_runtime_dependency(%q<dm-core>, ["= 0.9.11"])
28
- else
29
- s.add_dependency(%q<dm-core>, ["= 0.9.11"])
30
- end
31
- else
32
- s.add_dependency(%q<dm-core>, ["= 0.9.11"])
33
- end
34
- end
@@ -1,250 +0,0 @@
1
- $LOAD_PATH << File.dirname(__FILE__)
2
- require 'spec_helper'
3
-
4
- describe 'A REST adapter' do
5
-
6
- before do
7
- @book = Book.new(:title => 'Hello, World!', :author => 'Anonymous')
8
- @adapter = DataMapper::Repository.adapters[:default]
9
- end
10
-
11
- describe 'when saving a new resource' do
12
-
13
- before(:each) do
14
- @mock_resp = mock("response")
15
-
16
- @book.id = 1
17
- @mock_resp.should_receive(:body).and_return @book.to_xml
18
- end
19
-
20
- it "should create a book" do
21
- @mock_http = mock("http")
22
- Net::HTTP.should_receive(:start).and_yield @mock_http
23
-
24
- @mock_resp.should_receive(:code).and_return 200
25
-
26
- @mock_http.should_receive(:request).and_return @mock_resp
27
-
28
- @book.save.should eql(true)
29
- end
30
-
31
- it 'should make an HTTP POST' do
32
- @adapter.connection.should_receive(:http_post).with('books', @book.to_xml).and_return @mock_resp
33
- @book.save
34
- end
35
-
36
- it 'should call run_verb with POST' do
37
- @adapter.connection.should_receive(:run_verb).with('post', @book.to_xml).and_return @mock_resp
38
- @book.save
39
- end
40
-
41
- end
42
-
43
- describe 'when returning incorrect xml from a save' do
44
- before(:all) do
45
- @mock_resp = mock("response")
46
- end
47
-
48
- it "should raise error on missing root element in xml" do
49
- @mock_resp.should_receive(:body).and_return ""
50
- @adapter.connection.should_receive(:run_verb).with('post', @book.to_xml).and_return @mock_resp
51
-
52
- lambda {@book.save}.should raise_error(RuntimeError, "No root element matching book in xml")
53
- end
54
-
55
- it "should not raise an error if the root xml is empty" do
56
- @mock_resp.should_receive(:body).and_return "<book></book>"
57
- @adapter.connection.should_receive(:run_verb).with('post', @book.to_xml).and_return @mock_resp
58
-
59
- lambda {@book.save}.should_not raise_error(RuntimeError)
60
- end
61
- end
62
-
63
- describe 'when deleting an existing resource' do
64
- before do
65
- @book.stub!(:new_record?).and_return(false)
66
- end
67
-
68
- it 'should do an HTTP DELETE' do
69
- @adapter.connection.should_receive(:http_delete)
70
- @book.destroy
71
- end
72
-
73
- it "should raise NotImplementedError if is not a single resource query" do
74
- @adapter.should_receive(:is_single_resource_query?).and_return(false)
75
- lambda {@book.destroy}.should raise_error(NotImplementedError)
76
- end
77
-
78
- it 'should call run_verb with DELETE and no data' do
79
- @adapter.connection.should_receive(:run_verb).with('delete', nil)
80
- @book.destroy
81
- end
82
-
83
- it "should return false if the record does not exist in the repository" do
84
- @book.should_receive(:new_record?).and_return(true)
85
- @book.destroy.should eql(false)
86
- end
87
- end
88
-
89
- describe 'when getting one resource' do
90
-
91
- describe 'if the resource exists' do
92
-
93
- before do
94
- book_xml = <<-BOOK
95
- <?xml version='1.0' encoding='UTF-8'?>
96
- <book>
97
- <author>Stephen King</author>
98
- <created-at type='datetime'>2008-06-08T17:03:07Z</created-at>
99
- <id type='integer'>1</id>
100
- <title>The Shining</title>
101
- <updated-at type='datetime'>2008-06-08T17:03:07Z</updated-at>
102
- </book>
103
- BOOK
104
- @id = 1
105
- @response = mock(Net::HTTPResponse)
106
- @response.stub!(:body).and_return(book_xml)
107
- @adapter.connection.stub!(:http_get).and_return(@response)
108
- end
109
-
110
- it 'should return the resource' do
111
- book = Book.get(@id)
112
- book.should_not be_nil
113
- book.id.should be_an_instance_of(Fixnum)
114
- book.id.should == 1
115
- end
116
-
117
- it "should have its attributes well formed" do
118
- book = Book.get(@id)
119
- book.author.should == 'Stephen King'
120
- book.title.should == 'The Shining'
121
- end
122
-
123
- it 'should do an HTTP GET' do
124
- @adapter.connection.should_receive(:http_get).with('books/1').and_return(@response)
125
- Book.get(@id)
126
- end
127
-
128
- it "should be equal to itself" do
129
- Book.get(@id).should == Book.get(@id)
130
- end
131
-
132
- it "should return its cached version when it was already fetched" do
133
- book = mock(Book, :kind_of? => Book)
134
- repo = mock(DataMapper::Repository)
135
- ident_map = mock(DataMapper::IdentityMap)
136
-
137
- Book.should_receive(:repository).and_return(repo)
138
- repo.should_receive(:identity_map).and_return(ident_map)
139
- ident_map.stub!(:get).with([@id]).and_return(book)
140
-
141
- # The remote resource won't be called when a cached object exists
142
- Book.should_receive(:first).never
143
- Book.get(@id).should be_a_kind_of(Book)
144
- end
145
-
146
- it "should call read_one method" do
147
- @adapter.should_receive(:read_one)
148
- Book.get(@id)
149
- end
150
- end
151
-
152
- describe 'if the resource does not exist' do
153
- it 'should raise DataMapperRest::ResourceNotFound' do
154
- @mock_resp = mock("response")
155
- @mock_http = mock("http")
156
- Net::HTTP.should_receive(:start).and_yield @mock_http
157
-
158
- @mock_resp.should_receive(:code).and_return 404
159
- @mock_http.should_receive(:request).and_return @mock_resp
160
-
161
- lambda{ Book.get(5000) }.should raise_error(DataMapperRest::ResourceNotFound)
162
- end
163
- end
164
- end
165
-
166
- describe 'when getting all resource of a particular type' do
167
- before do
168
- books_xml = <<-BOOK
169
- <?xml version='1.0' encoding='UTF-8'?>
170
- <books type='array'>
171
- <book>
172
- <author>Ursula K LeGuin</author>
173
- <created-at type='datetime'>2008-06-08T17:02:28Z</created-at>
174
- <id type='integer'>1</id>
175
- <title>The Dispossed</title>
176
- <updated-at type='datetime'>2008-06-08T17:02:28Z</updated-at>
177
- </book>
178
- <book>
179
- <author>Stephen King</author>
180
- <created-at type='datetime'>2008-06-08T17:03:07Z</created-at>
181
- <id type='integer'>2</id>
182
- <title>The Shining</title>
183
- <updated-at type='datetime'>2008-06-08T17:03:07Z</updated-at>
184
- </book>
185
- </books>
186
- BOOK
187
- @response = mock(Net::HTTPResponse)
188
- @response.stub!(:body).and_return(books_xml)
189
- end
190
-
191
- it 'should get a non-empty list' do
192
- @adapter.connection.stub!(:http_get).and_return(@response)
193
- Book.all.should_not be_empty
194
- end
195
-
196
- it 'should receive one Resource for each entity in the XML' do
197
- @adapter.connection.stub!(:http_get).and_return(@response)
198
- Book.all.size.should == 2
199
- end
200
-
201
- it "should call read_many method" do
202
- @adapter.connection.stub!(:http_get).and_return(@response)
203
- @adapter.should_receive(:read_many)
204
- Book.all
205
- end
206
-
207
- it "should raise NotImplementedError if conditions are specified" do
208
- # Have to find a way to set an expectation for a method call inside a block
209
- # Book.all(:title => "NonExistentTitle")
210
- end
211
- end
212
-
213
- describe 'when updating an existing resource' do
214
- before do
215
- @books_xml = <<-XML
216
- <book>
217
- <id type='integer'>42</id>
218
- <title>Starship Troopers</title>
219
- <author>Robert Heinlein</author>
220
- <created-at type='datetime'>2008-06-08T17:02:28Z</created-at>
221
- </book>
222
- XML
223
- repository do |repo|
224
- @repository = repo
225
- @book = Book.new(:id => 42,
226
- :title => 'Starship Troopers',
227
- :author => 'Robert Heinlein',
228
- :created_at => DateTime.parse('2008-06-08T17:02:28Z'))
229
- @book.instance_eval { @new_record = false }
230
- @repository.identity_map(Book)[@book.key] = @book
231
- @book.title = "Mary Had a Little Lamb"
232
- end
233
- end
234
-
235
- it 'should do an HTTP PUT' do
236
- @adapter.connection.should_receive(:http_put).with('books/42', @book.to_xml)
237
- @repository.scope do
238
- @book.save
239
- end
240
- end
241
-
242
- it "should not do an HTTP PUT for non-dirty resources" do
243
- @book.should_receive(:dirty_attributes).and_return({})
244
- @adapter.connection.should_receive(:http_put).never
245
- @repository.scope do
246
- @book.save
247
- end
248
- end
249
- end
250
- end
@@ -1,13 +0,0 @@
1
- require 'rbconfig'
2
-
3
- module RubyForker
4
- # Forks a ruby interpreter with same type as ourself.
5
- # juby will fork jruby, ruby will fork ruby etc.
6
- def ruby(args, stderr=nil)
7
- config = ::Config::CONFIG
8
- interpreter = File::join(config['bindir'], config['ruby_install_name']) + config['EXEEXT']
9
- cmd = "#{interpreter} #{args}"
10
- cmd << " 2> #{stderr}" unless stderr.nil?
11
- `#{cmd}`
12
- end
13
- end