dm-core 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|