dm-rest-adapter 0.9.11 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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