dm-hibernate-adapter 0.1pre-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. data/lib/dm-hibernate-adapter.rb +471 -0
  2. data/lib/dm-hibernate-adapter/dialects.rb +37 -0
  3. data/lib/dm-hibernate-adapter/hibernate.rb +403 -0
  4. data/lib/dm-hibernate-adapter/spec/setup.rb +27 -0
  5. data/lib/dm-hibernate-adapter/transaction.rb +27 -0
  6. data/lib/dm-hibernate-adapter_ext.jar +0 -0
  7. data/lib/jibernate.rb +2 -0
  8. data/spec/abstract_adapter/adapter_shared_spec.rb +514 -0
  9. data/spec/abstract_adapter/dm-hibernate-adapter_spec.rb +25 -0
  10. data/spec/abstract_adapter/rcov.opts +6 -0
  11. data/spec/abstract_adapter/spec.opts +4 -0
  12. data/spec/abstract_adapter/spec_helper.rb +8 -0
  13. data/spec/dm_core/adapter_spec.rb +12 -0
  14. data/spec/dm_core/rcov.opts +6 -0
  15. data/spec/dm_core/spec.opts +5 -0
  16. data/spec/dm_core/spec_helper.rb +42 -0
  17. data/spec/log4j.properties +11 -0
  18. data/spec/transient/dm-hibernate-adapter_spec.rb +57 -0
  19. data/spec/transient/lib/adapter_helpers.rb +107 -0
  20. data/spec/transient/lib/collection_helpers.rb +18 -0
  21. data/spec/transient/lib/counter_adapter.rb +38 -0
  22. data/spec/transient/lib/pending_helpers.rb +46 -0
  23. data/spec/transient/lib/rspec_immediate_feedback_formatter.rb +54 -0
  24. data/spec/transient/rcov.opts +6 -0
  25. data/spec/transient/shared/adapter_shared_spec.rb +408 -0
  26. data/spec/transient/shared/finder_shared_spec.rb +1513 -0
  27. data/spec/transient/shared/model_spec.rb +165 -0
  28. data/spec/transient/shared/property_spec.rb +412 -0
  29. data/spec/transient/shared/resource_shared_spec.rb +1226 -0
  30. data/spec/transient/shared/resource_spec.rb +133 -0
  31. data/spec/transient/shared/sel_shared_spec.rb +112 -0
  32. data/spec/transient/spec.opts +4 -0
  33. data/spec/transient/spec_helper.rb +14 -0
  34. metadata +210 -0
