dm-core 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/.autotest +29 -0
  2. data/.document +5 -0
  3. data/.gitignore +27 -0
  4. data/LICENSE +20 -0
  5. data/{README.txt → README.rdoc} +14 -3
  6. data/Rakefile +23 -22
  7. data/VERSION +1 -0
  8. data/dm-core.gemspec +201 -10
  9. data/lib/dm-core.rb +32 -23
  10. data/lib/dm-core/adapters.rb +0 -1
  11. data/lib/dm-core/adapters/data_objects_adapter.rb +230 -151
  12. data/lib/dm-core/adapters/mysql_adapter.rb +7 -8
  13. data/lib/dm-core/adapters/oracle_adapter.rb +39 -59
  14. data/lib/dm-core/adapters/postgres_adapter.rb +0 -1
  15. data/lib/dm-core/adapters/sqlite3_adapter.rb +5 -0
  16. data/lib/dm-core/adapters/sqlserver_adapter.rb +114 -0
  17. data/lib/dm-core/adapters/yaml_adapter.rb +0 -5
  18. data/lib/dm-core/associations/many_to_many.rb +118 -56
  19. data/lib/dm-core/associations/many_to_one.rb +48 -21
  20. data/lib/dm-core/associations/one_to_many.rb +8 -30
  21. data/lib/dm-core/associations/one_to_one.rb +1 -5
  22. data/lib/dm-core/associations/relationship.rb +89 -97
  23. data/lib/dm-core/collection.rb +299 -184
  24. data/lib/dm-core/core_ext/enumerable.rb +28 -0
  25. data/lib/dm-core/core_ext/kernel.rb +0 -2
  26. data/lib/dm-core/migrations.rb +314 -170
  27. data/lib/dm-core/model.rb +97 -66
  28. data/lib/dm-core/model/descendant_set.rb +1 -1
  29. data/lib/dm-core/model/hook.rb +0 -3
  30. data/lib/dm-core/model/property.rb +7 -10
  31. data/lib/dm-core/model/relationship.rb +79 -26
  32. data/lib/dm-core/model/scope.rb +3 -4
  33. data/lib/dm-core/property.rb +152 -90
  34. data/lib/dm-core/property_set.rb +18 -37
  35. data/lib/dm-core/query.rb +452 -153
  36. data/lib/dm-core/query/conditions/comparison.rb +266 -173
  37. data/lib/dm-core/query/conditions/operation.rb +499 -57
  38. data/lib/dm-core/query/direction.rb +0 -3
  39. data/lib/dm-core/query/operator.rb +0 -4
  40. data/lib/dm-core/query/path.rb +10 -12
  41. data/lib/dm-core/query/sort.rb +4 -10
  42. data/lib/dm-core/repository.rb +10 -6
  43. data/lib/dm-core/resource.rb +343 -148
  44. data/lib/dm-core/spec/adapter_shared_spec.rb +17 -1
  45. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +277 -17
  46. data/lib/dm-core/support/chainable.rb +0 -2
  47. data/lib/dm-core/support/equalizer.rb +27 -3
  48. data/lib/dm-core/transaction.rb +75 -75
  49. data/lib/dm-core/type.rb +19 -5
  50. data/lib/dm-core/types/discriminator.rb +4 -4
  51. data/lib/dm-core/types/object.rb +2 -7
  52. data/lib/dm-core/types/paranoid_boolean.rb +8 -2
  53. data/lib/dm-core/types/paranoid_datetime.rb +8 -2
  54. data/lib/dm-core/version.rb +1 -1
  55. data/script/performance.rb +7 -7
  56. data/script/profile.rb +6 -6
  57. data/spec/lib/collection_helpers.rb +2 -2
  58. data/spec/lib/pending_helpers.rb +22 -3
  59. data/spec/lib/rspec_immediate_feedback_formatter.rb +1 -0
  60. data/spec/public/associations/many_to_many_spec.rb +6 -4
  61. data/spec/public/associations/many_to_one_spec.rb +10 -1
  62. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +39 -0
  63. data/spec/public/associations/one_to_many_spec.rb +4 -3
  64. data/spec/public/associations/one_to_one_spec.rb +19 -1
  65. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +45 -0
  66. data/spec/public/collection_spec.rb +4 -3
  67. data/spec/public/migrations_spec.rb +144 -0
  68. data/spec/public/model/relationship_spec.rb +115 -55
  69. data/spec/public/model_spec.rb +13 -13
  70. data/spec/public/property/object_spec.rb +106 -0
  71. data/spec/public/property_spec.rb +18 -14
  72. data/spec/public/resource_spec.rb +10 -1
  73. data/spec/public/sel_spec.rb +16 -49
  74. data/spec/public/setup_spec.rb +1 -1
  75. data/spec/public/shared/association_collection_shared_spec.rb +6 -14
  76. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  77. data/spec/public/shared/collection_shared_spec.rb +214 -217
  78. data/spec/public/shared/finder_shared_spec.rb +259 -365
  79. data/spec/public/shared/resource_shared_spec.rb +524 -248
  80. data/spec/public/transaction_spec.rb +27 -3
  81. data/spec/public/types/discriminator_spec.rb +1 -1
  82. data/spec/rcov.opts +6 -0
  83. data/spec/semipublic/adapters/sqlserver_adapter_spec.rb +17 -0
  84. data/spec/semipublic/associations/many_to_one_spec.rb +3 -20
  85. data/spec/semipublic/associations_spec.rb +2 -2
  86. data/spec/semipublic/collection_spec.rb +0 -32
  87. data/spec/semipublic/model_spec.rb +96 -0
  88. data/spec/semipublic/property_spec.rb +3 -3
  89. data/spec/semipublic/query/conditions/comparison_spec.rb +1719 -0
  90. data/spec/semipublic/query/conditions/operation_spec.rb +1292 -0
  91. data/spec/semipublic/query_spec.rb +1285 -144
  92. data/spec/semipublic/resource_spec.rb +0 -24
  93. data/spec/semipublic/shared/resource_shared_spec.rb +103 -38
  94. data/spec/spec.opts +1 -1
  95. data/spec/spec_helper.rb +15 -6
  96. data/tasks/ci.rake +1 -0
  97. data/tasks/metrics.rake +37 -0
  98. data/tasks/spec.rake +41 -0
  99. data/tasks/yard.rake +9 -0
  100. data/tasks/yardstick.rake +19 -0
  101. metadata +99 -29
  102. data/CONTRIBUTING +0 -51
  103. data/FAQ +0 -93
  104. data/History.txt +0 -27
  105. data/MIT-LICENSE +0 -22
  106. data/Manifest.txt +0 -121
  107. data/QUICKLINKS +0 -11
  108. data/SPECS +0 -35
  109. data/TODO +0 -1
  110. data/spec/semipublic/query/conditions_spec.rb +0 -528
  111. data/tasks/ci.rb +0 -24
  112. data/tasks/dm.rb +0 -58
  113. data/tasks/doc.rb +0 -17
  114. data/tasks/gemspec.rb +0 -23
  115. data/tasks/hoe.rb +0 -45
  116. data/tasks/install.rb +0 -18
