public this repo is viewable by everyone
Fork of sam/dm-core
Description: DataMapper - Core
Homepage: http://datamapper.org
Clone URL: git://github.com/myabc/dm-core.git
Merge branch 'master' of git://github.com/sam/dm-core
myabc (author)
5 days ago
commit  a7e8027aa54899bf10d831e5c01d5b95b073f3b1
tree    e22044534e83e153585aff074f3d3a2f53ef6992
parent  9dd0d0ac41badd864171b2e593b21ebd1b14ee50 parent  1341c65bb84838d49530fcaf9e002469cbcccba8
...
110
111
112
 
 
 
 
 
 
 
 
113
114
115
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
0
@@ -110,6 +110,14 @@ module DataMapper
0
           tm.map(DM::Text).to('TEXT')
0
         end
0
       end
0
+
0
+ def initialize(name, uri_or_options)
0
+ super
0
+
0
+ # Default the driver-specifc logger to DataMapper's logger
0
+ driver_module = DataObjects.const_get(@uri.scheme.capitalize) rescue nil
0
+ driver_module.logger = DataMapper.logger if driver_module && driver_module.respond_to?(:logger)
0
+ end
0
 
0
       def transaction_primitive
0
         DataObjects::Transaction.create_for_uri(@uri)
...
10
11
12
13
14
 
 
 
15
16
17
...
22
23
24
25
 
 
26
27
 
 
 
 
 
 
 
28
29
30
...
10
11
12
 
 
13
14
15
16
17
18
...
23
24
25
 
26
27
28
 
29
30
31
32
33
34
35
36
37
38
0
@@ -10,8 +10,9 @@ module DataMapper
0
     
0
     module ClassMethods
0
       def auto_migrate!(repository_name = default_repository_name)
0
- repository(repository_name).adapter.destroy_model_storage(repository, self)
0
- repository(repository_name).adapter.create_model_storage(repository, self)
0
+ self.relationships(repository_name).each_pair { |name, relationship| relationship.child_key }
0
+ repository(repository_name).adapter.destroy_model_storage(repository(repository_name), self)
0
+ repository(repository_name).adapter.create_model_storage(repository(repository_name), self)
0
       end
0
     end
0
   end
0
@@ -22,9 +23,16 @@ module DataMapper
0
       @@models ||= []
0
     end
0
     
0
- def self.auto_migrate(repository)
0
+ def self.auto_migrate(repository_name)
0
+ # First ensure that association keys are forced to load.
0
       models.each do |model|
0
- model.auto_migrate!
0
+ model.relationships(repository_name).each_pair do |name, relationship|
0
+ relationship.child_key
0
+ end
0
+ end
0
+
0
+ models.each do |model|
0
+ model.auto_migrate!(repository_name)
0
       end
0
     end
0
   end
...
255
256
257
258
259
260
 
261
262
263
...
285
286
287
288
 
 
 
 
 
 
289
290
291
...
255
256
257
 
 
 
258
259
260
261
...
283
284
285
 
286
287
288
289
290
291
292
293
294
0
@@ -255,9 +255,7 @@ module DataMapper
0
 
0
     attr_reader :primitive, :model, :name, :instance_variable_name,
0
       :type, :reader_visibility, :writer_visibility, :getter, :options,
0
- :default, :length, :precision, :scale
0
-
0
- alias size length
0
+ :default, :precision, :scale
0
 
0
     # Supplies the field in the data-store which the property corresponds to
0
     #
0
@@ -285,7 +283,12 @@ module DataMapper
0
         return false
0
       end
0
     end
0
-
0
+
0
+ def length
0
+ @length.is_a?(Range) ? @length.max : @length
0
+ end
0
+ alias size length
0
+
0
     # Returns whether or not the property is to be lazy-loaded
0
     #
0
     # ==== Returns
...
3
4
5
6
 
 
 
 
 
 
 
 
 
7
8
9
...
3
4
5
 
6
7
8
9
10
11
12
13
14
15
16
17
0
@@ -3,7 +3,15 @@ require 'set'
0
 module DataMapper
0
 
0
   module Resource
0
-
0
+
0
+ def self.new(default_name, &b)
0
+ x = Class.new
0
+ x.send(:include, self)
0
+ x.instance_variable_set(:@storage_names, Hash.new { |h,k| h[k] = repository(k).adapter.resource_naming_convention.call(default_name) })
0
+ x.instance_eval(&b)
0
+ x
0
+ end
0
+
0
     @@including_classes = Set.new