@@ -0,0 +1,165 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ share_examples_for 'An Adapter with model_spec support' do
4
+ # TODO: move these specs into shared specs for #copy
5
+ describe DataMapper::Model do
6
+ before :all do
7
+
8
+ raise '+@adapter+ should be defined in before block' unless instance_variable_get('@adapter')
9
+
10
+ # module ::Blog
11
+
12
+ class Article
13
+ include DataMapper::Resource
14
+
15
+ property :id, Serial
16
+ property :title, String, :required => true
17
+ property :content, Text, :writer => :private, :default => lambda { |resource, property| resource.title }
18
+ property :subtitle, String
19
+ property :author, String, :required => true
20
+
21
+ belongs_to :original, self, :required => false
22
+ has n, :revisions, self, :child_key => [ :original_id ]
23
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
24
+ end
25
+ # end
26
+
27
+ @article_model = Article
28
+ end
29
+
30
+ # supported_by :all do
31
+ before :all do
32
+ @author = 'Dan Kubb'
33
+
34
+ @original = @article_model.create(:title => 'Original Article', :author => @author)
35
+ @article = @article_model.create(:title => 'Sample Article', :original => @original, :author => @author)
36
+ @other = @article_model.create(:title => 'Other Article', :author => @author)
37
+ end
38
+
39
+ it { @article_model.should respond_to(:copy) }
40
+
41
+ describe '#copy' do
42
+ # with_alternate_adapter do
43
+ describe 'between identical models' do
44
+ before :all do
45
+ @return = @resources = @article_model.copy(@repository.name, @alternate_adapter.name)
46
+ end
47
+
48
+ it 'should return a Collection' do
49
+ @return.should be_a_kind_of(DataMapper::Collection)
50
+ end
51
+
52
+ it 'should return Resources' do
53
+ @return.each { |resource| resource.should be_a_kind_of(DataMapper::Resource) }
54
+ end
55
+
56
+ it 'should have each Resource set to the expected Repository' do
57
+ @resources.each { |resource| resource.repository.name.should == @alternate_adapter.name }
58
+ end
59
+
60
+ it 'should create the Resources in the expected Repository' do
61
+ @article_model.all(:repository => DataMapper.repository(@alternate_adapter.name)).should == @resources
62
+ end
63
+ end
64
+
65
+ describe 'between different models' do
66
+ before :all do
67
+ @other.destroy
68
+ @article.destroy
69
+ @original.destroy
70
+
71
+ # make sure the default repository is empty
72
+ @article_model.all(:repository => @repository).should be_empty
73
+
74
+ # add an extra property to the alternate model
75
+ DataMapper.repository(@alternate_adapter.name) do
76
+ @article_model.property :status, String, :default => 'new'
77
+ end
78
+
79
+ if @article_model.respond_to?(:auto_migrate!)
80
+ @article_model.auto_migrate!(@alternate_adapter.name)
81
+ end
82
+
83
+ # add new resources to the alternate repository
84
+ DataMapper.repository(@alternate_adapter.name) do
85
+ @heff1 = @article_model.create(:title => 'Alternate Repository', :author => @author)
86
+ end
87
+
88
+ # copy from the alternate to the default repository
89
+ @return = @resources = @article_model.copy(@alternate_adapter.name, :default)
90
+ end
91
+
92
+ it 'should return a Collection' do
93
+ @return.should be_a_kind_of(DataMapper::Collection)
94
+ end
95
+
96
+ it 'should return Resources' do
97
+ @return.each { |resource| resource.should be_a_kind_of(DataMapper::Resource) }
98
+ end
99
+
100
+ it 'should have each Resource set to the expected Repository' do
101
+ @resources.each { |resource| resource.repository.name.should == :default }
102
+ end
103
+
104
+ it 'should create the Resources in the expected Repository' do
105
+ @article_model.all.should == @resources
106
+ end
107
+ end
108
+ # end
109
+ end
110
+ end
111
+ # end
112
+
113
+ describe DataMapper::Model do
114
+ extend DataMapper::Spec::CollectionHelpers::GroupMethods
115
+
116
+ self.loaded = false
117
+
118
+ before :all do
119
+ module ::Blog
120
+ class Article
121
+ include DataMapper::Resource
122
+
123
+ property :id, Serial
124
+ property :title, String
125
+ property :content, Text
126
+ property :subtitle, String
127
+
128
+ belongs_to :original, self, :required => false
129
+ has n, :revisions, self, :child_key => [ :original_id ]
130
+ has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
131
+ has n, :publications, :through => Resource
132
+ end
133
+
134
+ class Publication
135
+ include DataMapper::Resource
136
+
137
+ property :id, Serial
138
+ property :name, String
139
+
140
+ has n, :articles, :through => Resource
141
+ end
142
+ end
143
+
144
+ @article_model = Blog::Article
145
+ @publication_model = Blog::Publication
146
+ end
147
+
148
+ # supported_by :all do
149
+ # model cannot be a kicker
150
+ def should_not_be_a_kicker; end
151
+
152
+ def model?; true end
153
+
154
+ before :all do
155
+ @articles = @article_model
156
+
157
+ @original = @articles.create(:title => 'Original Article')
158
+ @article = @articles.create(:title => 'Sample Article', :content => 'Sample', :original => @original)
159
+ @other = @articles.create(:title => 'Other Article', :content => 'Other')
160
+ end
161
+
162
+ it_should_behave_like 'Finder Interface'
163
+ # end
164
+ end
165
+ end
@@ -0,0 +1,412 @@
1
+ # -*- coding: utf-8 -*-
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
3
+
4
+ share_examples_for 'An Adapter with property_spec support' do
5
+ # instance methods
6
+ describe DataMapper::Property do
7
+
8
+ # define the model prior to supported_by
9
+ before :all do
10
+ class ::Track
11
+ include DataMapper::Resource
12
+
13
+ property :id, Serial
14
+ property :artist, String, :lazy => false, :index => :artist_album
15
+ property :title, String, :field => 'name', :index => true
16
+ property :album, String, :index => :artist_album
17
+ property :musicbrainz_hash, String, :unique => true, :unique_index => true
18
+ end
19
+
20
+ class ::Image
21
+ include DataMapper::Resource
22
+
23
+ property :md5hash, String, :key => true, :length => 32
24
+ property :title, String, :required => true, :unique => true
25
+ property :description, Text, :length => 1..1024, :lazy => [ :detail ]
26
+ property :format, String, :default => 'jpeg'
27
+ property :taken_at, Time, :default => proc { Time.now }
28
+ end
29
+
30
+ # TODO
31
+ # <added>
32
+ ::Track.auto_migrate!
33
+ ::Image.auto_migrate!
34
+ # </added>
35
+ end
36
+
37
+ # supported_by :all do
38
+ describe '#field' do
39
+ it 'returns @field value if it is present' do
40
+ Track.properties[:title].field.should eql('name')
41
+ end
42
+
43
+ it 'returns field for specific repository when it is present'
44
+
45
+ it 'sets field value using field naming convention on first reference'
46
+ end
47
+
48
+ describe '#custom?' do
49
+ it 'is true for custom type fields (not provided by dm_core)'
50
+
51
+ it 'is false for core type fields (provided by dm_core)'
52
+ end
53
+
54
+ describe '#default_for' do
55
+ it 'returns default value for non-callables' do
56
+ Image.properties[:format].default_for(Image.new).should == 'jpeg'
57
+ end
58
+
59
+ it 'returns result of a call for callable values' do
60
+ Image.properties[:taken_at].default_for(Image.new).year.should == Time.now.year
61
+ end
62
+ end
63
+
64
+ describe '#eql?' do
65
+ it 'is true for properties with the same model and name' do
66
+ Track.properties[:title].should eql(Track.properties[:title])
67
+ end
68
+
69
+
70
+ it 'is false for properties of different models' do
71
+ Track.properties[:title].should_not eql(Image.properties[:title])
72
+ end
73
+
74
+ it 'is false for properties with different names' do
75
+ Track.properties[:title].should_not eql(Track.properties[:id])
76
+ end
77
+ end
78
+
79
+ describe '#get' do
80
+ before :all do
81
+ @image = Image.create(:md5hash => '5268f0f3f452844c79843e820f998869',
82
+ :title => 'Rome at the sunset',
83
+ :description => 'Just wow')
84
+
85
+ @image.should be_saved
86
+
87
+ @image = Image.first(:fields => [ :md5hash, :title ], :md5hash => @image.md5hash)
88
+ end
89
+
90
+ it 'triggers loading for lazy loaded properties' do
91
+ Image.properties[:description].get(@image)
92
+ Image.properties[:description].loaded?(@image).should be(true)
93
+ end
94
+
95
+ it 'assigns loaded value to @ivar' do
96
+ Image.properties[:description].get(@image)
97
+ @image.instance_variable_get(:@description).should == 'Just wow'
98
+ end
99
+
100
+ it 'sets default value for new records with nil value' do
101
+ Image.properties[:format].get(@image).should == 'jpeg'
102
+ end
103
+
104
+ it 'returns property value' do
105
+ Image.properties[:description].get(@image).should == 'Just wow'
106
+ end
107
+ end
108
+
109
+ describe '#get!' do
110
+ before :all do
111
+ @image = Image.new
112
+
113
+ # now some dark Ruby magic
114
+ @image.instance_variable_set(:@description, 'Is set by magic')
115
+ end
116
+
117
+ it 'gets instance variable value from the resource directly' do
118
+ # if you know a better way to test direct instance variable access,
119
+ # go ahead and make changes to this example
120
+ Image.properties[:description].get!(@image).should == 'Is set by magic'
121
+ end
122
+ end
123
+
124
+ describe '#index' do
125
+ it 'returns true when property has an index' do
126
+ Track.properties[:title].index.should be_true
127
+ end
128
+
129
+ it 'returns index name when property has a named index' do
130
+ Track.properties[:album].index.should eql(:artist_album)
131
+ end
132
+
133
+ it 'returns nil when property has no index' do
134
+ Track.properties[:musicbrainz_hash].index.should be_nil
135
+ end
136
+ end
137
+
138
+ describe '#initialize' do
139
+ describe 'when tracking strategy is explicitly given' do
140
+ it 'uses tracking strategy from options'
141
+ end
142
+
143
+ describe 'when custom type has tracking stragegy' do
144
+ it 'uses tracking strategy from type'
145
+ end
146
+ end
147
+
148
+ describe '#inspect' do
149
+ before :all do
150
+ @str = Track.properties[:title].inspect
151
+ end
152
+
153
+ it 'features model name' do
154
+ @str.should =~ /@model=Track/
155
+ end
156
+
157
+ it 'features property name' do
158
+ @str.should =~ /@name=:title/
159
+ end
160
+ end
161
+
162
+ describe '#key?' do
163
+ describe 'returns true when property is a ' do
164
+ it 'serial key' do
165
+ Track.properties[:id].key?.should be_true
166
+ end
167
+ it 'natural key' do
168
+ Image.properties[:md5hash].key?.should be_true
169
+ end
170
+ end
171
+
172
+ it 'returns true when property is a part of composite key'
173
+
174
+ it 'returns false when property does not relate to a key' do
175
+ Track.properties[:title].key?.should be_false
176
+ end
177
+ end
178
+
179
+ describe '#lazy?' do
180
+ it 'returns true when property is lazy loaded' do
181
+ Image.properties[:description].lazy?.should be_true
182
+ end
183
+
184
+ it 'returns false when property is not lazy loaded' do
185
+ Track.properties[:artist].lazy?.should be_false
186
+ end
187
+ end
188
+
189
+ describe '#length' do
190
+ it 'returns upper bound for Range values' do
191
+ Image.properties[:description].length.should eql(1024)
192
+ end
193
+
194
+ it 'returns value as is for integer values' do
195
+ Image.properties[:md5hash].length.should eql(32)
196
+ end
197
+ end
198
+
199
+ describe '#min' do
200
+ describe 'when :min and :max options not provided to constructor' do
201
+ before do
202
+ @property = Image.property(:integer_with_nil_min, Integer)
203
+ end
204
+
205
+ it 'should be nil' do
206
+ @property.min.should be_nil
207
+ end
208
+ end
209
+
210
+ describe 'when :min option not provided to constructor, but :max is provided' do
211
+ before do
212
+ @property = Image.property(:integer_with_default_min, Integer, :max => 1)
213
+ end
214
+
215
+ it 'should be the default value' do
216
+ @property.min.should == 0
217
+ end
218
+ end
219
+
220
+ describe 'when :min and :max options provided to constructor' do
221
+ before do
222
+ @min = 1
223
+ @property = Image.property(:integer_with_explicit_min, Integer, :min => @min, :max => 2)
224
+ end
225
+
226
+ it 'should be the expected value' do
227
+ @property.min.should == @min
228
+ end
229
+ end
230
+ end
231
+
232
+ describe '#max' do
233
+ describe 'when :min and :max options not provided to constructor' do
234
+ before do
235
+ @property = Image.property(:integer_with_nil_max, Integer)
236
+ end
237
+
238
+ it 'should be nil' do
239
+ @property.max.should be_nil
240
+ end
241
+ end
242
+
243
+ describe 'when :max option not provided to constructor, but :min is provided' do
244
+ before do
245
+ @property = Image.property(:integer_with_default_max, Integer, :min => 1)
246
+ end
247
+
248
+ it 'should be the default value' do
249
+ @property.max.should == 2**31-1
250
+ end
251
+ end
252
+
253
+ describe 'when :min and :max options provided to constructor' do
254
+ before do
255
+ @max = 2
256
+ @property = Image.property(:integer_with_explicit_max, Integer, :min => 1, :max => @max)
257
+ end
258
+
259
+ it 'should be the expected value' do
260
+ @property.max.should == @max
261
+ end
262
+ end
263
+ end
264
+
265
+ describe '#allow_nil?' do
266
+ it 'returns true when property can accept nil as its value' do
267
+ Track.properties[:artist].allow_nil?.should be_true
268
+ end
269
+
270
+ it 'returns false when property nil value is prohibited for this property' do
271
+ Image.properties[:title].allow_nil?.should be_false
272
+ end
273
+ end
274
+
275
+ describe '#serial?' do
276
+ it 'returns true when property is serial (auto incrementing)' do
277
+ Track.properties[:id].serial?.should be_true
278
+ end
279
+
280
+ it 'returns false when property is NOT serial (auto incrementing)' do
281
+ Image.properties[:md5hash].serial?.should be_false
282
+ end
283
+ end
284
+
285
+ # What's going on here:
286
+ #
287
+ # we first set original value and make an assertion on it
288
+ # then we try to set it again, which clears original value
289
+ # (since original value is set, property is no longer dirty)
290
+ describe '#set_original_value' do
291
+ before :all do
292
+ @image = Image.create(
293
+ :md5hash => '5268f0f3f452844c79843e820f998869',
294
+ :title => 'Rome at the sunset',
295
+ :description => 'Just wow'
296
+ )
297
+
298
+ @property = Image.properties[:title]
299
+ end
300
+
301
+ describe 'when value changes' do
302
+ before :all do
303
+ @property.set_original_value(@image, 'New title')
304
+ end
305
+
306
+ it 'sets original value of the property' do
307
+ @image.original_attributes[@property].should == 'Rome at the sunset'
308
+ end
309
+ end
310
+
311
+ describe 'when value stays the same' do
312
+ before :all do
313
+ @property.set_original_value(@image, 'Rome at the sunset')
314
+ end
315
+
316
+ it 'only sets original value when it has changed' do
317
+ @property.set_original_value(@image, 'Rome at the sunset')
318
+ @image.original_attributes.should_not have_key(@property)
319
+ end
320
+ end
321
+ end
322
+
323
+ describe '#set' do
324
+ before :all do
325
+ # keep in mind we must run these examples with a
326
+ # saved model instance
327
+ @image = Image.create(
328
+ :md5hash => '5268f0f3f452844c79843e820f998869',
329
+ :title => 'Rome at the sunset',
330
+ :description => 'Just wow'
331
+ )
332
+
333
+ @property = Image.properties[:title]
334
+ end
335
+
336
+ it 'triggers lazy loading for given resource'
337
+
338
+ it 'type casts given value' do
339
+ @property.set(@image, Addressable::URI.parse('http://test.example/'))
340
+ # get a string that has been typecasted using #to_str
341
+ @image.title.should == 'http://test.example/'
342
+ end
343
+
344
+ it 'stores original value' do
345
+ @property.set(@image, 'Updated value')
346
+ @image.original_attributes[@property].should == 'Rome at the sunset'
347
+ end
348
+
349
+ it 'sets new property value' do
350
+ @property.set(@image, 'Updated value')
351
+ @image.title.should == 'Updated value'
352
+ end
353
+ end
354
+
355
+ describe '#set!' do
356
+ before :all do
357
+ @image = Image.new(:md5hash => '5268f0f3f452844c79843e820f998869',
358
+ :title => 'Rome at the sunset',
359
+ :description => 'Just wow')
360
+
361
+ @property = Image.properties[:title]
362
+ end
363
+
364
+ it 'directly sets instance variable on given resource' do
365
+ @property.set!(@image, 'Set with dark Ruby magic')
366
+ @image.title.should == 'Set with dark Ruby magic'
367
+ end
368
+ end
369
+
370
+ describe '#unique?' do
371
+ it 'is true for fields that explicitly given uniq index' do
372
+ Track.properties[:musicbrainz_hash].unique?.should be_true
373
+ end
374
+
375
+ it 'is true for serial fields' do
376
+ pending do
377
+ Track.properties[:title].unique?.should be_true
378
+ end
379
+ end
380
+
381
+ it 'is true for keys' do
382
+ Image.properties[:md5hash].unique?.should be_true
383
+ end
384
+ end
385
+
386
+ describe '#unique_index' do
387
+ it 'returns true when property has unique index' do
388
+ Track.properties[:musicbrainz_hash].unique_index.should be_true
389
+ end
390
+
391
+ it 'returns nil when property has no unique index' do
392
+ Image.properties[:title].unique_index.should be_nil
393
+ end
394
+ end
395
+
396
+ describe "exception on bad property names" do
397
+ it "is raised for 'model'" do
398
+ lambda {
399
+ Track.property :model, String
400
+ }.should raise_error(ArgumentError)
401
+ end
402
+
403
+ it "is raised for 'repository_name'" do
404
+ lambda {
405
+ Track.property :repository_name, String
406
+ }.should raise_error(ArgumentError)
407
+ end
408
+ end
409
+ # end
410
+ end # DataMapper::Property
411
+
412
+ end