dm-core 0.9.11 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (194) hide show
  1. data/.autotest +17 -14
  2. data/.gitignore +3 -1
  3. data/FAQ +6 -5
  4. data/History.txt +5 -50
  5. data/Manifest.txt +66 -76
  6. data/QUICKLINKS +1 -1
  7. data/README.txt +21 -15
  8. data/Rakefile +6 -7
  9. data/SPECS +2 -29
  10. data/TODO +1 -1
  11. data/deps.rip +2 -0
  12. data/dm-core.gemspec +11 -15
  13. data/lib/dm-core.rb +105 -110
  14. data/lib/dm-core/adapters.rb +135 -16
  15. data/lib/dm-core/adapters/abstract_adapter.rb +251 -181
  16. data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
  17. data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
  18. data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
  19. data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
  20. data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
  21. data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
  22. data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
  23. data/lib/dm-core/associations/many_to_many.rb +372 -90
  24. data/lib/dm-core/associations/many_to_one.rb +220 -73
  25. data/lib/dm-core/associations/one_to_many.rb +319 -255
  26. data/lib/dm-core/associations/one_to_one.rb +66 -53
  27. data/lib/dm-core/associations/relationship.rb +561 -156
  28. data/lib/dm-core/collection.rb +1101 -379
  29. data/lib/dm-core/core_ext/kernel.rb +12 -0
  30. data/lib/dm-core/core_ext/symbol.rb +10 -0
  31. data/lib/dm-core/identity_map.rb +4 -34
  32. data/lib/dm-core/migrations.rb +1283 -0
  33. data/lib/dm-core/model.rb +570 -369
  34. data/lib/dm-core/model/descendant_set.rb +81 -0
  35. data/lib/dm-core/model/hook.rb +45 -0
  36. data/lib/dm-core/model/is.rb +32 -0
  37. data/lib/dm-core/model/property.rb +247 -0
  38. data/lib/dm-core/model/relationship.rb +335 -0
  39. data/lib/dm-core/model/scope.rb +90 -0
  40. data/lib/dm-core/property.rb +808 -273
  41. data/lib/dm-core/property_set.rb +141 -98
  42. data/lib/dm-core/query.rb +1037 -483
  43. data/lib/dm-core/query/conditions/comparison.rb +872 -0
  44. data/lib/dm-core/query/conditions/operation.rb +221 -0
  45. data/lib/dm-core/query/direction.rb +43 -0
  46. data/lib/dm-core/query/operator.rb +84 -0
  47. data/lib/dm-core/query/path.rb +138 -0
  48. data/lib/dm-core/query/sort.rb +45 -0
  49. data/lib/dm-core/repository.rb +210 -94
  50. data/lib/dm-core/resource.rb +641 -421
  51. data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
  52. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
  53. data/lib/dm-core/support/chainable.rb +22 -0
  54. data/lib/dm-core/support/deprecate.rb +12 -0
  55. data/lib/dm-core/support/logger.rb +13 -0
  56. data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
  57. data/lib/dm-core/transaction.rb +333 -92
  58. data/lib/dm-core/type.rb +98 -60
  59. data/lib/dm-core/types/boolean.rb +1 -1
  60. data/lib/dm-core/types/discriminator.rb +34 -20
  61. data/lib/dm-core/types/object.rb +7 -4
  62. data/lib/dm-core/types/paranoid_boolean.rb +11 -9
  63. data/lib/dm-core/types/paranoid_datetime.rb +11 -9
  64. data/lib/dm-core/types/serial.rb +3 -3
  65. data/lib/dm-core/types/text.rb +3 -4
  66. data/lib/dm-core/version.rb +1 -1
  67. data/script/performance.rb +102 -109
  68. data/script/profile.rb +169 -38
  69. data/spec/lib/adapter_helpers.rb +105 -0
  70. data/spec/lib/collection_helpers.rb +18 -0
  71. data/spec/lib/counter_adapter.rb +34 -0
  72. data/spec/lib/pending_helpers.rb +27 -0
  73. data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
  74. data/spec/public/associations/many_to_many_spec.rb +193 -0
  75. data/spec/public/associations/many_to_one_spec.rb +73 -0
  76. data/spec/public/associations/one_to_many_spec.rb +77 -0
  77. data/spec/public/associations/one_to_one_spec.rb +156 -0
  78. data/spec/public/collection_spec.rb +65 -0
  79. data/spec/public/migrations_spec.rb +359 -0
  80. data/spec/public/model/relationship_spec.rb +924 -0
  81. data/spec/public/model_spec.rb +159 -0
  82. data/spec/public/property_spec.rb +829 -0
  83. data/spec/public/resource_spec.rb +71 -0
  84. data/spec/public/sel_spec.rb +44 -0
  85. data/spec/public/setup_spec.rb +145 -0
  86. data/spec/public/shared/association_collection_shared_spec.rb +317 -0
  87. data/spec/public/shared/collection_shared_spec.rb +1670 -0
  88. data/spec/public/shared/finder_shared_spec.rb +1619 -0
  89. data/spec/public/shared/resource_shared_spec.rb +924 -0
  90. data/spec/public/shared/sel_shared_spec.rb +112 -0
  91. data/spec/public/transaction_spec.rb +129 -0
  92. data/spec/public/types/discriminator_spec.rb +130 -0
  93. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  94. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
  95. data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
  96. data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
  97. data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
  98. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
  99. data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
  100. data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
  101. data/spec/semipublic/associations/relationship_spec.rb +194 -0
  102. data/spec/semipublic/associations_spec.rb +177 -0
  103. data/spec/semipublic/collection_spec.rb +142 -0
  104. data/spec/semipublic/property_spec.rb +61 -0
  105. data/spec/semipublic/query/conditions_spec.rb +528 -0
  106. data/spec/semipublic/query/path_spec.rb +443 -0
  107. data/spec/semipublic/query_spec.rb +2626 -0
  108. data/spec/semipublic/resource_spec.rb +47 -0
  109. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  110. data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
  111. data/spec/spec.opts +3 -1
  112. data/spec/spec_helper.rb +80 -57
  113. data/tasks/ci.rb +19 -31
  114. data/tasks/dm.rb +43 -48
  115. data/tasks/doc.rb +8 -11
  116. data/tasks/gemspec.rb +5 -5
  117. data/tasks/hoe.rb +15 -16
  118. data/tasks/install.rb +8 -10
  119. metadata +74 -111
  120. data/lib/dm-core/associations.rb +0 -207
  121. data/lib/dm-core/associations/relationship_chain.rb +0 -81
  122. data/lib/dm-core/auto_migrations.rb +0 -105
  123. data/lib/dm-core/dependency_queue.rb +0 -32
  124. data/lib/dm-core/hook.rb +0 -11
  125. data/lib/dm-core/is.rb +0 -16
  126. data/lib/dm-core/logger.rb +0 -232
  127. data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
  128. data/lib/dm-core/migrator.rb +0 -29
  129. data/lib/dm-core/scope.rb +0 -58
  130. data/lib/dm-core/support.rb +0 -7
  131. data/lib/dm-core/support/array.rb +0 -13
  132. data/lib/dm-core/support/assertions.rb +0 -8
  133. data/lib/dm-core/support/errors.rb +0 -23
  134. data/lib/dm-core/support/kernel.rb +0 -11
  135. data/lib/dm-core/support/symbol.rb +0 -41
  136. data/lib/dm-core/type_map.rb +0 -80
  137. data/lib/dm-core/types.rb +0 -19
  138. data/script/all +0 -4
  139. data/spec/integration/association_spec.rb +0 -1382
  140. data/spec/integration/association_through_spec.rb +0 -203
  141. data/spec/integration/associations/many_to_many_spec.rb +0 -449
  142. data/spec/integration/associations/many_to_one_spec.rb +0 -163
  143. data/spec/integration/associations/one_to_many_spec.rb +0 -188
  144. data/spec/integration/auto_migrations_spec.rb +0 -413
  145. data/spec/integration/collection_spec.rb +0 -1073
  146. data/spec/integration/data_objects_adapter_spec.rb +0 -32
  147. data/spec/integration/dependency_queue_spec.rb +0 -46
  148. data/spec/integration/model_spec.rb +0 -197
  149. data/spec/integration/mysql_adapter_spec.rb +0 -85
  150. data/spec/integration/postgres_adapter_spec.rb +0 -731
  151. data/spec/integration/property_spec.rb +0 -253
  152. data/spec/integration/query_spec.rb +0 -514
  153. data/spec/integration/repository_spec.rb +0 -61
  154. data/spec/integration/resource_spec.rb +0 -513
  155. data/spec/integration/sqlite3_adapter_spec.rb +0 -352
  156. data/spec/integration/sti_spec.rb +0 -273
  157. data/spec/integration/strategic_eager_loading_spec.rb +0 -156
  158. data/spec/integration/transaction_spec.rb +0 -75
  159. data/spec/integration/type_spec.rb +0 -275
  160. data/spec/lib/logging_helper.rb +0 -18
  161. data/spec/lib/mock_adapter.rb +0 -27
  162. data/spec/lib/model_loader.rb +0 -100
  163. data/spec/lib/publicize_methods.rb +0 -28
  164. data/spec/models/content.rb +0 -16
  165. data/spec/models/vehicles.rb +0 -34
  166. data/spec/models/zoo.rb +0 -48
  167. data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
  168. data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
  169. data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
  170. data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
  171. data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
  172. data/spec/unit/associations/many_to_many_spec.rb +0 -32
  173. data/spec/unit/associations/many_to_one_spec.rb +0 -159
  174. data/spec/unit/associations/one_to_many_spec.rb +0 -393
  175. data/spec/unit/associations/one_to_one_spec.rb +0 -7
  176. data/spec/unit/associations/relationship_spec.rb +0 -71
  177. data/spec/unit/associations_spec.rb +0 -242
  178. data/spec/unit/auto_migrations_spec.rb +0 -111
  179. data/spec/unit/collection_spec.rb +0 -182
  180. data/spec/unit/data_mapper_spec.rb +0 -35
  181. data/spec/unit/identity_map_spec.rb +0 -126
  182. data/spec/unit/is_spec.rb +0 -80
  183. data/spec/unit/migrator_spec.rb +0 -33
  184. data/spec/unit/model_spec.rb +0 -321
  185. data/spec/unit/naming_conventions_spec.rb +0 -36
  186. data/spec/unit/property_set_spec.rb +0 -90
  187. data/spec/unit/property_spec.rb +0 -753
  188. data/spec/unit/query_spec.rb +0 -571
  189. data/spec/unit/repository_spec.rb +0 -93
  190. data/spec/unit/resource_spec.rb +0 -649
  191. data/spec/unit/scope_spec.rb +0 -142
  192. data/spec/unit/transaction_spec.rb +0 -493
  193. data/spec/unit/type_map_spec.rb +0 -114
  194. data/spec/unit/type_spec.rb +0 -119