0
 
0
     # +----------------------
...
76
77
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
80
81
...
89
90
91
 
92
93
94
...
138
139
140
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
142
143
...
206
207
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
210
211
...
223
224
225
 
226
227
228
...
250
251
252
 
 
 
 
253
254
255
...
282
283
284
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
286
287
...
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
103
104
105
106
107
108
109
...
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
...
281
282
283
284
285
286
287
...
309
310
311
312
313
314
315
316
317
318
...
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
0
@@ -76,6 +76,20 @@ begin
0
     end
0
   end
0
 
0
+ class Node
0
+ include DataMapper::Resource
0
+
0
+ property :id, Fixnum, :serial => true
0
+ property :parent_id, Fixnum
0
+
0
+ property :name, String
0
+
0
+ repository(:sqlite3) do
0
+ one_to_many :children, :class_name => "Node", :child_key => [ :parent_id ]
0
+ many_to_one :parent, :class_name => "Node", :child_key => [ :parent_id ]
0
+ end
0
+ end
0
+
0
   describe DataMapper::Associations do
0
     describe "many to one associations" do
0
       before do
0
@@ -89,6 +103,7 @@ begin
0
         Yard.auto_migrate!(:sqlite3)
0
 
0
         @adapter.execute('INSERT INTO "yards" ("id", "name", "engine_id") values (?, ?, ?)', 1, 'yard1', 1)
0
+ @adapter.execute('INSERT INTO "yards" ("id", "name", "engine_id") values (?, ?, NULL)', 0, 'yard2')
0
       end
0
 
0
       it "should load without the parent"
0
@@ -138,6 +153,33 @@ begin
0
         repository(:sqlite3).all(Engine, :id => 10).first.should_not be_nil
0
       end
0
 
0
+ it 'should convert NULL parent ids into nils' do
0
+ y = repository(:sqlite3).all(Yard, :id => 0).first
0
+ y.engine.should be_nil
0
+ end
0
+
0
+ it 'should save nil parents as NULL ids' do
0
+ pending <<-EOS.margin
0
+ Broken. I'm guessing Resource#attributes= doesn't make any concessions for associations
0
+ (probably not what we want to do anyways), and more importantly, that many_to_one accessor=
0
+ methods don't properly handle nils.
0
+ EOS
0
+
0
+ y1,y2 = nil, nil
0
+
0
+ repository(:sqlite3) do |r|
0
+ y1 = Yard.new(:id => 20, :name => "Yard20")
0
+ r.save(y1)
0
+
0
+ y2 = Yard.create!(:id => 30, :name => "Yard30", :engine => nil)
0
+ end
0
+
0
+ y1.id.should == 20
0
+ y1.engine_id.should be_nil
0
+ y2.id.should == 30
0
+ y2.engine_id.should be_nil
0
+ end
0
+
0
       after do
0
         @adapter.execute('DROP TABLE "yards"')
0
         @adapter.execute('DROP TABLE "engines"')
0
@@ -206,6 +248,22 @@ begin
0
         repository(:sqlite3).first(Pie, :id => 10).should_not be_nil
0
       end
0
 
0
+ it 'should save nil parents as NULL ids' do
0
+ p1,p2 = nil, nil
0
+
0
+ repository(:sqlite3) do |r|
0
+ p1 = Pie.new(:id => 20, :name => "Pie20")
0
+ r.save(p1)
0
+
0
+ p2 = Pie.create!(:id => 30, :name => "Pie30", :sky => nil)
0
+ end
0
+
0
+ p1.id.should == 20
0
+ p1.sky_id.should be_nil
0
+ p2.id.should == 30
0
+ p2.sky_id.should be_nil
0
+ end
0
+
0
       after do
0
         @adapter.execute('DROP TABLE "pies"')
0
         @adapter.execute('DROP TABLE "skies"')
0
@@ -223,6 +281,7 @@ begin
0
 
0
         Slice.auto_migrate!(:sqlite3)
0
 
0
+ @adapter.execute('INSERT INTO "slices" ("id", "name", "host_id") values (?, ?, NULL)', 0, 'slice0')
0
         @adapter.execute('INSERT INTO "slices" ("id", "name", "host_id") values (?, ?, ?)', 1, 'slice1', 1)