@@ -12,7 +12,10 @@ describe 'One to One Associations' do
12
12
  property :description, Text
13
13
  property :admin, Boolean, :accessor => :private
14
14
 
15
- belongs_to :referrer, self, :nullable => true
15
+ belongs_to :parent, self, :required => false
16
+ has n, :children, self, :inverse => :parent
17
+
18
+ belongs_to :referrer, self, :required => false
16
19
  belongs_to :comment
17
20
 
18
21
  # TODO: remove this after Relationship#inverse can dynamically
@@ -50,6 +53,12 @@ describe 'One to One Associations' do
50
53
  end
51
54
  end
52
55
 
56
+ class ::Default
57
+ include DataMapper::Resource
58
+
59
+ property :name, String, :key => true, :default => 'a default value'
60
+ end
61
+
53
62
  @user_model = Blog::User
54
63
  @author_model = Blog::Author
55
64
  @comment_model = Blog::Comment
@@ -93,6 +102,9 @@ describe 'One to One Through Associations' do
93
102
  property :description, Text
94
103
  property :admin, Boolean, :accessor => :private
95
104
 
105
+ belongs_to :parent, self, :required => false
106
+ has n, :children, self, :inverse => :parent
107
+
96
108
  has 1, :referral_from, Referral, :child_key => [ :referree_name ]
97
109
  has 1, :referral_to, Referral, :child_key => [ :referrer_name ]
98
110
 
@@ -131,6 +143,12 @@ describe 'One to One Through Associations' do
131
143
  end
132
144
  end
133
145
 
146
+ class ::Default
147
+ include DataMapper::Resource
148
+
149
+ property :name, String, :key => true, :default => 'a default value'
150
+ end
151
+
134
152
  @referral_model = Blog::Referral
135
153
  @user_model = Blog::User
