dm-do-adapter 1.0.0.rc1

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.
@@ -0,0 +1,370 @@
1
+ share_examples_for 'A DataObjects Adapter' do
2
+ before :all do
3
+ raise '+@adapter+ should be defined in before block' unless instance_variable_get('@adapter')
4
+
5
+ @log = StringIO.new
6
+
7
+ @original_logger = DataMapper.logger
8
+ DataMapper.logger = DataMapper::Logger.new(@log, :debug)
9
+
10
+ # set up the adapter after switching the logger so queries can be captured
11
+ @adapter = DataMapper.setup(@adapter.name, @adapter.options)
12
+
13
+ @jruby = !!(RUBY_PLATFORM =~ /java/)
14
+
15
+ @postgres = defined?(DataMapper::Adapters::PostgresAdapter) && @adapter.kind_of?(DataMapper::Adapters::PostgresAdapter)
16
+ @mysql = defined?(DataMapper::Adapters::MysqlAdapter) && @adapter.kind_of?(DataMapper::Adapters::MysqlAdapter)
17
+ @sql_server = defined?(DataMapper::Adapters::SqlserverAdapter) && @adapter.kind_of?(DataMapper::Adapters::SqlserverAdapter)
18
+ @oracle = defined?(DataMapper::Adapters::OracleAdapter) && @adapter.kind_of?(DataMapper::Adapters::OracleAdapter)
19
+ end
20
+
21
+ after :all do
22
+ DataMapper.logger = @original_logger
23
+ end
24
+
25
+ def reset_log
26
+ @log.truncate(0)
27
+ @log.rewind
28
+ end
29
+
30
+ def log_output
31
+ @log.rewind
32
+ @log.read.chomp.gsub(/^\s+~ \(\d+\.?\d*\)\s+/, '').split("\n")
33
+ end
34
+
35
+ def supports_default_values?
36
+ @adapter.send(:supports_default_values?)
37
+ end
38
+
39
+ def supports_returning?
40
+ @adapter.send(:supports_returning?)
41
+ end
42
+
43
+ describe '#create' do
44
+ describe 'serial properties' do
45
+ before :all do
46
+ class ::Article
47
+ include DataMapper::Resource
48
+
49
+ property :id, Serial
50
+
51
+ auto_migrate!
52
+ end
53
+
54
+ reset_log
55
+
56
+ Article.create
57
+ end
58
+
59
+ it 'should not send NULL values' do
60
+ statement = if @mysql
61
+ /\AINSERT INTO `articles` \(\) VALUES \(\)\z/
62
+ elsif @oracle
63
+ /\AINSERT INTO "ARTICLES" \("ID"\) VALUES \(DEFAULT\) RETURNING "ID"/
64
+ elsif supports_default_values? && supports_returning?
65
+ /\AINSERT INTO "articles" DEFAULT VALUES RETURNING \"id\"\z/
66
+ elsif supports_default_values?
67
+ /\AINSERT INTO "articles" DEFAULT VALUES\z/
68
+ else
69
+ /\AINSERT INTO "articles" \(\) VALUES \(\)\z/
70
+ end
71
+
72
+ log_output.first.should =~ statement
73
+ end
74
+ end
75
+
76
+ describe 'properties without a default' do
77
+ before :all do
78
+ class ::Article
79
+ include DataMapper::Resource
80
+
81
+ property :id, Serial
82
+ property :title, String
83
+
84
+ auto_migrate!
85
+ end
86
+
87
+ reset_log
88
+
89
+ Article.create(:id => 1)
90
+ end
91
+
92
+ it 'should not send NULL values' do
93
+ regexp = if @mysql
94
+ /^INSERT INTO `articles` \(`id`\) VALUES \(.{1,2}\)$/i
95
+ elsif @sql_server
96
+ /^SET IDENTITY_INSERT \"articles\" ON INSERT INTO "articles" \("id"\) VALUES \(.{1,2}\) SET IDENTITY_INSERT \"articles\" OFF $/i
97
+ else
98
+ /^INSERT INTO "articles" \("id"\) VALUES \(.{1,2}\)$/i
99
+ end
100
+
101
+ log_output.first.should =~ regexp
102
+ end
103
+ end
104
+ end
105
+
106
+ describe '#select' do
107
+ before :all do
108
+ class ::Article
109
+ include DataMapper::Resource
110
+
111
+ property :name, String, :key => true
112
+ property :author, String, :required => true
113
+
114
+ auto_migrate!
115
+ end
116
+
117
+ @article_model = Article
118
+
119
+ @article_model.create(:name => 'Learning DataMapper', :author => 'Dan Kubb')
120
+ end
121
+
122
+ describe 'when one field specified in SELECT statement' do
123
+ before :all do
124
+ @return = @adapter.select('SELECT name FROM articles')
125
+ end
126
+
127
+ it 'should return an Array' do
128
+ @return.should be_kind_of(Array)
129
+ end
130
+
131
+ it 'should have a single result' do
132
+ @return.size.should == 1
133
+ end
134
+
135
+ it 'should return an Array of values' do
136
+ @return.should == [ 'Learning DataMapper' ]
137
+ end
138
+ end
139
+
140
+ describe 'when more than one field specified in SELECT statement' do
141
+ before :all do
142
+ @return = @adapter.select('SELECT name, author FROM articles')
143
+ end
144
+
145
+ it 'should return an Array' do
146
+ @return.should be_kind_of(Array)
147
+ end
148
+
149
+ it 'should have a single result' do
150
+ @return.size.should == 1
151
+ end
152
+
153
+ it 'should return an Array of Struct objects' do
154
+ @return.first.should be_kind_of(Struct)
155
+ end
156
+
157
+ it 'should return expected values' do
158
+ @return.first.values.should == [ 'Learning DataMapper', 'Dan Kubb' ]
159
+ end
160
+ end
161
+ end
162
+
163
+ describe '#execute' do
164
+ before :all do
165
+ class ::Article
166
+ include DataMapper::Resource
167
+
168
+ property :name, String, :key => true
169
+ property :author, String, :required => true
170
+
171
+ auto_migrate!
172
+ end
173
+
174
+ @article_model = Article
175
+ end
176
+
177
+ before :all do
178
+ @result = @adapter.execute('INSERT INTO articles (name, author) VALUES(?, ?)', 'Learning DataMapper', 'Dan Kubb')
179
+ end
180
+
181
+ it 'should return a DataObjects::Result' do
182
+ @result.should be_kind_of(DataObjects::Result)
183
+ end
184
+
185
+ it 'should affect 1 row' do
186
+ @result.affected_rows.should == 1
187
+ end
188
+
189
+ it 'should not have an insert_id' do
190
+ pending_if 'Inconsistent insert_id results', !(@postgres || @mysql || @oracle) do
191
+ @result.insert_id.should be_nil
192
+ end
193
+ end
194
+ end
195
+
196
+ describe '#read' do
197
+ before :all do
198
+ class ::Article
199
+ include DataMapper::Resource
200
+
201
+ property :name, String, :key => true
202
+ property :description, String, :required => false
203
+
204
+ belongs_to :parent, self, :required => false
205
+ has n, :children, self, :inverse => :parent
206
+
207
+ auto_migrate!
208
+ end
209
+
210
+ @article_model = Article
211
+ end
212
+
213
+ describe 'with a raw query' do
214
+ before :all do
215
+ @article_model.create(:name => 'Test', :description => 'Description').should be_saved
216
+ @article_model.create(:name => 'NoDescription').should be_saved
217
+
218
+ @query = DataMapper::Query.new(@repository, @article_model, :conditions => [ 'description IS NOT NULL' ])
219
+
220
+ @return = @adapter.read(@query)
221
+ end
222
+
223
+ it 'should return an Array of Hashes' do
224
+ @return.should be_kind_of(Array)
225
+ @return.all? { |entry| entry.should be_kind_of(Hash) }
226
+ end
227
+
228
+ it 'should return expected values' do
229
+ @return.should == [ { @article_model.properties[:name] => 'Test',
230
+ @article_model.properties[:description] => 'Description',
231
+ @article_model.properties[:parent_name] => nil } ]
232
+ end
233
+ end
234
+
235
+ describe 'with a raw query with a bind value mismatch' do
236
+ before :all do
237
+ @article_model.create(:name => 'Test').should be_saved
238
+
239
+ @query = DataMapper::Query.new(@repository, @article_model, :conditions => [ 'name IS NOT NULL', nil ])
240
+ end
241
+
242
+ it 'should raise an error' do
243
+ lambda {
244
+ @adapter.read(@query)
245
+ }.should raise_error(ArgumentError, 'Binding mismatch: 1 for 0')
246
+ end
247
+ end
248
+
249
+ describe 'with a Collection bind value' do
250
+ describe 'with an inclusion comparison' do
251
+ before :all do
252
+ 5.times do |index|
253
+ @article_model.create(:name => "Test #{index}", :parent => @article_model.last).should be_saved
254
+ end
255
+
256
+ @parents = @article_model.all
257
+ @query = DataMapper::Query.new(@repository, @article_model, :parent => @parents)
258
+
259
+ @expected = @article_model.all[1, 4].map { |article| article.attributes(:property) }
260
+ end
261
+
262
+ describe 'that is not loaded' do
263
+ before :all do
264
+ reset_log
265
+ @return = @adapter.read(@query)
266
+ end
267
+
268
+ it 'should return an Array of Hashes' do
269
+ @return.should be_kind_of(Array)
270
+ @return.all? { |entry| entry.should be_kind_of(Hash) }
271
+ end
272
+
273
+ it 'should return expected values' do
274
+ @return.should == @expected
275
+ end
276
+
277
+ it 'should execute one subquery' do
278
+ pending_if @mysql do
279
+ log_output.size.should == 1
280
+ end
281
+ end
282
+ end
283
+
284
+ describe 'that is loaded' do
285
+ before :all do
286
+ @parents.to_a # lazy load the collection
287
+ end
288
+
289
+ before :all do
290
+ reset_log
291
+ @return = @adapter.read(@query)
292
+ end
293
+
294
+ it 'should return an Array of Hashes' do
295
+ @return.should be_kind_of(Array)
296
+ @return.all? { |entry| entry.should be_kind_of(Hash) }
297
+ end
298
+
299
+ it 'should return expected values' do
300
+ @return.should == @expected
301
+ end
302
+
303
+ it 'should execute one query' do
304
+ log_output.size.should == 1
305
+ end
306
+ end
307
+ end
308
+
309
+ describe 'with an negated inclusion comparison' do
310
+ before :all do
311
+ 5.times do |index|
312
+ @article_model.create(:name => "Test #{index}", :parent => @article_model.last).should be_saved
313
+ end
314
+
315
+ @parents = @article_model.all
316
+ @query = DataMapper::Query.new(@repository, @article_model, :parent.not => @parents)
317
+
318
+ @expected = []
319
+ end
320
+
321
+ describe 'that is not loaded' do
322
+ before :all do
323
+ reset_log
324
+ @return = @adapter.read(@query)
325
+ end
326
+
327
+ it 'should return an Array of Hashes' do
328
+ @return.should be_kind_of(Array)
329
+ @return.all? { |entry| entry.should be_kind_of(Hash) }
330
+ end
331
+
332
+ it 'should return expected values' do
333
+ @return.should == @expected
334
+ end
335
+
336
+ it 'should execute one subquery' do
337
+ pending_if @mysql do
338
+ log_output.size.should == 1
339
+ end
340
+ end
341
+ end
342
+
343
+ describe 'that is loaded' do
344
+ before :all do
345
+ @parents.to_a # lazy load the collection
346
+ end
347
+
348
+ before :all do
349
+ reset_log
350
+ @return = @adapter.read(@query)
351
+ end
352
+
353
+ it 'should return an Array of Hashes' do
354
+ @return.should be_kind_of(Array)
355
+ @return.all? { |entry| entry.should be_kind_of(Hash) }
356
+ end
357
+
358
+ it 'should return expected values' do
359
+ @return.should == @expected
360
+ end
361
+
362
+ it 'should execute one query' do
363
+ log_output.size.should == 1
364
+ end
365
+ end
366
+ end
367
+
368
+ end
369
+ end
370
+ end
@@ -0,0 +1 @@
1
+ require 'dm-do-adapter/adapter'
@@ -0,0 +1,18 @@
1
+ desc "Support bundling from local source code (allows BUNDLE_GEMFILE=Gemfile.local bundle foo)"
2
+ task :local_gemfile do |t|
3
+
4
+ root = Pathname(__FILE__).dirname.parent
5
+ datamapper = root.parent
6
+
7
+ source_regex = /DATAMAPPER = 'git:\/\/github.com\/datamapper'/
8
+ gem_source_regex = /:git => \"#\{DATAMAPPER\}\/(.+?)(?:\.git)?\"/
9
+
10
+ root.join('Gemfile.local').open('w') do |f|
11
+ root.join('Gemfile').open.each do |line|
12
+ line.sub!(source_regex, "DATAMAPPER = '#{datamapper}'")
13
+ line.sub!(gem_source_regex, ':path => "#{DATAMAPPER}/\1"')
14
+ f.puts line
15
+ end
16
+ end
17
+
18
+ end
data/tasks/yard.rake ADDED
@@ -0,0 +1,9 @@
1
+ begin
2
+ require 'yard'
3
+
4
+ YARD::Rake::YardocTask.new
5
+ rescue LoadError
6
+ task :yard do
7
+ abort 'YARD is not available. In order to run yard, you must: gem install yard'
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'pathname'
3
+ require 'yardstick/rake/measurement'
4
+ require 'yardstick/rake/verify'
5
+
6
+ # yardstick_measure task
7
+ Yardstick::Rake::Measurement.new
8
+
9
+ # verify_measurements task
10
+ Yardstick::Rake::Verify.new do |verify|
11
+ verify.threshold = 100
12
+ end
13
+ rescue LoadError
14
+ %w[ yardstick_measure verify_measurements ].each do |name|
15
+ task name.to_s do
16
+ abort "Yardstick is not available. In order to run #{name}, you must: gem install yardstick"
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dm-do-adapter
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: true
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ - rc1
10
+ version: 1.0.0.rc1
11
+ platform: ruby
12
+ authors:
13
+ - Dan Kubb
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-19 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: data_objects
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 10
31
+ - 1
32
+ version: 0.10.1
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: dm-core
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 0
45
+ - 0
46
+ - rc1
47
+ version: 1.0.0.rc1
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ~>
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 1
59
+ - 3
60
+ version: "1.3"
61
+ type: :development
62
+ version_requirements: *id003
63
+ description: DataObjects Adapter for DataMapper
64
+ email: dan.kubb@gmail.com
65
+ executables: []
66
+
67
+ extensions: []
68
+
69
+ extra_rdoc_files:
70
+ - LICENSE
71
+ - README.rdoc
72
+ files:
73
+ - .gitignore
74
+ - Gemfile
75
+ - LICENSE
76
+ - README.rdoc
77
+ - Rakefile
78
+ - VERSION
79
+ - dm-do-adapter.gemspec
80
+ - lib/dm-do-adapter.rb
81
+ - lib/dm-do-adapter/adapter.rb
82
+ - lib/dm-do-adapter/spec/shared_spec.rb
83
+ - tasks/local_gemfile.rake
84
+ - tasks/yard.rake
85
+ - tasks/yardstick.rake
86
+ has_rdoc: true
87
+ homepage: http://github.com/datamapper/dm-do-adapter
88
+ licenses: []
89
+
90
+ post_install_message:
91
+ rdoc_options:
92
+ - --charset=UTF-8
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">"
105
+ - !ruby/object:Gem::Version
106
+ segments:
107
+ - 1
108
+ - 3
109
+ - 1
110
+ version: 1.3.1
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.3.6
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: DataObjects Adapter for DataMapper
118
+ test_files: []
119
+