0
         @adapter.execute('INSERT INTO "slices" ("id", "name", "host_id") values (?, ?, ?)', 2, 'slice2', 1)
0
       end
0
@@ -250,6 +309,10 @@ begin
0
         h.slices.size.should == 2
0
         h.slices.first.id.should == 1
0
         h.slices.last.id.should == 2
0
+
0
+ s0 = repository(:sqlite3).all(Slice, :id => 0).first
0
+ s0.host.should be_nil
0
+ s0.host_id.should be_nil
0
       end
0
 
0
       it "should add and save the associated instance" do
0
@@ -282,6 +345,64 @@ begin
0
         s.host.id.should == 10
0
       end
0
 
0
+ describe "many-to-one and one-to-many associations combined" do
0
+ before do
0
+ @adapter = repository(:sqlite3).adapter
0
+
0
+ Node.auto_migrate!(:sqlite3)
0
+
0
+ @adapter.execute('INSERT INTO "nodes" ("id", "name", "parent_id") values (?, ?, NULL)', 1, 'r1')
0
+ @adapter.execute('INSERT INTO "nodes" ("id", "name", "parent_id") values (?, ?, NULL)', 2, 'r2')
0
+ @adapter.execute('INSERT INTO "nodes" ("id", "name", "parent_id") values (?, ?, ?)', 3, 'r1c1', 1)
0
+ @adapter.execute('INSERT INTO "nodes" ("id", "name", "parent_id") values (?, ?, ?)', 4, 'r1c2', 1)
0
+ @adapter.execute('INSERT INTO "nodes" ("id", "name", "parent_id") values (?, ?, ?)', 5, 'r1c3', 1)
0
+ @adapter.execute('INSERT INTO "nodes" ("id", "name", "parent_id") values (?, ?, ?)', 6, 'r1c1c1', 3)
0
+ end
0
+
0
+ it "should properly set #parent" do
0
+ repository :sqlite3 do
0
+ r1 = Node.get 1
0
+ r1.parent.should be_nil
0
+
0
+ n3 = Node.get 3
0
+ n3.parent.should == r1
0
+
0
+ n6 = Node.get 6
0
+ n6.parent.should == n3
0
+ end
0
+ end
0
+
0
+ it "should properly set #children" do
0
+ repository :sqlite3 do
0
+ r1 = Node.get(1)
0
+ off = r1.children
0
+ off.size.should == 3
0
+ off.include?(Node.get(3)).should be_true
0
+ off.include?(Node.get(4)).should be_true
0
+ off.include?(Node.get(5)).should be_true
0
+ end
0
+ end
0
+
0
+ it "should allow to create root nodes" do
0
+ repository :sqlite3 do
0
+ r = Node.create!(:name => "newroot")
0
+ r.parent.should be_nil
0
+ r.children.size.should == 0
0
+ end
0
+ end
0
+
0
+ it "should properly delete nodes" do
0
+ repository :sqlite3 do
0
+ r1 = Node.get 1
0
+
0
+ r1.children.size.should == 3
0
+ r1.children.delete(Node.get(4))
0
+ Node.get(4).parent.should be_nil
0
+ r1.children.size.should == 2
0
+ end
0
+ end
0
+ end
0
+
0
       describe '#through' do
0
         before(:all) do
0
           module Sweets
...
24
25
26
 
27
28
29
...
125
126
127
 
128
129
130
...
211
212
213
214
 
215
216
 
217
218
219
220
221
 
222
223
224
...
347
348
349
350
 
351
352
 
353
354
355
...
24
25
26
27
28
29
30
...
126
127
128
129
130
131
132
...
213
214
215
 
216
217
 
218
219
220
221
222
223
224
225
226
227
...
350
351
352
 
353
354
 
355
356
357
358
0
@@ -24,6 +24,7 @@ class Book
0
 end
0
 
0
 begin
0
+ gem 'do_sqlite3', '=0.9.0'
0
   require 'do_sqlite3'
0
 
0
   DataMapper.setup(:sqlite3, "sqlite3://#{INTEGRATION_DB_PATH}")
0
@@ -125,6 +126,7 @@ rescue LoadError => e
0
 end
0
 
0
 begin
0
+ gem 'do_mysql', '=0.9.0'
0
   require 'do_mysql'
0
 
0
   DataMapper.setup(:mysql, 'mysql://localhost/dm_integration_test')
0
@@ -211,14 +213,15 @@ begin
0
     end
0
   end
