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.
Files changed (126) hide show
  1. data/.autotest +26 -0
  2. data/CONTRIBUTING +51 -0
  3. data/FAQ +92 -0
  4. data/History.txt +145 -0
  5. data/MIT-LICENSE +22 -0
  6. data/Manifest.txt +125 -0
  7. data/QUICKLINKS +12 -0
  8. data/README.txt +143 -0
  9. data/Rakefile +30 -0
  10. data/SPECS +63 -0
  11. data/TODO +1 -0
  12. data/lib/dm-core.rb +224 -0
  13. data/lib/dm-core/adapters.rb +4 -0
  14. data/lib/dm-core/adapters/abstract_adapter.rb +202 -0
  15. data/lib/dm-core/adapters/data_objects_adapter.rb +707 -0
  16. data/lib/dm-core/adapters/mysql_adapter.rb +136 -0
  17. data/lib/dm-core/adapters/postgres_adapter.rb +188 -0
  18. data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
  19. data/lib/dm-core/associations.rb +199 -0
  20. data/lib/dm-core/associations/many_to_many.rb +147 -0
  21. data/lib/dm-core/associations/many_to_one.rb +107 -0
  22. data/lib/dm-core/associations/one_to_many.rb +309 -0
  23. data/lib/dm-core/associations/one_to_one.rb +61 -0
  24. data/lib/dm-core/associations/relationship.rb +218 -0
  25. data/lib/dm-core/associations/relationship_chain.rb +81 -0
  26. data/lib/dm-core/auto_migrations.rb +113 -0
  27. data/lib/dm-core/collection.rb +638 -0
  28. data/lib/dm-core/dependency_queue.rb +31 -0
  29. data/lib/dm-core/hook.rb +11 -0
  30. data/lib/dm-core/identity_map.rb +45 -0
  31. data/lib/dm-core/is.rb +16 -0
  32. data/lib/dm-core/logger.rb +232 -0
  33. data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
  34. data/lib/dm-core/migrator.rb +29 -0
  35. data/lib/dm-core/model.rb +471 -0
  36. data/lib/dm-core/naming_conventions.rb +84 -0
  37. data/lib/dm-core/property.rb +673 -0
  38. data/lib/dm-core/property_set.rb +162 -0
  39. data/lib/dm-core/query.rb +625 -0
  40. data/lib/dm-core/repository.rb +159 -0
  41. data/lib/dm-core/resource.rb +637 -0
  42. data/lib/dm-core/scope.rb +58 -0
  43. data/lib/dm-core/support.rb +7 -0
  44. data/lib/dm-core/support/array.rb +13 -0
  45. data/lib/dm-core/support/assertions.rb +8 -0
  46. data/lib/dm-core/support/errors.rb +23 -0
  47. data/lib/dm-core/support/kernel.rb +7 -0
  48. data/lib/dm-core/support/symbol.rb +41 -0
  49. data/lib/dm-core/transaction.rb +267 -0
  50. data/lib/dm-core/type.rb +160 -0
  51. data/lib/dm-core/type_map.rb +80 -0
  52. data/lib/dm-core/types.rb +19 -0
  53. data/lib/dm-core/types/boolean.rb +7 -0
  54. data/lib/dm-core/types/discriminator.rb +34 -0
  55. data/lib/dm-core/types/object.rb +24 -0
  56. data/lib/dm-core/types/paranoid_boolean.rb +34 -0
  57. data/lib/dm-core/types/paranoid_datetime.rb +33 -0
  58. data/lib/dm-core/types/serial.rb +9 -0
  59. data/lib/dm-core/types/text.rb +10 -0
  60. data/lib/dm-core/version.rb +3 -0
  61. data/script/all +5 -0
  62. data/script/performance.rb +203 -0
  63. data/script/profile.rb +87 -0
  64. data/spec/integration/association_spec.rb +1371 -0
  65. data/spec/integration/association_through_spec.rb +203 -0
  66. data/spec/integration/associations/many_to_many_spec.rb +449 -0
  67. data/spec/integration/associations/many_to_one_spec.rb +163 -0
  68. data/spec/integration/associations/one_to_many_spec.rb +151 -0
  69. data/spec/integration/auto_migrations_spec.rb +398 -0
  70. data/spec/integration/collection_spec.rb +1069 -0
  71. data/spec/integration/data_objects_adapter_spec.rb +32 -0
  72. data/spec/integration/dependency_queue_spec.rb +58 -0
  73. data/spec/integration/model_spec.rb +127 -0
  74. data/spec/integration/mysql_adapter_spec.rb +85 -0
  75. data/spec/integration/postgres_adapter_spec.rb +731 -0
  76. data/spec/integration/property_spec.rb +233 -0
  77. data/spec/integration/query_spec.rb +506 -0
  78. data/spec/integration/repository_spec.rb +57 -0
  79. data/spec/integration/resource_spec.rb +475 -0
  80. data/spec/integration/sqlite3_adapter_spec.rb +352 -0
  81. data/spec/integration/sti_spec.rb +208 -0
  82. data/spec/integration/strategic_eager_loading_spec.rb +138 -0
  83. data/spec/integration/transaction_spec.rb +75 -0
  84. data/spec/integration/type_spec.rb +271 -0
  85. data/spec/lib/logging_helper.rb +18 -0
  86. data/spec/lib/mock_adapter.rb +27 -0
  87. data/spec/lib/model_loader.rb +91 -0
  88. data/spec/lib/publicize_methods.rb +28 -0
  89. data/spec/models/vehicles.rb +34 -0
  90. data/spec/models/zoo.rb +47 -0
  91. data/spec/spec.opts +3 -0
  92. data/spec/spec_helper.rb +86 -0
  93. data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
  94. data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
  95. data/spec/unit/adapters/data_objects_adapter_spec.rb +628 -0
  96. data/spec/unit/adapters/postgres_adapter_spec.rb +133 -0
  97. data/spec/unit/associations/many_to_many_spec.rb +17 -0
  98. data/spec/unit/associations/many_to_one_spec.rb +152 -0
  99. data/spec/unit/associations/one_to_many_spec.rb +393 -0
  100. data/spec/unit/associations/one_to_one_spec.rb +7 -0
  101. data/spec/unit/associations/relationship_spec.rb +71 -0
  102. data/spec/unit/associations_spec.rb +242 -0
  103. data/spec/unit/auto_migrations_spec.rb +111 -0
  104. data/spec/unit/collection_spec.rb +182 -0
  105. data/spec/unit/data_mapper_spec.rb +35 -0
  106. data/spec/unit/identity_map_spec.rb +126 -0
  107. data/spec/unit/is_spec.rb +80 -0
  108. data/spec/unit/migrator_spec.rb +33 -0
  109. data/spec/unit/model_spec.rb +339 -0
  110. data/spec/unit/naming_conventions_spec.rb +36 -0
  111. data/spec/unit/property_set_spec.rb +83 -0
  112. data/spec/unit/property_spec.rb +753 -0
  113. data/spec/unit/query_spec.rb +530 -0
  114. data/spec/unit/repository_spec.rb +93 -0
  115. data/spec/unit/resource_spec.rb +626 -0
  116. data/spec/unit/scope_spec.rb +142 -0
  117. data/spec/unit/transaction_spec.rb +493 -0
  118. data/spec/unit/type_map_spec.rb +114 -0
  119. data/spec/unit/type_spec.rb +119 -0
  120. data/tasks/ci.rb +68 -0
  121. data/tasks/dm.rb +63 -0
  122. data/tasks/doc.rb +20 -0
  123. data/tasks/gemspec.rb +23 -0
  124. data/tasks/hoe.rb +46 -0
  125. data/tasks/install.rb +20 -0
  126. metadata +216 -0
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ if ADAPTER
4
+ describe DataMapper::Repository, "with #{ADAPTER}" do
5
+ before :all do
6
+ class SerialFinderSpec
7
+ include DataMapper::Resource
8
+
9
+ property :id, Serial
10
+ property :sample, String
11
+
12
+ auto_migrate!(ADAPTER)
13
+ end
14
+
15
+ repository(ADAPTER).create((0...100).map { SerialFinderSpec.new(:sample => rand.to_s) })
16
+ end
17
+
18
+ before do
19
+ @repository = repository(ADAPTER)
20
+ @model = SerialFinderSpec
21
+ @query = DataMapper::Query.new(@repository, @model)
22
+ end
23
+
24
+ it "should throw an exception if the named repository is unknown" do
25
+ r = DataMapper::Repository.new(:completely_bogus)
26
+ lambda { r.adapter }.should raise_error(ArgumentError)
27
+ end
28
+
29
+ it "should return all available rows" do
30
+ @repository.read_many(@query).should have(100).entries
31
+ end
32
+
33
+ it "should allow limit and offset" do
34
+ @repository.read_many(@query.merge(:limit => 50)).should have(50).entries
35
+
36
+ collection = @repository.read_many(@query.merge(:limit => 20, :offset => 40))
37
+ collection.should have(20).entries
38
+ collection.map { |entry| entry.id }.should == @repository.read_many(@query)[40...60].map { |entry| entry.id }
39
+ end
40
+
41
+ it "should lazy-load missing attributes" do
42
+ sfs = @repository.read_one(@query.merge(:fields => [ :id ], :limit => 1))
43
+ sfs.should be_a_kind_of(@model)
44
+ sfs.should_not be_a_new_record
45
+
46
+ sfs.attribute_loaded?(:sample).should be_false
47
+ sfs.sample.should_not be_nil
48
+ end
49
+
50
+ it "should translate an Array to an IN clause" do
51
+ ids = @repository.read_many(@query.merge(:fields => [ :id ], :limit => 10)).map { |entry| entry.id }
52
+ results = @repository.read_many(@query.merge(:id => ids))
53
+
54
+ results.map { |entry| entry.id }.should == ids
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,475 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ # ------------------------------------------------------------
4
+ # ----- Read SPECS for information about how to read -----
5
+ # ----- and contribute to the DataMapper specs. -----
6
+ # ------------------------------------------------------------
7
+
8
+ if ADAPTER
9
+ describe "DataMapper::Resource with #{ADAPTER}" do
10
+
11
+ load_models_for_metaphor :zoo
12
+
13
+ before(:each) do
14
+ DataMapper.auto_migrate!(ADAPTER)
15
+ @zoo = Zoo.new(:name => "San Francisco")
16
+ repository(ADAPTER) { @zoo.save }
17
+ end
18
+
19
+ # --- Move somewhere ----
20
+ it "should be able to destroy objects" do
21
+ lambda { @zoo.destroy.should be_true }.should_not raise_error
22
+ end
23
+
24
+ describe '#attribute_get' do
25
+ it 'should provide #attribute_get' do
26
+ Zoo.new.should respond_to(:attribute_get)
27
+ end
28
+
29
+ it 'should delegate to Property#get' do
30
+ Zoo.properties[:name].should_receive(:get).with(zoo = Zoo.new)
31
+ zoo.name
32
+ end
33
+
34
+ it "should return Property#get's return value" do
35
+ Zoo.properties[:name].should_receive(:get).and_return("San Francisco")
36
+ Zoo.new.name.should == "San Francisco"
37
+ end
38
+ end
39
+
40
+ describe '#attribute_set' do
41
+ it "should provide #attribute_set" do
42
+ Zoo.new.should respond_to(:attribute_set)
43
+ end
44
+
45
+ it 'should delegate to Property#set' do
46
+ Zoo.properties[:name].should_receive(:set).with(zoo = Zoo.new, "San Francisco")
47
+ zoo.name = "San Francisco"
48
+ end
49
+ end
50
+
51
+ describe '#eql?' do
52
+ it "should return true if the objects are the same instances"
53
+ it "should return false if the other object is not an instance of the same model"
54
+ it "should return false if the other object is a different class"
55
+ it "should return true if the repositories are the same and the primary key is the same"
56
+ it "should return true if all the properties are the same"
57
+ it "should return false if any of the properties are different"
58
+ end
59
+
60
+ describe '#hash' do
61
+ it "should return the same hash values for unsaved objects that are equal" do
62
+ e1 = Employee.new(:name => "John")
63
+ e2 = Employee.new(:name => "John")
64
+ e1.hash.should == e2.hash
65
+ end
66
+
67
+ it "should return the same hash values for saved objects that are equal" do
68
+ # Make sure that the object_id's are not the same
69
+ e1 = e2 = nil
70
+ repository(ADAPTER) do
71
+ e1 = Employee.create(:name => "John")
72
+ end
73
+ repository(ADAPTER) do
74
+ e2 = Employee.get("John")
75
+ end
76
+ e1.hash.should == e2.hash
77
+ end
78
+
79
+ it "should return a different hash value for different objects of the same type" do
80
+ repository(ADAPTER) do
81
+ e1 = Employee.create(:name => "John")
82
+ e2 = Employee.create(:name => "Dan")
83
+ e1.hash.should_not == e2.hash
84
+ end
85
+ end
86
+
87
+ it "should return a different hash value for different types of objects with the same key"
88
+ end
89
+
90
+ describe '#id' do
91
+ it "should be awesome"
92
+ end
93
+
94
+ describe '#inspect' do
95
+ it "should return a string representing the object"
96
+ end
97
+
98
+ describe '#key' do
99
+ describe "original_value[:key]" do
100
+ it "should be used when an existing resource's key changes" do
101
+ repository(ADAPTER) do
102
+ employee = Employee.create(:name => "John")
103
+ employee.name = "Jon"
104
+ employee.key.should == ["John"]
105
+ end
106
+ end
107
+
108
+ it "should be used when saving an existing resource" do
109
+ repository(ADAPTER) do
110
+ employee = Employee.create(:name => "John")
111
+ employee.name = "Jon"
112
+ employee.save.should == true
113
+ Employee.get("Jon").should == employee
114
+ end
115
+ end
116
+
117
+ it "should not be used when a new resource's key changes" do
118
+ employee = Employee.new(:name => "John")
119
+ employee.name = "Jon"
120
+ employee.key.should == ["Jon"]
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#pretty_print' do
126
+ it "should display a pretty version of inspect"
127
+ end
128
+
129
+ describe '#save' do
130
+
131
+ describe 'with a new resource' do
132
+ it 'should set defaults before create'
133
+ it 'should create when dirty'
134
+ it 'should create when non-dirty, and it has a serial key'
135
+ end
136
+
137
+ describe 'with an existing resource' do
138
+ it 'should update'
139
+ end
140
+
141
+ end
142
+
143
+ describe '#repository' do
144
+ it "should return the repository associated with the object if there is one"
145
+ it "should return the repository associated with the model if the object doesn't have one"
146
+ end
147
+ end
148
+ end
149
+
150
+
151
+
152
+
153
+ # ---------- Old specs... BOOOOOOOOOO ---------------
154
+ if ADAPTER
155
+ class Orange
156
+ include DataMapper::Resource
157
+
158
+ def self.default_repository_name
159
+ ADAPTER
160
+ end
161
+
162
+ property :name, String, :key => true
163
+ property :color, String
164
+ end
165
+
166
+ class Apple
167
+ include DataMapper::Resource
168
+
169
+ def self.default_repository_name
170
+ ADAPTER
171
+ end
172
+
173
+ property :id, Serial
174
+ property :color, String, :default => 'green', :nullable => true
175
+ end
176
+
177
+ class FortunePig
178
+ include DataMapper::Resource
179
+
180
+ def self.default_repository_name
181
+ ADAPTER
182
+ end
183
+
184
+ property :id, Serial
185
+ property :name, String
186
+
187
+ def to_s
188
+ name
189
+ end
190
+
191
+ after :create do
192
+ @created_id = self.id
193
+ end
194
+
195
+ after :save do
196
+ @save_id = self.id
197
+ end
198
+ end
199
+
200
+ class Car
201
+ include DataMapper::Resource
202
+
203
+ def self.default_repository_name
204
+ ADAPTER
205
+ end
206
+
207
+ property :brand, String, :key => true
208
+ property :color, String
209
+ property :created_on, Date
210
+ property :touched_on, Date
211
+ property :updated_on, Date
212
+
213
+ before :save do
214
+ self.touched_on = Date.today
215
+ end
216
+
217
+ before :create do
218
+ self.created_on = Date.today
219
+ end
220
+
221
+ before :update do
222
+ self.updated_on = Date.today
223
+ end
224
+ end
225
+
226
+ class Male
227
+ include DataMapper::Resource
228
+
229
+ def self.default_repository_name
230
+ ADAPTER
231
+ end
232
+
233
+ property :id, Serial
234
+ property :name, String
235
+ property :iq, Integer, :default => 100
236
+ property :type, Discriminator
237
+ property :data, Object
238
+
239
+ def iq=(i)
240
+ attribute_set(:iq, i - 1)
241
+ end
242
+ end
243
+
244
+ class Bully < Male; end
245
+
246
+ class Mugger < Bully; end
247
+
248
+ class Maniac < Bully; end
249
+
250
+ class Psycho < Maniac; end
251
+
252
+ class Geek < Male
253
+ property :awkward, Boolean, :default => true
254
+
255
+ def iq=(i)
256
+ attribute_set(:iq, i + 30)
257
+ end
258
+ end
259
+
260
+ class Flanimal
261
+ include DataMapper::Resource
262
+
263
+ def self.default_repository_name
264
+ ADAPTER
265
+ end
266
+
267
+ property :id, Serial
268
+ property :type, Discriminator
269
+ property :name, String
270
+ end
271
+
272
+ class Sprog < Flanimal; end
273
+
274
+ describe "DataMapper::Resource with #{ADAPTER}" do
275
+ before :all do
276
+ Orange.auto_migrate!(ADAPTER)
277
+ Apple.auto_migrate!(ADAPTER)
278
+ FortunePig.auto_migrate!(ADAPTER)
279
+
280
+ orange = Orange.new(:color => 'orange')
281
+ orange.name = 'Bob' # Keys are protected from mass-assignment by default.
282
+ repository(ADAPTER) { orange.save }
283
+ end
284
+
285
+ it "should be able to overwrite Resource#to_s" do
286
+ repository(ADAPTER) do
287
+ ted = FortunePig.create(:name => "Ted")
288
+ FortunePig.get!(ted.id).to_s.should == 'Ted'
289
+ end
290
+ end
291
+
292
+ it "should be able to destroy objects" do
293
+ apple = Apple.create(:color => 'Green')
294
+ lambda do
295
+ apple.destroy.should be_true
296
+ end.should_not raise_error
297
+ end
298
+
299
+ it 'should return false to #destroy if the resource is new' do
300
+ Apple.new.destroy.should be_false
301
+ end
302
+
303
+ it "should be able to reload objects" do
304
+ orange = repository(ADAPTER) { Orange.get!('Bob') }
305
+ orange.color.should == 'orange'
306
+ orange.color = 'blue'
307
+ orange.color.should == 'blue'
308
+ orange.reload
309
+ orange.color.should == 'orange'
310
+ end
311
+
312
+ it "should be able to reload new objects" do
313
+ repository(ADAPTER) do
314
+ Orange.create(:name => 'Tom').reload
315
+ end
316
+ end
317
+
318
+ it "should be able to find first or create objects" do
319
+ repository(ADAPTER) do
320
+ orange = Orange.create(:name => 'Naval')
321
+
322
+ Orange.first_or_create(:name => 'Naval').should == orange
323
+
324
+ purple = Orange.first_or_create(:name => 'Purple', :color => 'Fuschia')
325
+ oranges = Orange.all(:name => 'Purple')
326
+ oranges.size.should == 1
327
+ oranges.first.should == purple
328
+ end
329
+ end
330
+
331
+ it "should be able to override a default with a nil" do
332
+ repository(ADAPTER) do
333
+ apple = Apple.new
334
+ apple.color = nil
335
+ apple.save
336
+ apple.color.should be_nil
337
+
338
+ apple = Apple.create(:color => nil)
339
+ apple.color.should be_nil
340
+ end
341
+ end
342
+
343
+ it "should be able to respond to create hooks" do
344
+ bob = repository(ADAPTER) { FortunePig.create(:name => 'Bob') }
345
+ bob.id.should_not be_nil
346
+ bob.instance_variable_get("@created_id").should == bob.id
347
+
348
+ fred = FortunePig.new(:name => 'Fred')
349
+ repository(ADAPTER) { fred.save }
350
+ fred.id.should_not be_nil
351
+ fred.instance_variable_get("@save_id").should == fred.id
352
+ end
353
+
354
+ it "should be dirty when Object properties are changed" do
355
+ # pending "Awaiting Property#track implementation"
356
+ repository(ADAPTER) do
357
+ Male.auto_migrate!
358
+ end
359
+ repository(ADAPTER) do
360
+ bob = Male.create(:name => "Bob", :data => {})
361
+ bob.dirty?.should be_false
362
+ bob.data.merge!(:name => "Bob")
363
+ bob.dirty?.should be_true
364
+ bob = Male.first
365
+ bob.data[:name] = "Bob"
366
+ bob.dirty?.should be_true
367
+ end
368
+ end
369
+
370
+ describe "hooking" do
371
+ before :all do
372
+ Car.auto_migrate!(ADAPTER)
373
+ end
374
+
375
+ it "should execute hooks before creating/updating objects" do
376
+ repository(ADAPTER) do
377
+ c1 = Car.new(:brand => 'BMW', :color => 'white')
378
+
379
+ c1.new_record?.should == true
380
+ c1.created_on.should == nil
381
+
382
+ c1.save
383
+
384
+ c1.new_record?.should == false
385
+ c1.touched_on.should == Date.today
386
+ c1.created_on.should == Date.today
387
+ c1.updated_on.should == nil
388
+
389
+ c1.color = 'black'
390
+ c1.save
391
+
392
+ c1.updated_on.should == Date.today
393
+ end
394
+
395
+ end
396
+
397
+ end
398
+
399
+ describe "inheritance" do
400
+ before :all do
401
+ Geek.auto_migrate!(ADAPTER)
402
+
403
+ repository(ADAPTER) do
404
+ Male.create(:name => 'John Dorian')
405
+ Bully.create(:name => 'Bob', :iq => 69)
406
+ Geek.create(:name => 'Steve', :awkward => false, :iq => 132)
407
+ Geek.create(:name => 'Bill', :iq => 150)
408
+ Bully.create(:name => 'Johnson')
409
+ Mugger.create(:name => 'Frank')
410
+ Maniac.create(:name => 'William')
411
+ Psycho.create(:name => 'Norman')
412
+ end
413
+
414
+ Flanimal.auto_migrate!(ADAPTER)
415
+
416
+ end
417
+
418
+ it "should test bug ticket #302" do
419
+ repository(ADAPTER) do
420
+ Sprog.create(:name => 'Marty')
421
+ Sprog.first(:name => 'Marty').should_not be_nil
422
+ end
423
+ end
424
+
425
+ it "should select appropriate types" do
426
+ repository(ADAPTER) do
427
+ males = Male.all
428
+ males.should have(8).entries
429
+
430
+ males.each do |male|
431
+ male.class.name.should == male.type.name
432
+ end
433
+
434
+ Male.first(:name => 'Steve').should be_a_kind_of(Geek)
435
+ Bully.first(:name => 'Bob').should be_a_kind_of(Bully)
436
+ Geek.first(:name => 'Steve').should be_a_kind_of(Geek)
437
+ Geek.first(:name => 'Bill').should be_a_kind_of(Geek)
438
+ Bully.first(:name => 'Johnson').should be_a_kind_of(Bully)
439
+ Male.first(:name => 'John Dorian').should be_a_kind_of(Male)
440
+ end
441
+ end
442
+
443
+ it "should not select parent type" do
444
+ repository(ADAPTER) do
445
+ Male.first(:name => 'John Dorian').should be_a_kind_of(Male)
446
+ Geek.first(:name => 'John Dorian').should be_nil
447
+ Geek.first.iq.should > Bully.first.iq
448
+ end
449
+ end
450
+
451
+ it "should select objects of all inheriting classes" do
452
+ repository(ADAPTER) do
453
+ Male.all.should have(8).entries
454
+ Geek.all.should have(2).entries
455
+ Bully.all.should have(5).entries
456
+ Mugger.all.should have(1).entries
457
+ Maniac.all.should have(2).entries
458
+ Psycho.all.should have(1).entries
459
+ end
460
+ end
461
+
462
+ it "should inherit setter method from parent" do
463
+ repository(ADAPTER) do
464
+ Bully.first(:name => "Bob").iq.should == 68
465
+ end
466
+ end
467
+
468
+ it "should be able to overwrite a setter in a child class" do
469
+ repository(ADAPTER) do
470
+ Geek.first(:name => "Bill").iq.should == 180
471
+ end
472
+ end
473
+ end
474
+ end
475
+ end