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