0
 rescue LoadError => e
0
- describe 'do_sqlite3' do
0
+ describe 'do_mysql' do
0
     it 'should be required' do
0
- fail "SQLite3 integration specs not run! Could not load do_sqlite3: #{e}"
0
+ fail "MySQL integration specs not run! Could not load do_mysql: #{e}"
0
     end
0
   end
0
 end
0
 
0
 begin
0
+ gem 'do_postgres', '=0.9.0'
0
   require 'do_postgres'
0
 
0
   DataMapper.setup(:postgres, 'postgres://postgres@localhost/dm_core_test')
0
@@ -347,9 +350,9 @@ begin
0
     end
0
   end
0
 rescue LoadError => e
0
- describe 'do_sqlite3' do
0
+ describe 'do_postgres' do
0
     it 'should be required' do
0
- fail "SQLite3 integration specs not run! Could not load do_sqlite3: #{e}"
0
+ fail "PostgreSQL integration specs not run! Could not load do_postgres: #{e}"
0
     end
0
   end
0
 end
...
15
16
17
18
 
19
20
21
22
 
23
24
25
...
47
48
49
50
 
51
52
53
...
95
96
97
98
 
99
100
101
...
418
419
420
421
 
422
423
424
...
465
466
467
468
 
469
470
471
...
486
487
488
489
 
490
491
492
...
503
504
505
506
 
507
508
509
...
15
16
17
 
18
19
20
21
 
22
23
24
25
...
47
48
49
 
50
51
52
53
...
95
96
97
 
98
99
100
101
...
418
419
420
 
421
422
423
424
...
465
466
467
 
468
469
470
471
...
486
487
488
 
489
490
491
492
...
503
504
505
 
506
507
508
509
0
@@ -15,11 +15,11 @@ begin
0
       before :all do
0
         class Sputnik
0
           include DataMapper::Resource
0
-
0
+
0
           property :id, Fixnum, :serial => true
0
           property :name, DM::Text
0
         end
0
-
0
+
0
         Sputnik.auto_migrate!(:postgres)
0
       end
0
 
0
@@ -47,7 +47,7 @@ begin
0
       before do
0
         class User
0
           include DataMapper::Resource
0
-
0
+
0
           property :id, Fixnum, :serial => true
0
           property :name, DM::Text
0
         end
0
@@ -95,7 +95,7 @@ begin
0
           property :id, Fixnum, :serial => true
0
           property :name, String
0
         end
0
-
0
+
0
         VideoGame.auto_migrate!(:postgres)
0
       end
0
 
0
@@ -418,7 +418,7 @@ begin
0
             many_to_one :engine
0
           end
0
         end
0
-
0
+
0
 
0
         Yard.auto_migrate!(:postgres)
0
 
0
@@ -465,7 +465,7 @@ begin
0
           e = Engine.new(:id => 10, :name => "engine10")
0
           y = Yard.new(:id => 10, :name => "Yard10", :engine => e)
0
           r.save(y)
0
-
0
+
0
           y.engine_id.should == 10
0
         end
0
 
0
@@ -486,7 +486,7 @@ begin
0
             one_to_many :slices
0
           end
0
         end
0
-
0
+
0
         Host.auto_migrate!(:postgres)
0
 
0
         @adapter.execute('INSERT INTO "hosts" ("id", "name") values (?, ?)', 1, 'host1')
0
@@ -503,7 +503,7 @@ begin
0
             many_to_one :host
0
           end
0
         end
0
-
0
+
0
         Slice.auto_migrate!(:postgres)
0
 
0
         @adapter.execute('INSERT INTO "slices" ("id", "name", "host_id") values (?, ?, ?)', 1, 'slice1', 1)
...
30
31
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
34
35
...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
0
@@ -30,6 +30,32 @@ begin
0
       orange.color.should == 'orange'
0
     end
0
     
0
+ describe "anonymity" do
0
+
0
+ before(:all) do
0
+ @planet = DataMapper::Resource.new("planet") do
0
+ property :name, String, :key => true
0
+ property :distance, Fixnum
0
+ end
0
+
0
+ @planet.auto_migrate!(:sqlite3)
0
+ end
0
+
0
+ it "should be able to persist" do
0
+ repository(:sqlite3) do
0
+ pluto = @planet.new
0
+ pluto.name = 'Pluto'
0
+ pluto.distance = 1_000_000
0
+ pluto.save
0
+
0
+ clone = @planet['Pluto']
0
+ clone.name.should == 'Pluto'
0
+ clone.distance.should == 1_000_000
0
+ end
0
+ end
0
+
0
+ end
0
+
0
     describe "inheritance" do
