sam-dm-core 0.9.6
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/.autotest +26 -0
- data/CONTRIBUTING +51 -0
- data/FAQ +92 -0
- data/History.txt +145 -0
- data/MIT-LICENSE +22 -0
- data/Manifest.txt +125 -0
- data/QUICKLINKS +12 -0
- data/README.txt +143 -0
- data/Rakefile +30 -0
- data/SPECS +63 -0
- data/TODO +1 -0
- data/lib/dm-core.rb +224 -0
- data/lib/dm-core/adapters.rb +4 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +202 -0
- data/lib/dm-core/adapters/data_objects_adapter.rb +707 -0
- data/lib/dm-core/adapters/mysql_adapter.rb +136 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +188 -0
- data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
- data/lib/dm-core/associations.rb +199 -0
- data/lib/dm-core/associations/many_to_many.rb +147 -0
- data/lib/dm-core/associations/many_to_one.rb +107 -0
- data/lib/dm-core/associations/one_to_many.rb +309 -0
- data/lib/dm-core/associations/one_to_one.rb +61 -0
- data/lib/dm-core/associations/relationship.rb +218 -0
- data/lib/dm-core/associations/relationship_chain.rb +81 -0
- data/lib/dm-core/auto_migrations.rb +113 -0
- data/lib/dm-core/collection.rb +638 -0
- data/lib/dm-core/dependency_queue.rb +31 -0
- data/lib/dm-core/hook.rb +11 -0
- data/lib/dm-core/identity_map.rb +45 -0
- data/lib/dm-core/is.rb +16 -0
- data/lib/dm-core/logger.rb +232 -0
- data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
- data/lib/dm-core/migrator.rb +29 -0
- data/lib/dm-core/model.rb +471 -0
- data/lib/dm-core/naming_conventions.rb +84 -0
- data/lib/dm-core/property.rb +673 -0
- data/lib/dm-core/property_set.rb +162 -0
- data/lib/dm-core/query.rb +625 -0
- data/lib/dm-core/repository.rb +159 -0
- data/lib/dm-core/resource.rb +637 -0
- data/lib/dm-core/scope.rb +58 -0
- data/lib/dm-core/support.rb +7 -0
- data/lib/dm-core/support/array.rb +13 -0
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/errors.rb +23 -0
- data/lib/dm-core/support/kernel.rb +7 -0
- data/lib/dm-core/support/symbol.rb +41 -0
- data/lib/dm-core/transaction.rb +267 -0
- data/lib/dm-core/type.rb +160 -0
- data/lib/dm-core/type_map.rb +80 -0
- data/lib/dm-core/types.rb +19 -0
- data/lib/dm-core/types/boolean.rb +7 -0
- data/lib/dm-core/types/discriminator.rb +34 -0
- data/lib/dm-core/types/object.rb +24 -0
- data/lib/dm-core/types/paranoid_boolean.rb +34 -0
- data/lib/dm-core/types/paranoid_datetime.rb +33 -0
- data/lib/dm-core/types/serial.rb +9 -0
- data/lib/dm-core/types/text.rb +10 -0
- data/lib/dm-core/version.rb +3 -0
- data/script/all +5 -0
- data/script/performance.rb +203 -0
- data/script/profile.rb +87 -0
- data/spec/integration/association_spec.rb +1371 -0
- data/spec/integration/association_through_spec.rb +203 -0
- data/spec/integration/associations/many_to_many_spec.rb +449 -0
- data/spec/integration/associations/many_to_one_spec.rb +163 -0
- data/spec/integration/associations/one_to_many_spec.rb +151 -0
- data/spec/integration/auto_migrations_spec.rb +398 -0
- data/spec/integration/collection_spec.rb +1069 -0
- data/spec/integration/data_objects_adapter_spec.rb +32 -0
- data/spec/integration/dependency_queue_spec.rb +58 -0
- data/spec/integration/model_spec.rb +127 -0
- data/spec/integration/mysql_adapter_spec.rb +85 -0
- data/spec/integration/postgres_adapter_spec.rb +731 -0
- data/spec/integration/property_spec.rb +233 -0
- data/spec/integration/query_spec.rb +506 -0
- data/spec/integration/repository_spec.rb +57 -0
- data/spec/integration/resource_spec.rb +475 -0
- data/spec/integration/sqlite3_adapter_spec.rb +352 -0
- data/spec/integration/sti_spec.rb +208 -0
- data/spec/integration/strategic_eager_loading_spec.rb +138 -0
- data/spec/integration/transaction_spec.rb +75 -0
- data/spec/integration/type_spec.rb +271 -0
- data/spec/lib/logging_helper.rb +18 -0
- data/spec/lib/mock_adapter.rb +27 -0
- data/spec/lib/model_loader.rb +91 -0
- data/spec/lib/publicize_methods.rb +28 -0
- data/spec/models/vehicles.rb +34 -0
- data/spec/models/zoo.rb +47 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
- data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
- data/spec/unit/adapters/data_objects_adapter_spec.rb +628 -0
- data/spec/unit/adapters/postgres_adapter_spec.rb +133 -0
- data/spec/unit/associations/many_to_many_spec.rb +17 -0
- data/spec/unit/associations/many_to_one_spec.rb +152 -0
- data/spec/unit/associations/one_to_many_spec.rb +393 -0
- data/spec/unit/associations/one_to_one_spec.rb +7 -0
- data/spec/unit/associations/relationship_spec.rb +71 -0
- data/spec/unit/associations_spec.rb +242 -0
- data/spec/unit/auto_migrations_spec.rb +111 -0
- data/spec/unit/collection_spec.rb +182 -0
- data/spec/unit/data_mapper_spec.rb +35 -0
- data/spec/unit/identity_map_spec.rb +126 -0
- data/spec/unit/is_spec.rb +80 -0
- data/spec/unit/migrator_spec.rb +33 -0
- data/spec/unit/model_spec.rb +339 -0
- data/spec/unit/naming_conventions_spec.rb +36 -0
- data/spec/unit/property_set_spec.rb +83 -0
- data/spec/unit/property_spec.rb +753 -0
- data/spec/unit/query_spec.rb +530 -0
- data/spec/unit/repository_spec.rb +93 -0
- data/spec/unit/resource_spec.rb +626 -0
- data/spec/unit/scope_spec.rb +142 -0
- data/spec/unit/transaction_spec.rb +493 -0
- data/spec/unit/type_map_spec.rb +114 -0
- data/spec/unit/type_spec.rb +119 -0
- data/tasks/ci.rb +68 -0
- data/tasks/dm.rb +63 -0
- data/tasks/doc.rb +20 -0
- data/tasks/gemspec.rb +23 -0
- data/tasks/hoe.rb +46 -0
- data/tasks/install.rb +20 -0
- metadata +216 -0
@@ -0,0 +1,352 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
if HAS_SQLITE3
|
4
|
+
describe DataMapper::Adapters::Sqlite3Adapter do
|
5
|
+
before :all do
|
6
|
+
@adapter = repository(:sqlite3).adapter
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "auto migrating" do
|
10
|
+
before :all do
|
11
|
+
class Sputnik
|
12
|
+
include DataMapper::Resource
|
13
|
+
|
14
|
+
property :id, Serial
|
15
|
+
property :name, DM::Text
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it "#upgrade_model should work" do
|
20
|
+
@adapter.destroy_model_storage(repository(:sqlite3), Sputnik)
|
21
|
+
@adapter.storage_exists?("sputniks").should == false
|
22
|
+
Sputnik.auto_migrate!(:sqlite3)
|
23
|
+
@adapter.storage_exists?("sputniks").should == true
|
24
|
+
@adapter.field_exists?("sputniks", "new_prop").should == false
|
25
|
+
Sputnik.property :new_prop, Integer
|
26
|
+
Sputnik.auto_upgrade!(:sqlite3)
|
27
|
+
@adapter.field_exists?("sputniks", "new_prop").should == true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "querying metadata" do
|
32
|
+
before :all do
|
33
|
+
class Sputnik
|
34
|
+
include DataMapper::Resource
|
35
|
+
|
36
|
+
property :id, Serial
|
37
|
+
property :name, DM::Text
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
before do
|
42
|
+
Sputnik.auto_migrate!(:sqlite3)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "#storage_exists? should return true for tables that exist" do
|
46
|
+
@adapter.storage_exists?("sputniks").should == true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "#storage_exists? should return false for tables that don't exist" do
|
50
|
+
@adapter.storage_exists?("space turds").should == false
|
51
|
+
end
|
52
|
+
|
53
|
+
it "#field_exists? should return true for columns that exist" do
|
54
|
+
@adapter.field_exists?("sputniks", "name").should == true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "#storage_exists? should return false for tables that don't exist" do
|
58
|
+
@adapter.field_exists?("sputniks", "plur").should == false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "database file handling" do
|
63
|
+
it "should preserve the file path for file-based databases" do
|
64
|
+
file = 'newfile.db'
|
65
|
+
DataMapper.setup(:sqlite3file, "sqlite3:#{file}")
|
66
|
+
adapter = repository(:sqlite3file).adapter
|
67
|
+
adapter.uri.path.should == file
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should have a path of just :memory: when using memory databases" do
|
71
|
+
DataMapper.setup(:sqlite3memory, "sqlite3::memory:")
|
72
|
+
adapter = repository(:sqlite3memory).adapter
|
73
|
+
adapter.uri.path.should == ':memory:'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "handling transactions" do
|
78
|
+
before :all do
|
79
|
+
class Sputnik
|
80
|
+
include DataMapper::Resource
|
81
|
+
|
82
|
+
property :id, Serial
|
83
|
+
property :name, DM::Text
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
before do
|
88
|
+
Sputnik.auto_migrate!(:sqlite3)
|
89
|
+
|
90
|
+
@transaction = DataMapper::Transaction.new(@adapter)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should rollback changes when #rollback_transaction is called" do
|
94
|
+
@transaction.commit do |transaction|
|
95
|
+
@adapter.execute("INSERT INTO sputniks (name) VALUES ('my pretty sputnik')")
|
96
|
+
transaction.rollback
|
97
|
+
end
|
98
|
+
@adapter.query("SELECT * FROM sputniks WHERE name = 'my pretty sputnik'").empty?.should == true
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should commit changes when #commit_transaction is called" do
|
102
|
+
@transaction.commit do
|
103
|
+
@adapter.execute("INSERT INTO sputniks (name) VALUES ('my pretty sputnik')")
|
104
|
+
end
|
105
|
+
@adapter.query("SELECT * FROM sputniks WHERE name = 'my pretty sputnik'").size.should == 1
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "reading & writing a database" do
|
110
|
+
before :all do
|
111
|
+
class User
|
112
|
+
include DataMapper::Resource
|
113
|
+
|
114
|
+
property :id, Serial
|
115
|
+
property :name, DM::Text
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
before do
|
120
|
+
User.auto_migrate!(:sqlite3)
|
121
|
+
|
122
|
+
@adapter.execute("INSERT INTO users (name) VALUES ('Paul')")
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'should be able to #execute an arbitrary query' do
|
126
|
+
result = @adapter.execute("INSERT INTO users (name) VALUES ('Sam')")
|
127
|
+
|
128
|
+
result.affected_rows.should == 1
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'should be able to #query' do
|
132
|
+
result = @adapter.query("SELECT * FROM users")
|
133
|
+
|
134
|
+
result.should be_kind_of(Array)
|
135
|
+
row = result.first
|
136
|
+
row.should be_kind_of(Struct)
|
137
|
+
row.members.should == %w{id name}
|
138
|
+
|
139
|
+
row.id.should == 1
|
140
|
+
row.name.should == 'Paul'
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should return an empty array if #query found no rows' do
|
144
|
+
@adapter.execute("DELETE FROM users")
|
145
|
+
|
146
|
+
result = nil
|
147
|
+
lambda { result = @adapter.query("SELECT * FROM users") }.should_not raise_error
|
148
|
+
|
149
|
+
result.should be_kind_of(Array)
|
150
|
+
result.size.should == 0
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "CRUD for serial Key" do
|
155
|
+
before :all do
|
156
|
+
class VideoGame
|
157
|
+
include DataMapper::Resource
|
158
|
+
|
159
|
+
property :id, Serial
|
160
|
+
property :name, String
|
161
|
+
property :object, Object
|
162
|
+
property :notes, Text
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
before do
|
167
|
+
VideoGame.auto_migrate!(:sqlite3)
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should be able to create a record' do
|
171
|
+
time = Time.now
|
172
|
+
game = repository(:sqlite3) do
|
173
|
+
game = VideoGame.new(:name => 'System Shock', :object => time, :notes => "Test")
|
174
|
+
game.save
|
175
|
+
game.should_not be_a_new_record
|
176
|
+
game.should_not be_dirty
|
177
|
+
game
|
178
|
+
end
|
179
|
+
repository(:sqlite3) do
|
180
|
+
saved = VideoGame.first(:name => 'System Shock')
|
181
|
+
saved.id.should == game.id
|
182
|
+
saved.notes.should == game.notes
|
183
|
+
saved.object.should == time
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should be able to read a record' do
|
188
|
+
name = 'Wing Commander: Privateer'
|
189
|
+
id = @adapter.execute('INSERT INTO "video_games" ("name") VALUES (?)', name).insert_id
|
190
|
+
|
191
|
+
game = repository(:sqlite3) do
|
192
|
+
VideoGame.get(id)
|
193
|
+
end
|
194
|
+
|
195
|
+
game.name.should == name
|
196
|
+
game.should_not be_dirty
|
197
|
+
game.should_not be_a_new_record
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'should be able to update a record' do
|
201
|
+
name = 'Resistance: Fall of Mon'
|
202
|
+
id = @adapter.execute('INSERT INTO "video_games" ("name") VALUES (?)', name).insert_id
|
203
|
+
|
204
|
+
game = repository(:sqlite3) do
|
205
|
+
VideoGame.get(id)
|
206
|
+
end
|
207
|
+
|
208
|
+
game.name = game.name.sub(/Mon/, 'Man')
|
209
|
+
|
210
|
+
game.should_not be_a_new_record
|
211
|
+
game.should be_dirty
|
212
|
+
|
213
|
+
repository(:sqlite3) do
|
214
|
+
game.save
|
215
|
+
end
|
216
|
+
|
217
|
+
game.should_not be_dirty
|
218
|
+
|
219
|
+
clone = repository(:sqlite3) do
|
220
|
+
VideoGame.get(id)
|
221
|
+
end
|
222
|
+
|
223
|
+
clone.name.should == game.name
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'should be able to delete a record' do
|
227
|
+
name = 'Zelda'
|
228
|
+
id = @adapter.execute('INSERT INTO "video_games" ("name") VALUES (?)', name).insert_id
|
229
|
+
|
230
|
+
game = repository(:sqlite3) do
|
231
|
+
VideoGame.get(id)
|
232
|
+
end
|
233
|
+
|
234
|
+
game.name.should == name
|
235
|
+
|
236
|
+
repository(:sqlite3) do
|
237
|
+
game.destroy.should be_true
|
238
|
+
end
|
239
|
+
game.should be_a_new_record
|
240
|
+
game.should be_dirty
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'should respond to Resource#get' do
|
244
|
+
name = 'Contra'
|
245
|
+
id = @adapter.execute('INSERT INTO "video_games" ("name") VALUES (?)', name).insert_id
|
246
|
+
|
247
|
+
contra = repository(:sqlite3) { VideoGame.get(id) }
|
248
|
+
|
249
|
+
contra.should_not be_nil
|
250
|
+
contra.should_not be_dirty
|
251
|
+
contra.should_not be_a_new_record
|
252
|
+
contra.id.should == id
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
describe "CRUD for Composite Key" do
|
257
|
+
before :all do
|
258
|
+
class BankCustomer
|
259
|
+
include DataMapper::Resource
|
260
|
+
|
261
|
+
property :bank, String, :key => true
|
262
|
+
property :account_number, String, :key => true
|
263
|
+
property :name, String
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
before do
|
268
|
+
BankCustomer.auto_migrate!(:sqlite3)
|
269
|
+
end
|
270
|
+
|
271
|
+
it 'should be able to create a record' do
|
272
|
+
customer = BankCustomer.new(:bank => 'Community Bank', :account_number => '123456', :name => 'David Hasselhoff')
|
273
|
+
repository(:sqlite3) do
|
274
|
+
customer.save
|
275
|
+
end
|
276
|
+
|
277
|
+
customer.should_not be_a_new_record
|
278
|
+
customer.should_not be_dirty
|
279
|
+
|
280
|
+
row = @adapter.query('SELECT "bank", "account_number" FROM "bank_customers" WHERE "name" = ?', customer.name).first
|
281
|
+
row.bank.should == customer.bank
|
282
|
+
row.account_number.should == customer.account_number
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'should be able to read a record' do
|
286
|
+
bank, account_number, name = 'Chase', '4321', 'Super Wonderful'
|
287
|
+
@adapter.execute('INSERT INTO "bank_customers" ("bank", "account_number", "name") VALUES (?, ?, ?)', bank, account_number, name)
|
288
|
+
|
289
|
+
repository(:sqlite3) do
|
290
|
+
BankCustomer.get(bank, account_number).name.should == name
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'should be able to update a record' do
|
295
|
+
bank, account_number, name = 'Wells Fargo', '00101001', 'Spider Pig'
|
296
|
+
@adapter.execute('INSERT INTO "bank_customers" ("bank", "account_number", "name") VALUES (?, ?, ?)', bank, account_number, name)
|
297
|
+
|
298
|
+
customer = repository(:sqlite3) do
|
299
|
+
BankCustomer.get(bank, account_number)
|
300
|
+
end
|
301
|
+
|
302
|
+
customer.name = 'Bat-Pig'
|
303
|
+
|
304
|
+
customer.should_not be_a_new_record
|
305
|
+
customer.should be_dirty
|
306
|
+
|
307
|
+
repository(:sqlite3) do
|
308
|
+
customer.save
|
309
|
+
end
|
310
|
+
|
311
|
+
customer.should_not be_dirty
|
312
|
+
|
313
|
+
clone = repository(:sqlite3) do
|
314
|
+
BankCustomer.get(bank, account_number)
|
315
|
+
end
|
316
|
+
|
317
|
+
clone.name.should == customer.name
|
318
|
+
end
|
319
|
+
|
320
|
+
it 'should be able to delete a record' do
|
321
|
+
bank, account_number, name = 'Megacorp', 'ABC', 'Flash Gordon'
|
322
|
+
@adapter.execute('INSERT INTO "bank_customers" ("bank", "account_number", "name") VALUES (?, ?, ?)', bank, account_number, name)
|
323
|
+
|
324
|
+
customer = repository(:sqlite3) do
|
325
|
+
BankCustomer.get(bank, account_number)
|
326
|
+
end
|
327
|
+
|
328
|
+
customer.name.should == name
|
329
|
+
|
330
|
+
repository(:sqlite3) do
|
331
|
+
customer.destroy.should be_true
|
332
|
+
end
|
333
|
+
|
334
|
+
customer.should be_a_new_record
|
335
|
+
customer.should be_dirty
|
336
|
+
end
|
337
|
+
|
338
|
+
it 'should respond to Resource#get' do
|
339
|
+
bank, account_number, name = 'Conchords', '1100101', 'Robo Boogie'
|
340
|
+
@adapter.execute('INSERT INTO "bank_customers" ("bank", "account_number", "name") VALUES (?, ?, ?)', bank, account_number, name)
|
341
|
+
|
342
|
+
robots = repository(:sqlite3) { BankCustomer.get(bank, account_number) }
|
343
|
+
|
344
|
+
robots.should_not be_nil
|
345
|
+
robots.should_not be_dirty
|
346
|
+
robots.should_not be_a_new_record
|
347
|
+
robots.bank.should == bank
|
348
|
+
robots.account_number.should == account_number
|
349
|
+
end
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
if HAS_SQLITE3
|
5
|
+
describe DataMapper::AutoMigrations, '.auto_migrate! on STI models with sqlite3' do
|
6
|
+
before :all do
|
7
|
+
@adapter = repository(:sqlite3).adapter
|
8
|
+
|
9
|
+
@property_class = Struct.new(:name, :type, :nullable, :default, :serial)
|
10
|
+
|
11
|
+
class Book
|
12
|
+
include DataMapper::Resource
|
13
|
+
|
14
|
+
property :id, Serial
|
15
|
+
property :title, String, :nullable => false
|
16
|
+
property :isbn, Integer, :nullable => false
|
17
|
+
property :class_type, Discriminator
|
18
|
+
end
|
19
|
+
|
20
|
+
class Propaganda < Book
|
21
|
+
property :marxist, Boolean, :nullable => false, :default => false
|
22
|
+
end
|
23
|
+
|
24
|
+
class Fiction < Book
|
25
|
+
property :series, String
|
26
|
+
end
|
27
|
+
|
28
|
+
class ShortStory < Fiction
|
29
|
+
property :moral, String
|
30
|
+
end
|
31
|
+
|
32
|
+
class ScienceFiction < Fiction
|
33
|
+
property :aliens, Boolean
|
34
|
+
end
|
35
|
+
|
36
|
+
class SpaceWestern < ScienceFiction
|
37
|
+
property :cowboys, Boolean
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "with the identity map" do
|
42
|
+
before :all do
|
43
|
+
Book.auto_migrate!(:sqlite3)
|
44
|
+
repository(:sqlite3) do
|
45
|
+
Propaganda.create(:title => "Something", :isbn => "129038")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should find the base model in the identity map" do
|
50
|
+
repository(:sqlite3) do
|
51
|
+
book = Book.first
|
52
|
+
book.object_id.should == Propaganda.first.object_id
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should find the child model in the identity map" do
|
57
|
+
repository(:sqlite3) do
|
58
|
+
book = Propaganda.first
|
59
|
+
book.object_id.should == Book.first.object_id
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "with a parent class" do
|
65
|
+
before :all do
|
66
|
+
Book.auto_migrate!(:sqlite3).should be_true
|
67
|
+
|
68
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
69
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
70
|
+
nil
|
71
|
+
else
|
72
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
73
|
+
end
|
74
|
+
|
75
|
+
property = @property_class.new(
|
76
|
+
column.name,
|
77
|
+
column.type.upcase,
|
78
|
+
column.notnull == 0,
|
79
|
+
default,
|
80
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
81
|
+
)
|
82
|
+
|
83
|
+
ts.update(property.name => property)
|
84
|
+
end
|
85
|
+
|
86
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should create the child class property columns" do
|
90
|
+
@table_set.keys.should include("series", "marxist")
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should create all property columns of the child classes in the inheritance tree" do
|
94
|
+
@table_set.keys.should include("moral")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "with a child class" do
|
99
|
+
before :all do
|
100
|
+
Propaganda.auto_migrate!(:sqlite3).should be_true
|
101
|
+
|
102
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
103
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
104
|
+
nil
|
105
|
+
else
|
106
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
107
|
+
end
|
108
|
+
|
109
|
+
property = @property_class.new(
|
110
|
+
column.name,
|
111
|
+
column.type.upcase,
|
112
|
+
column.notnull == 0,
|
113
|
+
default,
|
114
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
115
|
+
)
|
116
|
+
|
117
|
+
ts.update(property.name => property)
|
118
|
+
end
|
119
|
+
|
120
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should create the parent class' property columns" do
|
124
|
+
@table_set.keys.should include("id", "title", "isbn")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "with a child class with it's own child class" do
|
129
|
+
before :all do
|
130
|
+
Fiction.auto_migrate!(:sqlite3).should be_true
|
131
|
+
|
132
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
133
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
134
|
+
nil
|
135
|
+
else
|
136
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
137
|
+
end
|
138
|
+
|
139
|
+
property = @property_class.new(
|
140
|
+
column.name,
|
141
|
+
column.type.upcase,
|
142
|
+
column.notnull == 0,
|
143
|
+
default,
|
144
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
145
|
+
)
|
146
|
+
|
147
|
+
ts.update(property.name => property)
|
148
|
+
end
|
149
|
+
|
150
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should create the parent class' property columns" do
|
154
|
+
@table_set.keys.should include("id", "title", "isbn")
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should create the child class' property columns" do
|
158
|
+
@table_set.keys.should include("moral")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "with a nephew class" do
|
163
|
+
before :all do
|
164
|
+
ShortStory.auto_migrate!(:sqlite3).should be_true
|
165
|
+
|
166
|
+
@table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
|
167
|
+
default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
|
168
|
+
nil
|
169
|
+
else
|
170
|
+
/^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
|
171
|
+
end
|
172
|
+
|
173
|
+
property = @property_class.new(
|
174
|
+
column.name,
|
175
|
+
column.type.upcase,
|
176
|
+
column.notnull == 0,
|
177
|
+
default,
|
178
|
+
column.pk == 1 # in SQLite3 the serial key is also primary
|
179
|
+
)
|
180
|
+
|
181
|
+
ts.update(property.name => property)
|
182
|
+
end
|
183
|
+
@index_list = @adapter.query('PRAGMA index_list("books")')
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
it "should create the grandparent class' property columns" do
|
188
|
+
@table_set.keys.should include("id", "title", "isbn")
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should create the uncle class' property columns" do
|
192
|
+
@table_set.keys.should include("marxist")
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "with a great-grandchild class" do
|
197
|
+
it "should inherit its parent's properties" do
|
198
|
+
SpaceWestern.properties[:aliens].should_not be_nil
|
199
|
+
end
|
200
|
+
it "should inherit its grandparent's properties" do
|
201
|
+
SpaceWestern.properties[:series].should_not be_nil
|
202
|
+
end
|
203
|
+
it "should inherit its great-granparent's properties" do
|
204
|
+
SpaceWestern.properties[:title].should_not be_nil
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|