136
154
  @author_model = Blog::Author
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ # TODO: combine this into one_to_one_spec.rb
4
+
5
+ describe 'One to One Associations when foreign key is part of a composite key and contains a boolean, with an integer and a boolean making up the composite key' do
6
+ before :all do
7
+ class ::ParentModel
8
+ include DataMapper::Resource
9
+
10
+ property :integer_key, Integer, :key => true
11
+ property :boolean_key, Boolean, :key => true
12
+
13
+ has 1, :child_model, :child_key => [ :integer_key, :boolean_key ]
14
+ end
15
+
16
+ class ::ChildModel
17
+ include DataMapper::Resource
18
+
19
+ property :integer_key, Integer, :key => true
20
+ property :other_integer_key, Integer, :key => true
21
+ property :boolean_key, Boolean, :key => true
22
+
23
+ belongs_to :parent_model, :child_key => [ :integer_key, :boolean_key ]
24
+ end
25
+ end
26
+
27
+ supported_by :all do
28
+ before :all do
29
+ @parent = ParentModel.create(:integer_key => 1, :boolean_key => false)
30
+ @child = ChildModel.create(:integer_key => 1, :other_integer_key => 1, :boolean_key => false)
31
+ end
32
+
33
+ it 'should be able to access the child' do
34
+ @parent.child_model.should == @child
35
+ end
36
+
37
+ it 'should be able to access the parent' do
38
+ @child.parent_model.should == @parent
39
+ end
40
+
41
+ it 'should be able to access the parent_key' do
42
+ @child.parent_model.key.should_not be_nil
43
+ end
44
+ end
45
+ end
@@ -13,12 +13,12 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
13
13
  include DataMapper::Resource
14
14
 
15
15
  property :id, Serial
16
- property :title, String, :nullable => false
16
+ property :title, String, :required => true
17
17
  property :content, Text
18
18
  property :subtitle, String
19
- property :author, String, :nullable => false
19
+ property :author, String, :required => true
20
20
 
21
- belongs_to :original, self, :nullable => true
21
+ belongs_to :original, self, :required => false
22
22
  has n, :revisions, self, :child_key => [ :original_id ]
23
23
  has 1, :previous, self, :child_key => [ :original_id ], :order => [ :id.desc ]
24
24
  has n, :publications, :through => Resource
@@ -60,6 +60,7 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
60
60
  it_should_behave_like 'A public Collection'
61
61
  it_should_behave_like 'A Collection supporting Strategic Eager Loading'
62
62
  it_should_behave_like 'Finder Interface'
63
+ it_should_behave_like 'Collection Finder Interface'
63
64
  end
64
65
  end
65
66
  end
@@ -243,6 +243,38 @@ describe DataMapper::Migrations do
243
243
  end
244
244
  end
245
245
  end