0
       before(:all) do
0
         class Male
...
13
14
15
 
 
 
 
 
 
 
 
 
 
 
 
...
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
0
@@ -13,3 +13,15 @@ module DataMapper
0
     end
0
   end
0
 end
0
+
0
+module DataObjects
0
+ module Mock
0
+
0
+ def self.logger
0
+ end
0
+
0
+ def self.logger=(value)
0
+ end
0
+
0
+ end
0
+end
...
12
13
14
15
16
17
18
19
...
22
23
24
 
 
25
26
27
...
12
13
14
 
 
15
16
17
...
20
21
22
23
24
25
26
27
0
@@ -12,8 +12,6 @@ gem 'rspec', '>=1.1.3'
0
 INTEGRATION_DB_PATH = DataMapper.root / 'spec' / 'integration' / 'integration_test.db'
0
 FileUtils.touch INTEGRATION_DB_PATH unless INTEGRATION_DB_PATH.exist?
0
 
0
-DataMapper.setup(:default, 'mock://localhost')
0
-
0
 # Determine log path.
0
 ENV['_'] =~ /(\w+)/
0
 log_path = DataMapper.root / 'log' / "#{$1 == 'opt' ? 'spec' : $1}.log"
0
@@ -22,6 +20,8 @@ log_path.dirname.mkpath
0
 DataMapper::Logger.new(log_path, 0)
0
 at_exit { DataMapper.logger.close }
0
 
0
+DataMapper.setup(:default, 'mock://localhost')
0
+
0
 class Article
0
   include DataMapper::Resource
0
 
...
82
83
84
 
85
86
87
...
82
83
84
85
86
87
88
0
@@ -82,6 +82,7 @@ describe DataMapper::AutoMigrations do
0
       models.each do |model|
0
         DataMapper::AutoMigrator.models << model
0
         model.should_receive(:auto_migrate!)
0
+ model.should_receive(:relationships).and_return({})
0
       end
0
       
0
       DataMapper::AutoMigrator.auto_migrate(@repository)
...
164
165
166
 
 
 
 
 
 
 
167
168
169
...
164
165
166
167
168
169
170
171
172
173
174
175
176
0
@@ -164,6 +164,13 @@ describe DataMapper::Property do
0
   it 'should provide typecast' do
0
     DataMapper::Property.new(Zoo, :name, String).should respond_to(:typecast)
0
   end
0
+
0
+ it "should provide a size/length" do
0
+ DataMapper::Property.new(Zoo, :cleanliness, String, { :size => 100 }).size.should == 100
0
+ DataMapper::Property.new(Zoo, :cleanliness, String, { :length => 200 }).size.should == 200
0
+ DataMapper::Property.new(Zoo, :cleanliness, String, { :size => (0..100) }).size.should == 100
0
+ DataMapper::Property.new(Zoo, :cleanliness, String, { :length => (0..200) }).size.should == 200
0
+ end
0
 
0
   it 'should pass through the value if it is the same type when typecasting' do
0
     value = 'San Diego'
...
292
293
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
296
297
...
346
347
348
 
349
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
...
365
366
367
368
369
0
@@ -292,6 +292,25 @@ describe "DataMapper::Resource" do
0
       Planet.should respond_to(:exists?)
0
       Planet.exists?.should == true
0
     end
0
+
0
+ end
0
+
0
+ describe "anonymity" do
0
+
0
+ before(:all) do
0
+ DataMapper.setup(:andromeda, 'mock://localhost')
0
+ end
0
+
0
+ it "should require a default storage name and accept a block" do
0
+ pluto = DataMapper::Resource.new("planet") do
0
+ property :name, String, :key => true
0
+ end
0
+
0
+ pluto.storage_name(:default).should == 'planets'
0
+ pluto.storage_name(:andromeda).should == 'planets'
0
+ pluto.properties[:name].should_not be_nil
0
+ end
0
+
0
   end
0
 
0
   describe 'when retrieving by key' do
0
@@ -346,4 +365,5 @@ describe "DataMapper::Resource" do
0
       NewsPaper.properties.should have(2).entries
0
     end
0
   end
0
+
0
 end

Comments

    No one has commented yet.