@@ -1,352 +0,0 @@
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.map { |m| m.to_s }.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
@@ -1,273 +0,0 @@
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 :content, Text
18
- property :class_type, Discriminator
19
- end
20
-
21
- class ::Propaganda < Book
22
- property :marxist, Boolean, :nullable => false, :default => false
23
- end
24
-
25
- class ::Fiction < Book
26
- property :series, String
27
- end
28
-
29
- class ::ShortStory < Fiction
30
- property :moral, String
31
- end
32
-
33
- class ::ScienceFiction < Fiction
34
- property :aliens, Boolean
35
- end
36
-
37
- class ::SpaceWestern < ScienceFiction
38
- property :cowboys, Boolean
39
- end
40
- end
41
-
42
- describe "with the identity map" do
43
- before :all do
44
- Book.auto_migrate!(:sqlite3)
45
- repository(:sqlite3) do
46
- Propaganda.create(:title => "Something", :isbn => "129038")
47
- end
48
- end
49
-
50
- it "should find the base model in the identity map" do
51
- repository(:sqlite3) do
52
- book = Book.first
53
- book.object_id.should == Propaganda.first.object_id
54
- end
55
- end
56
-
57
- it "should find the child model in the identity map" do
58
- repository(:sqlite3) do
59
- book = Propaganda.first
60
- book.object_id.should == Book.first.object_id
61
- end
62
- end
63
- end
64
-
65
- describe "with a parent class" do
66
- before :all do
67
- Book.auto_migrate!(:sqlite3).should be_true
68
-
69
- @table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
70
- default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
71
- nil
72
- else
73
- /^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
74
- end
75
-
76
- property = @property_class.new(
77
- column.name,
78
- column.type.upcase,
79
- column.notnull == 0,
80
- default,
81
- column.pk == 1 # in SQLite3 the serial key is also primary
82
- )
83
-
84
- ts.update(property.name => property)
85
- end
86
-
87
- @index_list = @adapter.query('PRAGMA index_list("books")')
88
- end
89
-
90
- it "should create the child class property columns" do
91
- @table_set.keys.should include("series", "marxist")
92
- end
93
-
94
- it "should create all property columns of the child classes in the inheritance tree" do
95
- @table_set.keys.should include("moral")
96
- end
97
- end
98
-
99
- describe "with a child class" do
100
- before :all do
101
- Propaganda.auto_migrate!(:sqlite3).should be_true
102
-
103
- @table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
104
- default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
105
- nil
106
- else
107
- /^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
108
- end
109
-
110
- property = @property_class.new(
111
- column.name,
112
- column.type.upcase,
113
- column.notnull == 0,
114
- default,
115
- column.pk == 1 # in SQLite3 the serial key is also primary
116
- )
117
-
118
- ts.update(property.name => property)
119
- end
120
-
121
- @index_list = @adapter.query('PRAGMA index_list("books")')
122
- end
123
-
124
- it "should create the parent class' property columns" do
125
- @table_set.keys.should include("id", "title", "isbn")
126
- end
127
- end
128
-
129
- describe "with a child class with it's own child class" do
130
- before :all do
131
- Fiction.auto_migrate!(:sqlite3).should be_true
132
-
133
- @table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
134
- default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
135
- nil
136
- else
137
- /^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
138
- end
139
-
140
- property = @property_class.new(
141
- column.name,
142
- column.type.upcase,
143
- column.notnull == 0,
144
- default,
145
- column.pk == 1 # in SQLite3 the serial key is also primary
146
- )
147
-
148
- ts.update(property.name => property)
149
- end
150
-
151
- @index_list = @adapter.query('PRAGMA index_list("books")')
152
- end
153
-
154
- it "should create the parent class' property columns" do
155
- @table_set.keys.should include("id", "title", "isbn")
156
- end
157
-
158
- it "should create the child class' property columns" do
159
- @table_set.keys.should include("moral")
160
- end
161
- end
162
-
163
- describe "with a nephew class" do
164
- before :all do
165
- ShortStory.auto_migrate!(:sqlite3).should be_true
166
-
167
- @table_set = @adapter.query('PRAGMA table_info("books")').inject({}) do |ts,column|
168
- default = if 'NULL' == column.dflt_value || column.dflt_value.nil?
169
- nil
170
- else
171
- /^(['"]?)(.*)\1$/.match(column.dflt_value)[2]
172
- end
173
-
174
- property = @property_class.new(
175
- column.name,
176
- column.type.upcase,
177
- column.notnull == 0,
178
- default,
179
- column.pk == 1 # in SQLite3 the serial key is also primary
180
- )
181
-
182
- ts.update(property.name => property)
183
- end
184
- @index_list = @adapter.query('PRAGMA index_list("books")')
185
- end
186
-
187
-
188
- it "should create the grandparent class' property columns" do
189
- @table_set.keys.should include("id", "title", "isbn")
190
- end
191
-
192
- it "should create the uncle class' property columns" do
193
- @table_set.keys.should include("marxist")
194
- end
195
- end
196
-
197
- describe "with a great-grandchild class" do
198
- it "should inherit its parent's properties" do
199
- SpaceWestern.properties[:aliens].should_not be_nil
200
- end
201
- it "should inherit its grandparent's properties" do
202
- SpaceWestern.properties[:series].should_not be_nil
203
- end
204
- it "should inherit its great-granparent's properties" do
205
- SpaceWestern.properties[:title].should_not be_nil
206
- end
207
- end
208
-
209
- describe "with a child class" do
210
- before :all do
211
- Book.auto_migrate!(:sqlite3)
212
- repository(:sqlite3) do
213
- ShortStory.create(
214
- :title => "The Science of Happiness",
215
- :isbn => "129038",
216
- :moral => "Bullshit might get you to the top, but it won't keep you there.")
217
- end
218
- end
219
-
220
- it "should be able to access the properties from the parent collection" do
221
- repository(:sqlite3) do
222
- Book.all.each do |book|
223
- book.title.should_not be_nil
224
- book.isbn.should_not be_nil
225
- book.moral.should_not be_nil
226
- end
227
- end
228
- end
229
- end
230
-
231
- describe "with lazy property" do
232
- before :all do
233
- Book.auto_migrate!(:sqlite3)
234
- repository(:sqlite3) do
235
- ShortStory.create(
236
- :title => "The Science of Happiness",
237
- :isbn => "129038",
238
- :content => 'This doesn\'t feel like a normal academic conference. True, the three-day Positive Psychology Summit i',
239
- :moral => "Bullshit might get you to the top, but it won't keep you there."
240
- )
241
-
242
- ShortStory.create(
243
- :title => "Blank as white paper",
244
- :isbn => "129039",
245
- :content => '',
246
- :moral => "none."
247
- )
248
- end
249
- end
250
-
251
- it "should be able to access the properties from the parent collection" do
252
- repository(:sqlite3) do
253
- books = Book.all
254
-
255
- books.each do |book|
256
- book.title.should_not be_nil
257
- book.isbn.should_not be_nil
258
- book.moral.should_not be_nil
259
- end
260
-
261
- books[0].content
262
-
263
- books.each do |book|
264
- book.title.should_not be_nil
265
- book.isbn.should_not be_nil
266
- book.moral.should_not be_nil
267
- end
268
-
269
- end
270
- end
271
- end
272
- end
273
- end