246
+
247
+ describe 'String property' do
248
+ before :all do
249
+ @model.property(:id, DataMapper::Types::Serial)
250
+ end
251
+
252
+ [
253
+ [ 1, 'VARCHAR(1)' ],
254
+ [ 50, 'VARCHAR(50)' ],
255
+ [ 255, 'VARCHAR(255)' ],
256
+ [ nil, 'VARCHAR(50)' ],
257
+ ].each do |length, statement|
258
+ options = {}
259
+ options[:length] = length if length
260
+
261
+ describe "with a length of #{length}" do
262
+ before :all do
263
+ @property = @model.property(:title, String, options)
264
+
265
+ @response = capture_log(DataObjects::Mysql) { @model.auto_migrate! }
266
+ end
267
+
268
+ it 'should return true' do
269
+ @response.should be_true
270
+ end
271
+
272
+ it "should create a #{statement} column" do
273
+ @output.last.should =~ %r{\ACREATE TABLE `blog_articles` \(`id` INT\(10\) UNSIGNED NOT NULL AUTO_INCREMENT, `title` #{Regexp.escape(statement)}, PRIMARY KEY\(`id`\)\) ENGINE = InnoDB CHARACTER SET [a-z\d]+ COLLATE (?:[a-z\d](?:_?[a-z\d]+)*)\z}
274
+ end
275
+ end
276
+ end
277
+ end
246
278
  end
247
279
  end
248
280
 
@@ -354,6 +386,118 @@ describe DataMapper::Migrations do
354
386
  end
355
387
  end
356
388
  end
389
+
390
+ describe 'String property' do
391
+ before :all do
392
+ @model.property(:id, DataMapper::Types::Serial)
393
+ end
394
+
395
+ [
396
+ [ 1, 'VARCHAR(1)' ],
397
+ [ 50, 'VARCHAR(50)' ],
398
+ [ 255, 'VARCHAR(255)' ],
399
+ [ nil, 'VARCHAR(50)' ],
400
+ ].each do |length, statement|
401
+ options = {}
402
+ options[:length] = length if length
403
+
404
+ describe "with a length of #{length}" do
405
+ before :all do
406
+ @property = @model.property(:title, String, options)
407
+
408
+ @response = capture_log(DataObjects::Postgres) { @model.auto_migrate! }
409
+ end
410
+
411
+ it 'should return true' do
412
+ @response.should be_true
413
+ end
414
+
415
+ it "should create a #{statement} column" do
416
+ @output[-2].should == "CREATE TABLE \"blog_articles\" (\"id\" SERIAL NOT NULL, \"title\" #{statement}, PRIMARY KEY(\"id\"))"
417
+ end
418
+ end
419
+ end
420
+ end
421
+ end
422
+ end
423
+
424
+ supported_by :sqlserver do
425
+ before :all do
426
+ module ::Blog
427
+ class Article
428
+ include DataMapper::Resource
429
+ end
430
+ end
431
+
432
+ @model = ::Blog::Article
433
+ end
434
+
435
+ describe '#auto_migrate' do
436
+ describe 'Integer property' do
437
+ [
438
+ [ 0, 1, 'TINYINT' ],
439
+ [ 0, 255, 'TINYINT' ],
440
+ [ 0, 256, 'SMALLINT' ],
441
+ [ 0, 32767, 'SMALLINT' ],
442
+ [ 0, 32768, 'INT' ],
443
+ [ 0, 2147483647, 'INT' ],
444
+ [ 0, 2147483648, 'BIGINT' ],
445
+ [ 0, 9223372036854775807, 'BIGINT' ],
446
+
447
+ [ -1, 1, 'SMALLINT' ],
448
+ [ -1, 255, 'SMALLINT' ],
449
+ [ -1, 256, 'SMALLINT' ],
450
+ [ -1, 32767, 'SMALLINT' ],
451
+ [ -1, 32768, 'INT' ],
452
+ [ -1, 2147483647, 'INT' ],
453
+ [ -1, 2147483648, 'BIGINT' ],
454
+ [ -1, 9223372036854775807, 'BIGINT' ],
455
+
456
+ [ -1, 0, 'SMALLINT' ],
457
+ [ -32768, 0, 'SMALLINT' ],
458
+ [ -32769, 0, 'INT' ],
459
+ [ -2147483648, 0, 'INT' ],
460
+ [ -2147483649, 0, 'BIGINT' ],
461
+ [ -9223372036854775808, 0, 'BIGINT' ],
462
+
463
+ [ nil, 2147483647, 'INT' ],
464
+ [ 0, nil, 'INT' ],
465
+ [ nil, nil, 'INTEGER' ],
466
+ ].each do |min, max, statement|
467
+ options = { :key => true }
468
+ options[:min] = min if min
469
+ options[:max] = max if max
470
+
471
+ describe "with a min of #{min} and a max of #{max}" do
472
+ before :all do
473
+ @property = @model.property(:id, Integer, options)
474
+
475
+ @response = capture_log(DataObjects::Sqlserver) { @model.auto_migrate! }
476
+ end
477
+
478
+ it 'should return true' do
479
+ @response.should be_true
480
+ end
481
+
482
+ it "should create a #{statement} column" do
483
+ @output.last.should == "CREATE TABLE \"blog_articles\" (\"id\" #{statement} NOT NULL, PRIMARY KEY(\"id\"))"
484
+ end
485
+
486
+ options.only(:min, :max).each do |key, value|
487
+ it "should allow the #{key} value #{value} to be stored" do
488
+ lambda {
489
+ resource = @model.create(@property => value)
490
+ @model.first(@property => value).should eql(resource)
491
+ }.should_not raise_error
492
+ end
493
+ end
494
+ end
495
+ end
496
+ end
497
+
498
+ describe 'String property' do
499
+ it 'needs specs'
500
+ end
357
501
  end
358
502
  end
359
503
  end
@@ -5,7 +5,7 @@ share_examples_for 'it creates a one accessor' do
5
5
  describe 'when there is no associated resource' do
6
6
  describe 'without a query' do
7
7
  before :all do
8
- @return = @car.send(@name)
8
+ @return = @car.__send__(@name)
9
9
  end
10
10
 
11
11
  it 'should return nil' do
@@ -15,7 +15,7 @@ share_examples_for 'it creates a one accessor' do
15
15
 
16
16
  describe 'with a query' do
17
17
  before :all do
18
- @return = @car.send(@name, :id => 99)
18
+ @return = @car.__send__(@name, :id => 99)
19
19
  end
20
20
 
21
21
  it 'should return nil' do
@@ -27,12 +27,12 @@ share_examples_for 'it creates a one accessor' do
27
27
  describe 'when there is an associated resource' do
28
28
  before :all do
29
29
  @expected = @model.new
30
- @car.send("#{@name}=", @expected)
30
+ @car.__send__("#{@name}=", @expected)
31
31
  end
32
32
 
33
33
  describe 'without a query' do
34
34
  before :all do
35
- @return = @car.send(@name)
35
+ @return = @car.__send__(@name)
36
36
  end
37
37
 
38
38
  it 'should return a Resource' do
@@ -50,7 +50,7 @@ share_examples_for 'it creates a one accessor' do
50
50
 
51
51
  @expected.id.should_not be_nil
52
52
 
53
- @return = @car.send(@name, :id => @expected.id)
53
+ @return = @car.__send__(@name, :id => @expected.id)
54
54
  end
55
55
 
56
56
  it 'should return a Resource' do
@@ -66,13 +66,13 @@ share_examples_for 'it creates a one accessor' do
66
66
  describe 'when the target model is scoped' do
67
67
  before :all do
68
68
  @resource = @model.new
69
- @car.send("#{@name}=", @resource)
69
+ @car.__send__("#{@name}=", @resource)
70
70
  @car.save
71
71
 
72
72
  # set the model scope to not match the expected resource
73
73
  @model.default_scope.update(:id.not => @resource.id)
74
74
 
75
- @return = @car.model.get(*@car.key).send(@name)
75
+ @return = @car.model.get(*@car.key).__send__(@name)
76
76
  end
77
77
 
78
78
  it 'should return nil' do
@@ -88,7 +88,7 @@ share_examples_for 'it creates a one mutator' do
88
88
  before :all do
89
89
  @expected = @model.new
90
90
 
91
- @return = @car.send("#{@name}=", @expected)
91
+ @return = @car.__send__("#{@name}=", @expected)
92
92
  end
93
93
 
94
94
  it 'should return the expected Resource' do
@@ -96,7 +96,7 @@ share_examples_for 'it creates a one mutator' do
96
96
  end
97
97
 
98
98
  it 'should set the Resource' do
99
- @car.send(@name).should equal(@expected)
99
+ @car.__send__(@name).should equal(@expected)
100
100
  end
101
101
 
102
102
  it 'should relate associated Resource' do
@@ -104,14 +104,14 @@ share_examples_for 'it creates a one mutator' do
104
104
  many_to_one = relationship.kind_of?(DataMapper::Associations::ManyToOne::Relationship)
105
105
  one_to_one_through = relationship.kind_of?(DataMapper::Associations::OneToOne::Relationship) && relationship.respond_to?(:through)
106
106
 
107
- pending_if 'TODO', many_to_one || one_to_one_through do
107
+ pending_if many_to_one || one_to_one_through do
108
108
  @expected.car.should == @car
109
109
  end
110
110
  end
111
111
 
112
112
  it 'should persist the Resource' do
113
113
  @car.save.should be_true
114
- @car.model.get(*@car.key).send(@name).should == @expected
114
+ @car.model.get(*@car.key).__send__(@name).should == @expected
115
115
  end
116
116
 
117
117
  it 'should persist the associated Resource' do
@@ -123,12 +123,12 @@ share_examples_for 'it creates a one mutator' do
123
123
 
124
124
  describe 'when setting a Hash' do
125
125
  before :all do
126
- @car.send("#{@name}=", @model.new)
126
+ @car.__send__("#{@name}=", @model.new)
127
127
 
128
128
  attributes = { :id => 10 }
129
129
  @expected = @model.new(attributes)
130
130
 
131
- @return = @car.send("#{@name}=", attributes)
131
+ @return = @car.__send__("#{@name}=", attributes)
132
132
  end
133
133
 
134
134
  it 'should return the expected Resource' do
@@ -136,7 +136,7 @@ share_examples_for 'it creates a one mutator' do
136
136
  end
137
137
 
138
138
  it 'should set the Resource' do
139
- @car.send(@name).should equal(@return)
139
+ @car.__send__(@name).should equal(@return)
140
140
  end
141
141
 
142
142
  it 'should relate associated Resource' do
@@ -144,14 +144,14 @@ share_examples_for 'it creates a one mutator' do
144
144
  many_to_one = relationship.kind_of?(DataMapper::Associations::ManyToOne::Relationship)
145
145
  one_to_one_through = relationship.kind_of?(DataMapper::Associations::OneToOne::Relationship) && relationship.respond_to?(:through)
146
146
 
147
- pending_if 'TODO', many_to_one || one_to_one_through do
147
+ pending_if many_to_one || one_to_one_through do
148
148
  @return.car.should == @car
149
149
  end
150
150
  end
151
151
 
152
152
  it 'should persist the Resource' do
153
153
  @car.save.should be_true
154
- @car.model.get(*@car.key).send(@name).should == @return
154
+ @car.model.get(*@car.key).__send__(@name).should == @return
155
155
  end
156
156
 
157
157
  it 'should persist the associated Resource' do
@@ -163,9 +163,9 @@ share_examples_for 'it creates a one mutator' do
163
163
 
164
164
  describe 'when setting nil' do
165
165
  before :all do
166
- @car.send("#{@name}=", @model.new)
166
+ @car.__send__("#{@name}=", @model.new)
167
167
 
168
- @return = @car.send("#{@name}=", nil)
168
+ @return = @car.__send__("#{@name}=", nil)
169
169
  end
170
170
 
171
171
  it 'should return nil' do
@@ -173,21 +173,21 @@ share_examples_for 'it creates a one mutator' do
173
173
  end
174
174
 
175
175
  it 'should set nil' do
176
- @car.send(@name).should be_nil
176
+ @car.__send__(@name).should be_nil
177
177
  end
178
178
 
179
179
  it 'should persist as nil' do
180
180
  @car.save.should be_true
181
- @car.model.get(*@car.key).send(@name).should be_nil
181
+ @car.model.get(*@car.key).__send__(@name).should be_nil
182
182
  end
183
183
  end
184
184
 
185
185
  describe 'when changing the Resource' do
186
186
  before :all do
187
- @car.send("#{@name}=", @model.new)
187
+ @car.__send__("#{@name}=", @model.new)
188
188
  @expected = @model.new
189
189
 
190
- @return = @car.send("#{@name}=", @expected)
190
+ @return = @car.__send__("#{@name}=", @expected)
191
191
  end
192
192
 
193
193
  it 'should return the expected Resource' do
@@ -195,7 +195,7 @@ share_examples_for 'it creates a one mutator' do
195
195
  end
196
196
 
197
197
  it 'should set the Resource' do
198
- @car.send(@name).should equal(@expected)
198
+ @car.__send__(@name).should equal(@expected)
199
199
  end
200
200
 
201
201
  it 'should relate associated Resource' do
@@ -210,7 +210,7 @@ share_examples_for 'it creates a one mutator' do
210
210
 
211
211
  it 'should persist the Resource' do
212
212
  @car.save.should be_true
213
- @car.model.get(*@car.key).send(@name).should == @expected
213
+ @car.model.get(*@car.key).__send__(@name).should == @expected
214
214
  end
215
215
 
216
216
  it 'should persist the associated Resource' do
@@ -227,7 +227,7 @@ share_examples_for 'it creates a many accessor' do
227
227
  describe 'when there is no child resource and the source is saved' do
228
228
  before :all do
229
229
  @car.save.should be_true
230
- @return = @car.send(@name)
230
+ @return = @car.__send__(@name)
231
231
  end
232
232
 
233
233
  it 'should return a Collection' do
@@ -241,7 +241,7 @@ share_examples_for 'it creates a many accessor' do
241
241
 
242
242
  describe 'when there is no child resource and the source is not saved' do
243
243
  before :all do
244
- @return = @car.send(@name)
244
+ @return = @car.__send__(@name)
245
245
  end
246
246
 
247
247
  it 'should return a Collection' do
@@ -258,9 +258,9 @@ share_examples_for 'it creates a many accessor' do
258
258
  @return = nil
259
259
 
260
260
  @expected = @model.new
261
- @car.send("#{@name}=", [ @expected ])
261
+ @car.__send__("#{@name}=", [ @expected ])
262
262
 
263
- @return = @car.send(@name)
263
+ @return = @car.__send__(@name)
264
264
  end
265
265
 
266
266
  it 'should return a Collection' do
@@ -274,15 +274,15 @@ share_examples_for 'it creates a many accessor' do
274
274
 
275
275
  describe 'when the target model is scoped' do
276
276
  before :all do
277
- 2.times { @car.send(@name).new }
277
+ 2.times { @car.__send__(@name).new }
278
278
  @car.save
279
279
 
280
- @expected = @car.send(@name).first
280
+ @expected = @car.__send__(@name).first
281
281
 
282
282
  # set the model scope to only return the first record
283
283
  @model.default_scope.update(@model.key(@repository.name).zip(@expected.key).to_hash)
284
284
 
285
- @return = @car.model.get(*@car.key).send(@name)
285
+ @return = @car.model.get(*@car.key).__send__(@name)
286
286
  end
287
287
 
288
288
  it 'should return a Collection' do
@@ -302,7 +302,7 @@ share_examples_for 'it creates a many mutator' do
302
302
  before :all do
303
303
  @expected = [ @model.new ]
304
304
 
305
- @return = @car.send("#{@name}=", @expected)
305
+ @return = @car.__send__("#{@name}=", @expected)
306
306
  end
307
307
 
308
308
  it 'should return the expected Collection' do
@@ -310,19 +310,19 @@ share_examples_for 'it creates a many mutator' do
310
310
  end
311
311
 
312
312
  it 'should set the Collection' do
313
- @car.send(@name).should == @expected
314
- @car.send(@name).zip(@expected) { |value, expected| value.should equal(expected) }
313
+ @car.__send__(@name).should == @expected
314
+ @car.__send__(@name).zip(@expected) { |value, expected| value.should equal(expected) }
315
315
  end
316
316
 
317
317
  it 'should relate the associated Collection' do
318
- pending_if 'TODO', Car.relationships[@name].kind_of?(DataMapper::Associations::ManyToMany::Relationship) do
318
+ pending_if Car.relationships[@name].kind_of?(DataMapper::Associations::ManyToMany::Relationship) do
319
319
  @expected.each { |resource| resource.car.should == @car }
320
320
  end
321
321
  end
322
322
 
323
323
  it 'should persist the Collection' do
324
324
  @car.save.should be_true
325
- @car.model.get(*@car.key).send(@name).should == @expected
325
+ @car.model.get(*@car.key).__send__(@name).should == @expected
326
326
  end
327
327
 
328
328
  it 'should persist the associated Resource' do
@@ -338,7 +338,7 @@ share_examples_for 'it creates a many mutator' do
338
338
  @hashes = [ attributes ]
339
339
  @expected = [ @model.new(attributes) ]
340
340
 
341
- @return = @car.send("#{@name}=", @hashes)
341
+ @return = @car.__send__("#{@name}=", @hashes)
342
342
  end
343
343
 
344
344
  it 'should return the expected Collection' do
@@ -346,18 +346,18 @@ share_examples_for 'it creates a many mutator' do
346
346
  end
347
347
 
348
348
  it 'should set the Collection' do
349
- @car.send(@name).should == @return
349
+ @car.__send__(@name).should == @return
350
350
  end
351
351
 
352
352
  it 'should relate the associated Collection' do
353
- pending_if 'TODO', Car.relationships[@name].kind_of?(DataMapper::Associations::ManyToMany::Relationship) do
353
+ pending_if Car.relationships[@name].kind_of?(DataMapper::Associations::ManyToMany::Relationship) do
354
354
  @return.each { |resource| resource.car.should == @car }
355
355
  end
356
356
  end
357
357
 
358
358
  it 'should persist the Collection' do
359
359
  @car.save.should be_true
360
- @car.model.get(*@car.key).send(@name).should == @return
360
+ @car.model.get(*@car.key).__send__(@name).should == @return
361
361
  end
362
362
 
363
363
  it 'should persist the associated Resource' do
@@ -369,9 +369,9 @@ share_examples_for 'it creates a many mutator' do
369
369
 
370
370
  describe 'when setting an empty collection' do
371
371
  before :all do
372
- @car.send("#{@name}=", [ @model.new ])
372
+ @car.__send__("#{@name}=", [ @model.new ])
373
373
 
374
- @return = @car.send("#{@name}=", [])
374
+ @return = @car.__send__("#{@name}=", [])
375
375
  end
376
376
 
377
377
  it 'should return a Collection' do
@@ -379,22 +379,22 @@ share_examples_for 'it creates a many mutator' do
379
379
  end
380
380
 
381
381
  it 'should set an empty Collection' do
382
- @car.send(@name).should be_empty
382
+ @car.__send__(@name).should be_empty
383
383
  end
384
384
 
385
385
  it 'should persist as an empty Collection' do
386
386
  @car.save.should be_true
387
- @car.model.get(*@car.key).send(@name).should be_empty
387
+ @car.model.get(*@car.key).__send__(@name).should be_empty
388
388
  end
389
389
  end
390
390
 
391
391
  describe 'when changing an associated collection' do
392
392
  before :all do
393
- @car.send("#{@name}=", [ @model.new ])
393
+ @car.__send__("#{@name}=", [ @model.new ])
394
394
 
395
395
  @expected = [ @model.new ]
396
396
 
397
- @return = @car.send("#{@name}=", @expected)
397
+ @return = @car.__send__("#{@name}=", @expected)
398
398
  end
399
399
 
400
400
  it 'should return the expected Resource' do
@@ -402,19 +402,19 @@ share_examples_for 'it creates a many mutator' do
402
402
  end
403
403
 
404
404
  it 'should set the Resource' do
405
- @car.send(@name).should == @expected
406
- @car.send(@name).zip(@expected) { |value, expected| value.should equal(expected) }
405
+ @car.__send__(@name).should == @expected
406
+ @car.__send__(@name).zip(@expected) { |value, expected| value.should equal(expected) }
407
407
  end
408
408
 
409
409
  it 'should relate associated Resource' do
410
- pending_if 'TODO', Car.relationships[@name].kind_of?(DataMapper::Associations::ManyToMany::Relationship) do
410
+ pending_if Car.relationships[@name].kind_of?(DataMapper::Associations::ManyToMany::Relationship) do
411
411
  @expected.each { |resource| resource.car.should == @car }
412
412
  end
413
413
  end
414
414
 
415
415
  it 'should persist the Resource' do
416
416
  @car.save.should be_true
417
- @car.model.get(*@car.key).send(@name).should == @expected
417
+ @car.model.get(*@car.key).__send__(@name).should == @expected
418
418
  end
419
419
 
420
420
  it 'should persist the associated Resource' do
@@ -432,6 +432,7 @@ describe DataMapper::Associations do
432
432
  include DataMapper::Resource
433
433
 
434
434
  property :id, Serial
435
+ property :name, String
435
436
  end
436
437
 
437
438
  class ::Engine
@@ -464,7 +465,7 @@ describe DataMapper::Associations do
464
465
  @model = Engine
465
466
  @name = :engine
466
467
 
467
- Car.belongs_to(@name, :nullable => true)
468
+ Car.belongs_to(@name, :required => false)
468
469
  Engine.has(1, :car)
469
470
  end
470
471
 
@@ -561,8 +562,7 @@ describe DataMapper::Associations do
561
562
  before :all do
562
563
  @car = Car.create
563
564
 
564
- @engine = Engine.new
565
- @engine.car_id = @car.id
565
+ @engine = Engine.new(:car_id => @car.id)
566
566
  end
567
567
 
568
568
  it 'should set the associated resource' do
@@ -611,6 +611,66 @@ describe DataMapper::Associations do
611
611
  end
612
612
  end
613
613
  end
614
+
615
+ describe 'with a model' do
616
+ before :all do
617
+ Engine.belongs_to(:vehicle, Car)
618
+ end
619
+
620
+ it 'should set the relationship target model' do
621
+ Engine.relationships[:vehicle].target_model.should == Car
622
+ end
623
+ end
624
+
625
+ describe 'with a :model option' do
626
+ before :all do
627
+ Engine.belongs_to(:vehicle, :model => Car)
628
+ end
629
+
630
+ it 'should set the relationship target model' do
631
+ Engine.relationships[:vehicle].target_model.should == Car
632
+ end
633
+ end
634
+
635
+ describe 'with a single element as :child_key option' do
636
+ before :all do
637
+ Engine.belongs_to(:vehicle, :model => Car, :child_key => :bike_id)
638
+ end
639
+
640
+ it 'should set the relationship child key' do
641
+ Engine.relationships[:vehicle].child_key.map { |property| property.name }.should == [:bike_id]
642
+ end
643
+ end
644
+
645
+ describe 'with an array as :child_key option' do
646
+ before :all do
647
+ Engine.belongs_to(:vehicle, :model => Car, :child_key => [:bike_id])
648
+ end
649
+
650
+ it 'should set the relationship child key' do
651
+ Engine.relationships[:vehicle].child_key.map { |property| property.name }.should == [:bike_id]
652
+ end
653
+ end
654
+
655
+ describe 'with a single element as :parent_key option' do
656
+ before :all do
657
+ Engine.belongs_to(:vehicle, :model => Car, :parent_key => :name)
658
+ end
659
+
660
+ it 'should set the relationship parent key' do
661
+ Engine.relationships[:vehicle].parent_key.map { |property| property.name }.should == [:name]
662
+ end
663
+ end
664
+
665
+ describe 'with an array as :parent_key option' do
666
+ before :all do
667
+ Engine.belongs_to(:vehicle, :model => Car, :parent_key => [:name])
668
+ end
669
+
670
+ it 'should set the relationship parent key' do
671
+ Engine.relationships[:vehicle].parent_key.map { |property| property.name }.should == [:name]
672
+ end
673
+ end
614
674
  end
615
675
 
616
676
  it { Car.should respond_to(:has) }
@@ -679,7 +739,7 @@ describe DataMapper::Associations do
679
739
  @name = :doors
680
740
 
681
741
  Car.has(1..4, @name)
682
- Door.belongs_to(:car, :nullable => true)
742
+ Door.belongs_to(:car, :required => false)
683
743
  end
684
744
 
685
745
  supported_by :all do
@@ -902,7 +962,7 @@ describe DataMapper::Associations do
902
962
  property :id, Serial
903
963
  property :name, String
904
964
 
905
- belongs_to :owner, Employee, :nullable => true
965
+ belongs_to :owner, Employee, :required => false
906
966
  has n, :employees
907
967
  end
908
968
  end