dm-core 0.9.2 → 0.9.3
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/{CHANGELOG → History.txt} +78 -77
- data/Manifest.txt +123 -0
- data/{README → README.txt} +0 -0
- data/Rakefile +29 -0
- data/SPECS +63 -0
- data/TODO +1 -0
- data/lib/dm-core.rb +6 -1
- data/lib/dm-core/adapters/data_objects_adapter.rb +29 -32
- data/lib/dm-core/adapters/mysql_adapter.rb +1 -1
- data/lib/dm-core/adapters/postgres_adapter.rb +1 -1
- data/lib/dm-core/adapters/sqlite3_adapter.rb +2 -2
- data/lib/dm-core/associations.rb +26 -0
- data/lib/dm-core/associations/many_to_many.rb +34 -25
- data/lib/dm-core/associations/many_to_one.rb +4 -4
- data/lib/dm-core/associations/one_to_many.rb +48 -13
- data/lib/dm-core/associations/one_to_one.rb +4 -4
- data/lib/dm-core/associations/relationship.rb +144 -42
- data/lib/dm-core/associations/relationship_chain.rb +31 -24
- data/lib/dm-core/auto_migrations.rb +0 -4
- data/lib/dm-core/collection.rb +40 -7
- data/lib/dm-core/dependency_queue.rb +31 -0
- data/lib/dm-core/hook.rb +2 -2
- data/lib/dm-core/is.rb +2 -2
- data/lib/dm-core/logger.rb +10 -10
- data/lib/dm-core/model.rb +94 -41
- data/lib/dm-core/property.rb +72 -41
- data/lib/dm-core/property_set.rb +8 -14
- data/lib/dm-core/query.rb +34 -9
- data/lib/dm-core/repository.rb +0 -0
- data/lib/dm-core/resource.rb +13 -13
- data/lib/dm-core/scope.rb +25 -2
- data/lib/dm-core/type.rb +3 -3
- data/lib/dm-core/types/discriminator.rb +10 -8
- data/lib/dm-core/types/object.rb +4 -0
- data/lib/dm-core/types/paranoid_boolean.rb +15 -4
- data/lib/dm-core/types/paranoid_datetime.rb +15 -4
- data/lib/dm-core/version.rb +3 -0
- data/script/all +5 -0
- data/script/performance.rb +191 -0
- data/script/profile.rb +86 -0
- data/spec/integration/association_spec.rb +288 -204
- data/spec/integration/association_through_spec.rb +9 -3
- data/spec/integration/associations/many_to_many_spec.rb +97 -31
- data/spec/integration/associations/many_to_one_spec.rb +41 -6
- data/spec/integration/associations/one_to_many_spec.rb +18 -2
- data/spec/integration/auto_migrations_spec.rb +0 -0
- data/spec/integration/collection_spec.rb +89 -42
- data/spec/integration/dependency_queue_spec.rb +58 -0
- data/spec/integration/model_spec.rb +67 -8
- data/spec/integration/postgres_adapter_spec.rb +19 -20
- data/spec/integration/property_spec.rb +17 -8
- data/spec/integration/query_spec.rb +273 -191
- data/spec/integration/resource_spec.rb +108 -10
- data/spec/integration/strategic_eager_loading_spec.rb +138 -0
- data/spec/integration/transaction_spec.rb +3 -3
- data/spec/integration/type_spec.rb +121 -0
- data/spec/lib/logging_helper.rb +18 -0
- data/spec/lib/model_loader.rb +91 -0
- data/spec/lib/publicize_methods.rb +28 -0
- data/spec/models/vehicles.rb +34 -0
- data/spec/models/zoo.rb +48 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +25 -62
- data/spec/unit/adapters/data_objects_adapter_spec.rb +1 -0
- data/spec/unit/associations/many_to_many_spec.rb +3 -0
- data/spec/unit/associations/many_to_one_spec.rb +9 -1
- data/spec/unit/associations/one_to_many_spec.rb +12 -4
- data/spec/unit/associations/relationship_spec.rb +19 -15
- data/spec/unit/associations_spec.rb +37 -0
- data/spec/unit/collection_spec.rb +8 -0
- data/spec/unit/data_mapper_spec.rb +14 -0
- data/spec/unit/model_spec.rb +2 -2
- data/spec/unit/property_set_spec.rb +0 -13
- data/spec/unit/property_spec.rb +92 -21
- data/spec/unit/query_spec.rb +49 -4
- data/spec/unit/resource_spec.rb +122 -60
- data/spec/unit/scope_spec.rb +11 -0
- data/tasks/ci.rb +68 -0
- data/tasks/dm.rb +63 -0
- data/tasks/doc.rb +20 -0
- data/tasks/hoe.rb +38 -0
- data/tasks/install.rb +20 -0
- metadata +63 -22
@@ -1,6 +1,9 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
2
2
|
|
3
3
|
describe DataMapper::Associations::Relationship do
|
4
|
+
|
5
|
+
load_models_for_metaphor :vehicles
|
6
|
+
|
4
7
|
it "should describe an association" do
|
5
8
|
belongs_to = DataMapper::Associations::Relationship.new(
|
6
9
|
:manufacturer,
|
@@ -11,50 +14,51 @@ describe DataMapper::Associations::Relationship do
|
|
11
14
|
)
|
12
15
|
|
13
16
|
belongs_to.should respond_to(:name)
|
14
|
-
belongs_to.should respond_to(:
|
17
|
+
belongs_to.should respond_to(:with_repository)
|
15
18
|
belongs_to.should respond_to(:child_key)
|
16
19
|
belongs_to.should respond_to(:parent_key)
|
17
20
|
end
|
18
21
|
|
19
22
|
it "should map properties explicitly when an association method passes them in its options" do
|
20
|
-
repository_name = :mock
|
21
|
-
|
22
23
|
belongs_to = DataMapper::Associations::Relationship.new(
|
23
24
|
:manufacturer,
|
24
|
-
|
25
|
+
:mock,
|
25
26
|
'Vehicle',
|
26
27
|
'Manufacturer',
|
27
28
|
{ :child_key => [ :manufacturer_id ], :parent_key => [ :id ] }
|
28
29
|
)
|
29
30
|
|
30
31
|
belongs_to.name.should == :manufacturer
|
31
|
-
belongs_to.
|
32
|
+
belongs_to.with_repository do |r|
|
33
|
+
r.name.should == :mock
|
34
|
+
end
|
32
35
|
|
33
36
|
belongs_to.child_key.should be_a_kind_of(DataMapper::PropertySet)
|
34
37
|
belongs_to.parent_key.should be_a_kind_of(DataMapper::PropertySet)
|
35
38
|
|
36
|
-
belongs_to.child_key.to_a.should == Vehicle.properties(
|
37
|
-
belongs_to.parent_key.to_a.should == Manufacturer.properties(
|
39
|
+
belongs_to.child_key.to_a.should == Vehicle.properties(:mock).slice(:manufacturer_id)
|
40
|
+
belongs_to.parent_key.to_a.should == Manufacturer.properties(:mock).key
|
38
41
|
end
|
39
42
|
|
40
43
|
it "should infer properties when options aren't passed" do
|
41
|
-
repository_name = :mock
|
42
|
-
|
43
44
|
has_many = DataMapper::Associations::Relationship.new(
|
44
45
|
:models,
|
45
|
-
|
46
|
+
:mock,
|
46
47
|
'Vehicle',
|
47
|
-
'Manufacturer'
|
48
|
+
'Manufacturer',
|
49
|
+
{ :child_key => [:model_id] }
|
48
50
|
)
|
49
51
|
|
50
52
|
has_many.name.should == :models
|
51
|
-
has_many.
|
53
|
+
has_many.with_repository do |r|
|
54
|
+
r.name.should == :mock
|
55
|
+
end
|
52
56
|
|
53
57
|
has_many.child_key.should be_a_kind_of(DataMapper::PropertySet)
|
54
58
|
has_many.parent_key.should be_a_kind_of(DataMapper::PropertySet)
|
55
|
-
|
56
|
-
has_many.child_key.to_a.should == Vehicle.properties(
|
57
|
-
has_many.parent_key.to_a.should == Manufacturer.properties(
|
59
|
+
# Vehicle.has n, :models, :class_name => 'Manufacturer', :child_key => "models_id"
|
60
|
+
has_many.child_key.to_a.should == Vehicle.properties(:mock).slice(:model_id)
|
61
|
+
has_many.parent_key.to_a.should == Manufacturer.properties(:mock).key
|
58
62
|
end
|
59
63
|
|
60
64
|
it "should generate child properties with a safe subset of the parent options" do
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
2
|
|
3
3
|
describe "DataMapper::Associations" do
|
4
|
+
|
5
|
+
load_models_for_metaphor :vehicles
|
6
|
+
|
4
7
|
before do
|
5
8
|
@relationship = mock(DataMapper::Associations::Relationship)
|
6
9
|
@n = 1.0/0
|
@@ -8,6 +11,40 @@ describe "DataMapper::Associations" do
|
|
8
11
|
Manufacturer.mock_relationship = Vehicle.mock_relationship = @relationship
|
9
12
|
end
|
10
13
|
|
14
|
+
describe "#many_to_one_relationships" do
|
15
|
+
before :all do
|
16
|
+
module MTORelationships
|
17
|
+
class A
|
18
|
+
include DataMapper::Resource
|
19
|
+
def self.default_repository_name
|
20
|
+
:a_db
|
21
|
+
end
|
22
|
+
repository(:b_db) do
|
23
|
+
belongs_to :b
|
24
|
+
end
|
25
|
+
repository(:c_db) do
|
26
|
+
belongs_to :c
|
27
|
+
end
|
28
|
+
end
|
29
|
+
class B
|
30
|
+
include DataMapper::Resource
|
31
|
+
def self.default_repository_name
|
32
|
+
:b_db
|
33
|
+
end
|
34
|
+
end
|
35
|
+
class C
|
36
|
+
include DataMapper::Resource
|
37
|
+
def self.default_repository_name
|
38
|
+
:c_db
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
it "should list all relationships that are one-to-many" do
|
44
|
+
MTORelationships::A.many_to_one_relationships.sort_by { |r| r.name.to_s }.should == [MTORelationships::A.relationships(:b_db)[:b], MTORelationships::A.relationships(:c_db)[:c]]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
11
48
|
describe ".relationships" do
|
12
49
|
class B
|
13
50
|
include DataMapper::Resource
|
@@ -24,6 +24,10 @@ describe DataMapper::Collection do
|
|
24
24
|
@collection.should respond_to(:at)
|
25
25
|
end
|
26
26
|
|
27
|
+
it 'should provide #build' do
|
28
|
+
@collection.should respond_to(:build)
|
29
|
+
end
|
30
|
+
|
27
31
|
it 'should provide #clear' do
|
28
32
|
@collection.should respond_to(:clear)
|
29
33
|
end
|
@@ -72,6 +76,10 @@ describe DataMapper::Collection do
|
|
72
76
|
@collection.should respond_to(:first)
|
73
77
|
end
|
74
78
|
|
79
|
+
it 'should provide #freeze' do
|
80
|
+
@collection.should respond_to(:freeze)
|
81
|
+
end
|
82
|
+
|
75
83
|
it 'should provide #get' do
|
76
84
|
@collection.should respond_to(:get)
|
77
85
|
end
|
@@ -1,6 +1,20 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
2
|
|
3
3
|
describe DataMapper do
|
4
|
+
describe ".dependency_queue" do
|
5
|
+
before(:all) do
|
6
|
+
@q = DataMapper.dependency_queue
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return a dependency queue" do
|
10
|
+
@q.should be_a_kind_of(DataMapper::DependencyQueue)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should only create one dependency queue" do
|
14
|
+
@q.should == DataMapper.dependency_queue
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
4
18
|
describe ".prepare" do
|
5
19
|
it "should pass the default repository to the block if no argument is given" do
|
6
20
|
DataMapper.should_receive(:repository).with(no_args).and_return :default_repo
|
data/spec/unit/model_spec.rb
CHANGED
@@ -205,11 +205,11 @@ describe 'DataMapper::Model' do
|
|
205
205
|
@standard_resource_inclusions = DataMapper::Resource.instance_variable_get('@extra_inclusions')
|
206
206
|
@standard_model_extensions = DataMapper::Model.instance_variable_get('@extra_extensions')
|
207
207
|
end
|
208
|
-
|
208
|
+
|
209
209
|
before(:each) do
|
210
210
|
DataMapper::Resource.instance_variable_set('@extra_inclusions', [])
|
211
211
|
DataMapper::Model.instance_variable_set('@extra_extensions', [])
|
212
|
-
|
212
|
+
|
213
213
|
@module = Module.new do
|
214
214
|
def greet
|
215
215
|
hi_mom!
|
@@ -79,18 +79,5 @@ describe DataMapper::PropertySet do
|
|
79
79
|
@properties.instance_variable_get("@property_for").should_not be_empty
|
80
80
|
@properties.dup.instance_variable_get("@property_for").should be_empty
|
81
81
|
end
|
82
|
-
|
83
|
-
it 'should be able to retarget a new model' do
|
84
|
-
copy = Icon.properties.dup(Boat)
|
85
|
-
copy.should have(4).entries
|
86
|
-
|
87
|
-
copy.each do |property|
|
88
|
-
property.model.should == Boat
|
89
|
-
end
|
90
|
-
|
91
|
-
copy << DataMapper::Property.new(Icon, :z_index, Integer, {})
|
92
|
-
copy.should have(5).entries
|
93
|
-
Icon.properties.should have(4).entries
|
94
|
-
end
|
95
82
|
end
|
96
83
|
end
|
data/spec/unit/property_spec.rb
CHANGED
@@ -52,6 +52,25 @@ describe DataMapper::Property do
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
it 'should provide #field' do
|
56
|
+
@property.should respond_to(:field)
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#field' do
|
60
|
+
it 'should accept a custom field' do
|
61
|
+
property = DataMapper::Property.new(Zoo, :location, String, :field => 'City')
|
62
|
+
property.field.should == 'City'
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should use repository name if passed in' do
|
66
|
+
@property.field(:default).should == 'name'
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should return default field if no repository name passed in' do
|
70
|
+
@property.field.should == 'name'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
55
74
|
it 'should provide #get' do
|
56
75
|
@property.should respond_to(:get)
|
57
76
|
end
|
@@ -105,7 +124,7 @@ describe DataMapper::Property do
|
|
105
124
|
describe '#set' do
|
106
125
|
before do
|
107
126
|
@original_values = {}
|
108
|
-
@resource = mock('resource', :kind_of? => true, :original_values => @original_values)
|
127
|
+
@resource = mock('resource', :kind_of? => true, :original_values => @original_values, :new_record? => true)
|
109
128
|
end
|
110
129
|
|
111
130
|
it 'should typecast the value' do
|
@@ -199,18 +218,56 @@ describe DataMapper::Property do
|
|
199
218
|
property.default_for(resource).should == 'Tomato'
|
200
219
|
end
|
201
220
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
221
|
+
describe "reader and writer visibility" do
|
222
|
+
# parameter passed to Property.new # reader | writer visibility
|
223
|
+
{
|
224
|
+
{} => [:public, :public],
|
225
|
+
{ :accessor => :public } => [:public, :public],
|
226
|
+
{ :accessor => :protected } => [:protected, :protected],
|
227
|
+
{ :accessor => :private } => [:private, :private],
|
228
|
+
{ :reader => :public } => [:public, :public],
|
229
|
+
{ :reader => :protected } => [:protected, :public],
|
230
|
+
{ :reader => :private } => [:private, :public],
|
231
|
+
{ :writer => :public } => [:public, :public],
|
232
|
+
{ :writer => :protected } => [:public, :protected],
|
233
|
+
{ :writer => :private } => [:public, :private],
|
234
|
+
{ :reader => :public, :writer => :public } => [:public, :public],
|
235
|
+
{ :reader => :public, :writer => :protected } => [:public, :protected],
|
236
|
+
{ :reader => :public, :writer => :private } => [:public, :private],
|
237
|
+
{ :reader => :protected, :writer => :public } => [:protected, :public],
|
238
|
+
{ :reader => :protected, :writer => :protected } => [:protected, :protected],
|
239
|
+
{ :reader => :protected, :writer => :private } => [:protected, :private],
|
240
|
+
{ :reader => :private, :writer => :public } => [:private, :public],
|
241
|
+
{ :reader => :private, :writer => :protected } => [:private, :protected],
|
242
|
+
{ :reader => :private, :writer => :private } => [:private, :private],
|
243
|
+
}.each do |input, output|
|
244
|
+
it "#{input.inspect} should make reader #{output[0]} and writer #{output[1]}" do
|
245
|
+
property = DataMapper::Property.new(Tomato, :botanical_name, String, input)
|
246
|
+
property.reader_visibility.should == output[0]
|
247
|
+
property.writer_visibility.should == output[1]
|
248
|
+
end
|
249
|
+
end
|
210
250
|
|
211
|
-
|
212
|
-
|
213
|
-
|
251
|
+
[
|
252
|
+
{ :accessor => :junk },
|
253
|
+
{ :reader => :junk },
|
254
|
+
{ :writer => :junk },
|
255
|
+
{ :reader => :public, :writer => :junk },
|
256
|
+
{ :reader => :protected, :writer => :junk },
|
257
|
+
{ :reader => :private, :writer => :junk },
|
258
|
+
{ :reader => :junk, :writer => :public },
|
259
|
+
{ :reader => :junk, :writer => :protected },
|
260
|
+
{ :reader => :junk, :writer => :private },
|
261
|
+
{ :reader => :junk, :writer => :junk },
|
262
|
+
{ :reader => :junk, :writer => :junk },
|
263
|
+
{ :reader => :junk, :writer => :junk },
|
264
|
+
].each do |input|
|
265
|
+
it "#{input.inspect} should raise ArgumentError" do
|
266
|
+
lambda {
|
267
|
+
property = DataMapper::Property.new(Tomato, :family, String, input)
|
268
|
+
}.should raise_error(ArgumentError)
|
269
|
+
end
|
270
|
+
end
|
214
271
|
end
|
215
272
|
|
216
273
|
it "should return an instance variable name" do
|
@@ -263,8 +320,8 @@ describe DataMapper::Property do
|
|
263
320
|
end
|
264
321
|
|
265
322
|
it "should set the field to the correct field_naming_convention" do
|
266
|
-
DataMapper::Property.new(Zoo, :species, String, {}).field.should == 'species'
|
267
|
-
DataMapper::Property.new(Tomato, :genetic_history, DataMapper::Types::Text, {}).field.should == "genetic_history"
|
323
|
+
DataMapper::Property.new(Zoo, :species, String, {}).field(:default).should == 'species'
|
324
|
+
DataMapper::Property.new(Tomato, :genetic_history, DataMapper::Types::Text, {}).field(:default).should == "genetic_history"
|
268
325
|
end
|
269
326
|
|
270
327
|
it "should provide the primitive mapping" do
|
@@ -340,6 +397,13 @@ describe DataMapper::Property do
|
|
340
397
|
end
|
341
398
|
end
|
342
399
|
|
400
|
+
{ '-8' => -8, '-8.0' => -8, -8 => -8, -8.0 => -8, BigDecimal('8.0') => 8 }.each do |value,expected|
|
401
|
+
it "should typecast #{format(value)} to #{format(expected)} for an Integer property" do
|
402
|
+
property = DataMapper::Property.new(Zoo, :integer, Integer)
|
403
|
+
property.typecast(value).should == expected
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
343
407
|
{ '0' => 0, '0.0' => 0, 0 => 0, 0.0 => 0, BigDecimal('0.0') => 0 }.each do |value,expected|
|
344
408
|
it "should typecast #{format(value)} to #{format(expected)} for an Integer property" do
|
345
409
|
property = DataMapper::Property.new(Zoo, :integer, Integer)
|
@@ -347,6 +411,20 @@ describe DataMapper::Property do
|
|
347
411
|
end
|
348
412
|
end
|
349
413
|
|
414
|
+
{ '5' => 5, '5.0' => 5, 5 => 5, 5.0 => 5, BigDecimal('5.0') => 5 }.each do |value,expected|
|
415
|
+
it "should typecast #{format(value)} to #{format(expected)} for an Integer property" do
|
416
|
+
property = DataMapper::Property.new(Zoo, :integer, Integer)
|
417
|
+
property.typecast(value).should == expected
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
{ 'none' => nil, 'almost 5' => nil, '-3 change' => -3, '9 items' => 9 }.each do |value,expected|
|
422
|
+
it "should typecast #{format(value)} to #{format(expected)} for an Integer property" do
|
423
|
+
property = DataMapper::Property.new(Zoo, :integer, Integer)
|
424
|
+
property.typecast(value).should == expected
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
350
428
|
{ '0' => BigDecimal('0'), '0.0' => BigDecimal('0.0'), 0.0 => BigDecimal('0.0'), BigDecimal('0.0') => BigDecimal('0.0') }.each do |value,expected|
|
351
429
|
it "should typecast #{format(value)} to #{format(expected)} for a BigDecimal property" do
|
352
430
|
property = DataMapper::Property.new(Zoo, :big_decimal, BigDecimal)
|
@@ -434,13 +512,6 @@ describe DataMapper::Property do
|
|
434
512
|
DataMapper::Property.new(Zoo, :name, String).should respond_to(:inspect)
|
435
513
|
end
|
436
514
|
|
437
|
-
it "should use the Repository of its @model" do
|
438
|
-
p = DataMapper::Property.new(Zoo, :name, String)
|
439
|
-
repo = mock("repository")
|
440
|
-
Zoo.should_receive(:repository).and_return(repo)
|
441
|
-
p.repository.should == repo
|
442
|
-
end
|
443
|
-
|
444
515
|
it 'should return an abbreviated representation of the property when inspected' do
|
445
516
|
DataMapper::Property.new(Zoo, :name, String).inspect.should == '#<Property:Zoo:name>'
|
446
517
|
end
|
data/spec/unit/query_spec.rb
CHANGED
@@ -17,8 +17,8 @@ BAD_OPTIONS = {
|
|
17
17
|
:reload => 'true',
|
18
18
|
:offset => -1,
|
19
19
|
:limit => 0,
|
20
|
-
:order => [],
|
21
|
-
:fields => [],
|
20
|
+
# :order => [], # TODO: spec conditions where :order may be empty
|
21
|
+
# :fields => [], # TODO: spec conditions where :fields may be empty
|
22
22
|
:links => [],
|
23
23
|
:includes => [],
|
24
24
|
:conditions => [],
|
@@ -110,7 +110,7 @@ describe DataMapper::Query do
|
|
110
110
|
query.conditions.should == [ [ :eql, Article.properties[:author], 'dkubb' ] ]
|
111
111
|
end
|
112
112
|
|
113
|
-
it 'when a
|
113
|
+
it 'when a Query::Operator object is a key' do
|
114
114
|
query = DataMapper::Query.new(@repository, Article, :author.like => /\Ad(?:an\.)kubb\z/)
|
115
115
|
query.conditions.should == [ [ :like, Article.properties[:author], /\Ad(?:an\.)kubb\z/ ] ]
|
116
116
|
end
|
@@ -161,7 +161,7 @@ describe DataMapper::Query do
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
-
it 'when unknown options use something that is not a
|
164
|
+
it 'when unknown options use something that is not a Query::Operator, Symbol or String is a key' do
|
165
165
|
lambda {
|
166
166
|
DataMapper::Query.new(@repository, Article, nil => nil)
|
167
167
|
}.should raise_error(ArgumentError)
|
@@ -483,3 +483,48 @@ describe DataMapper::Query do
|
|
483
483
|
end
|
484
484
|
end
|
485
485
|
end
|
486
|
+
|
487
|
+
describe DataMapper::Query::Operator do
|
488
|
+
before do
|
489
|
+
@operator = :thing.gte
|
490
|
+
end
|
491
|
+
|
492
|
+
it 'should provide #==' do
|
493
|
+
@operator.should respond_to(:==)
|
494
|
+
end
|
495
|
+
|
496
|
+
describe '#==' do
|
497
|
+
describe 'should be equal' do
|
498
|
+
it 'when other is same object' do
|
499
|
+
@operator.should == @operator
|
500
|
+
end
|
501
|
+
|
502
|
+
it 'when other has the same target and operator' do
|
503
|
+
other = :thing.gte
|
504
|
+
@operator.target.should == other.target
|
505
|
+
@operator.operator.should == other.operator
|
506
|
+
@operator.should == other
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
describe 'should be different' do
|
511
|
+
it 'when other class is not a descendant of self.class' do
|
512
|
+
other = :thing
|
513
|
+
other.class.should_not be_kind_of(@operator.class)
|
514
|
+
@operator.should_not == other
|
515
|
+
end
|
516
|
+
|
517
|
+
it 'when other has a different target' do
|
518
|
+
other = :other.gte
|
519
|
+
@operator.target.should_not == other.target
|
520
|
+
@operator.should_not == other
|
521
|
+
end
|
522
|
+
|
523
|
+
it 'when other has a different operator' do
|
524
|
+
other = :thing.gt
|
525
|
+
@operator.operator.should_not == other.operator
|
526
|
+
@operator.should_not == other
|
527
|
+
end
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
data/spec/unit/resource_spec.rb
CHANGED
@@ -1,5 +1,52 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
2
|
|
3
|
+
# rSpec completely FUBARs everything if you give it a Module here.
|
4
|
+
# So we give it a String of the module name instead.
|
5
|
+
# DO NOT CHANGE THIS!
|
6
|
+
describe "DataMapper::Resource" do
|
7
|
+
|
8
|
+
load_models_for_metaphor :zoo
|
9
|
+
|
10
|
+
describe '#attributes' do
|
11
|
+
it 'should return a hash of attribute-names and values' do
|
12
|
+
zoo = Zoo.new
|
13
|
+
zoo.name = "San Francisco"
|
14
|
+
zoo.description = "This is a pretty awesome zoo"
|
15
|
+
zoo.attributes.should == {
|
16
|
+
:name => "San Francisco", :description => "This is a pretty awesome zoo",
|
17
|
+
:id => nil, :inception => nil, :open => false, :size => nil
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return a hash with all nil values if the instance is new and has no default values" do
|
22
|
+
Species.new.attributes.should == { :id => nil, :name => nil }
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should not include private attributes' do
|
26
|
+
Species.new.attributes.should == { :id => nil, :name => nil }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# ---------- REPOSITORY WRITE METHODS ---------------
|
31
|
+
|
32
|
+
describe '#save' do
|
33
|
+
|
34
|
+
describe 'with a new resource' do
|
35
|
+
it 'should set defaults before create'
|
36
|
+
it 'should create when dirty'
|
37
|
+
it 'should create when non-dirty, and it has a serial key'
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'with an existing resource' do
|
41
|
+
it 'should update'
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# ---------- Old specs... BOOOOOOOOOO ---------------
|
49
|
+
|
3
50
|
class Planet
|
4
51
|
include DataMapper::Resource
|
5
52
|
|
@@ -8,7 +55,7 @@ class Planet
|
|
8
55
|
property :id, Integer, :key => true
|
9
56
|
property :name, String
|
10
57
|
property :age, Integer
|
11
|
-
property :core, String, :
|
58
|
+
property :core, String, :accessor => :private
|
12
59
|
property :type, Discriminator
|
13
60
|
property :data, Object
|
14
61
|
|
@@ -25,9 +72,6 @@ class Planet
|
|
25
72
|
end
|
26
73
|
end
|
27
74
|
|
28
|
-
class Moon
|
29
|
-
end
|
30
|
-
|
31
75
|
class BlackHole
|
32
76
|
include DataMapper::Resource
|
33
77
|
|
@@ -74,54 +118,16 @@ class Banana < Fruit
|
|
74
118
|
property :type, Discriminator
|
75
119
|
end
|
76
120
|
|
121
|
+
class Cyclist
|
122
|
+
include DataMapper::Resource
|
123
|
+
property :id, Integer, :serial => true
|
124
|
+
property :victories, Integer
|
125
|
+
end
|
126
|
+
|
77
127
|
# rSpec completely FUBARs everything if you give it a Module here.
|
78
128
|
# So we give it a String of the module name instead.
|
79
129
|
# DO NOT CHANGE THIS!
|
80
130
|
describe "DataMapper::Resource" do
|
81
|
-
it 'should provide #attribute_get' do
|
82
|
-
Planet.new.should respond_to(:attribute_get)
|
83
|
-
end
|
84
|
-
|
85
|
-
describe '#attribute_get' do
|
86
|
-
it 'should delegate to Property#get' do
|
87
|
-
planet = Planet.new
|
88
|
-
Planet.properties[:age].should_receive(:get).with(planet).and_return(1)
|
89
|
-
planet.age.should == 1
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'should provide #attribute_set' do
|
94
|
-
Planet.new.should respond_to(:attribute_set)
|
95
|
-
end
|
96
|
-
|
97
|
-
describe '#attribute_set' do
|
98
|
-
it 'should typecast the value' do
|
99
|
-
Planet.properties[:age].should_receive(:typecast).with('1').and_return(1)
|
100
|
-
planet = Planet.new
|
101
|
-
planet.age = '1'
|
102
|
-
planet.age.should == 1
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'should delegate to Property#set' do
|
106
|
-
planet = Planet.new
|
107
|
-
Planet.properties[:age].should_receive(:set).with(planet, 1).and_return(1)
|
108
|
-
planet.age = 1
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
describe '#attributes' do
|
113
|
-
it 'should return a hash of attribute-names and values' do
|
114
|
-
vegetable = Vegetable.new
|
115
|
-
vegetable.attributes.should == {:name => nil, :id => nil}
|
116
|
-
vegetable.name = "carot"
|
117
|
-
vegetable.attributes.should == {:name => "carot", :id => nil}
|
118
|
-
end
|
119
|
-
|
120
|
-
it 'should not include private attributes' do
|
121
|
-
hole = BlackHole.new
|
122
|
-
hole.attributes.should == {:id => nil}
|
123
|
-
end
|
124
|
-
end
|
125
131
|
|
126
132
|
it 'should provide #save' do
|
127
133
|
Planet.new.should respond_to(:save)
|
@@ -181,6 +187,46 @@ describe "DataMapper::Resource" do
|
|
181
187
|
|
182
188
|
resource.save.should be_false
|
183
189
|
end
|
190
|
+
|
191
|
+
describe 'for integer fields' do
|
192
|
+
|
193
|
+
it "should save strings without digits as nil" do
|
194
|
+
resource = Cyclist.new
|
195
|
+
resource.victories = "none"
|
196
|
+
resource.save.should be_true
|
197
|
+
resource.victories.should be_nil
|
198
|
+
end
|
199
|
+
|
200
|
+
it "should save strings beginning with non-digits as nil" do
|
201
|
+
resource = Cyclist.new
|
202
|
+
resource.victories = "almost 5"
|
203
|
+
resource.save.should be_true
|
204
|
+
resource.victories.should be_nil
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'should save strings beginning with negative numbers as that number' do
|
208
|
+
resource = Cyclist.new
|
209
|
+
resource.victories = "-4 victories"
|
210
|
+
resource.save.should be_true
|
211
|
+
resource.victories.should == -4
|
212
|
+
end
|
213
|
+
|
214
|
+
it 'should save strings beginning with 0 as 0' do
|
215
|
+
resource = Cyclist.new
|
216
|
+
resource.victories = "0 victories"
|
217
|
+
resource.save.should be_true
|
218
|
+
resource.victories.should == 0
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'should save strings beginning with positive numbers as that number' do
|
222
|
+
resource = Cyclist.new
|
223
|
+
resource.victories = "23 victories"
|
224
|
+
resource.save.should be_true
|
225
|
+
resource.victories.should == 23
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
184
230
|
end
|
185
231
|
|
186
232
|
describe 'with an existing resource' do
|
@@ -245,7 +291,7 @@ describe "DataMapper::Resource" do
|
|
245
291
|
end
|
246
292
|
|
247
293
|
it "should return an instance of the created object" do
|
248
|
-
Planet.create
|
294
|
+
Planet.create(:name => 'Venus', :age => 1_000_000, :id => 42).should be_a_kind_of(Planet)
|
249
295
|
end
|
250
296
|
|
251
297
|
it 'should provide persistance methods' do
|
@@ -256,31 +302,47 @@ describe "DataMapper::Resource" do
|
|
256
302
|
end
|
257
303
|
|
258
304
|
it "should have attributes" do
|
259
|
-
attributes = { :name => 'Jupiter', :age => 1_000_000, :
|
305
|
+
attributes = { :name => 'Jupiter', :age => 1_000_000, :id => 42, :type => Planet, :data => nil }
|
260
306
|
jupiter = Planet.new(attributes)
|
261
307
|
jupiter.attributes.should == attributes
|
262
308
|
end
|
263
309
|
|
264
310
|
it "should be able to set attributes" do
|
265
|
-
attributes = { :name => 'Jupiter', :age => 1_000_000, :
|
311
|
+
attributes = { :name => 'Jupiter', :age => 1_000_000, :id => 42, :type => Planet, :data => nil }
|
266
312
|
jupiter = Planet.new(attributes)
|
267
313
|
jupiter.attributes.should == attributes
|
268
|
-
|
314
|
+
|
315
|
+
new_attributes = attributes.merge( :age => 2_500_000 )
|
316
|
+
jupiter.attributes = new_attributes
|
317
|
+
jupiter.attributes.should == new_attributes
|
318
|
+
end
|
319
|
+
|
320
|
+
it "should be able to set attributes using update_attributes" do
|
321
|
+
attributes = { :name => 'Jupiter', :age => 1_000_000, :id => 42, :type => Planet, :data => nil }
|
322
|
+
jupiter = Planet.new(attributes)
|
269
323
|
jupiter.attributes.should == attributes
|
270
324
|
|
271
|
-
|
272
|
-
jupiter.
|
273
|
-
jupiter.
|
325
|
+
new_age = { :age => 3_700_000 }
|
326
|
+
jupiter.update_attributes(new_age).should be_true
|
327
|
+
jupiter.age.should == 3_700_000
|
328
|
+
jupiter.attributes.should == attributes.merge(new_age)
|
329
|
+
end
|
330
|
+
|
331
|
+
# :core is a private accessor so Ruby should raise NameError
|
332
|
+
it "should not be able to set private attributes" do
|
333
|
+
lambda {
|
334
|
+
jupiter = Planet.new({ :core => "Molten Metal" })
|
335
|
+
}.should raise_error(NameError)
|
274
336
|
end
|
275
337
|
|
276
|
-
it "should not mark attributes dirty if
|
277
|
-
jupiter = Planet.new(:name => 'Jupiter', :age => 1_000_000, :
|
338
|
+
it "should not mark attributes dirty if they are similar after update" do
|
339
|
+
jupiter = Planet.new(:name => 'Jupiter', :age => 1_000_000, :id => 42, :data => { :a => "Yeah!" })
|
278
340
|
jupiter.save.should be_true
|
279
341
|
|
280
342
|
# discriminator will be set automatically
|
281
343
|
jupiter.type.should == Planet
|
282
344
|
|
283
|
-
jupiter.attributes = { :name => 'Jupiter', :age => 1_000_000, :
|
345
|
+
jupiter.attributes = { :name => 'Jupiter', :age => 1_000_000, :data => { :a => "Yeah!" } }
|
284
346
|
|
285
347
|
jupiter.attribute_dirty?(:name).should be_false
|
286
348
|
jupiter.attribute_dirty?(:age).should be_false
|
@@ -291,7 +353,7 @@ describe "DataMapper::Resource" do
|
|
291
353
|
end
|
292
354
|
|
293
355
|
it "should not mark attributes dirty if they are similar after typecasting" do
|
294
|
-
jupiter = Planet.new(:name => 'Jupiter', :age => 1_000_000, :
|
356
|
+
jupiter = Planet.new(:name => 'Jupiter', :age => 1_000_000, :id => 42, :type => nil)
|
295
357
|
jupiter.save.should be_true
|
296
358
|
jupiter.dirty?.should be_false
|
297
359
|
|
@@ -378,7 +440,7 @@ describe "DataMapper::Resource" do
|
|
378
440
|
|
379
441
|
it 'should store and retrieve default values' do
|
380
442
|
Planet.property(:satellite_count, Integer, :default => 0)
|
381
|
-
# stupid example but it's
|
443
|
+
# stupid example but it's reliable and works
|
382
444
|
Planet.property(:orbit_period, Float, :default => lambda { |r,p| p.name.to_s.length })
|
383
445
|
earth = Planet.new(:name => 'Earth')
|
384
446
|
earth.satellite_count.should == 0
|