ardm-core 1.2.1 → 1.3.0
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.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +2 -2
- data/Gemfile +1 -11
- data/ardm-core.gemspec +3 -3
- data/lib/dm-core.rb +2 -2
- data/lib/dm-core/adapters/abstract_adapter.rb +1 -1
- data/lib/dm-core/associations/many_to_one.rb +6 -4
- data/lib/dm-core/collection.rb +1 -0
- data/lib/dm-core/model.rb +3 -2
- data/lib/dm-core/model/property.rb +2 -1
- data/lib/dm-core/property.rb +4 -2
- data/lib/dm-core/query.rb +1 -1
- data/lib/dm-core/resource.rb +8 -1
- data/lib/dm-core/resource/persistence_state/transient.rb +14 -1
- data/lib/dm-core/spec/lib/adapter_helpers.rb +2 -0
- data/lib/dm-core/spec/lib/spec_helper.rb +2 -3
- data/lib/dm-core/spec/setup.rb +4 -2
- data/lib/dm-core/spec/shared/adapter_spec.rb +116 -77
- data/lib/dm-core/spec/shared/resource_spec.rb +5 -1
- data/lib/dm-core/support/mash.rb +1 -1
- data/lib/dm-core/support/naming_conventions.rb +20 -1
- data/lib/dm-core/support/ordered_set.rb +1 -0
- data/lib/dm-core/support/subject_set.rb +1 -0
- data/lib/dm-core/version.rb +1 -1
- data/script/performance.rb +1 -1
- data/script/profile.rb +1 -1
- data/spec/public/associations/many_to_many_spec.rb +2 -2
- data/spec/public/associations/many_to_one_spec.rb +1 -1
- data/spec/public/associations/one_to_many_spec.rb +1 -1
- data/spec/public/associations/one_to_one_spec.rb +2 -2
- data/spec/public/finalize_spec.rb +2 -2
- data/spec/public/model/relationship_spec.rb +19 -19
- data/spec/public/model_spec.rb +1 -1
- data/spec/public/property/discriminator_spec.rb +2 -2
- data/spec/public/property/object_spec.rb +13 -2
- data/spec/public/property_spec.rb +0 -6
- data/spec/public/resource/state_spec.rb +72 -0
- data/spec/public/resource_spec.rb +5 -5
- data/spec/public/shared/association_collection_shared_spec.rb +1 -1
- data/spec/public/shared/collection_shared_spec.rb +24 -24
- data/spec/public/shared/finder_shared_spec.rb +26 -8
- data/spec/spec.opts +1 -3
- data/tasks/ci.rake +1 -1
- data/tasks/spec.rake +0 -21
- data/tasks/yardstick.rake +1 -1
- metadata +26 -19
@@ -233,13 +233,17 @@ share_examples_for 'A public Resource' do
|
|
233
233
|
describe 'when a public mutator is specified' do
|
234
234
|
before :all do
|
235
235
|
rescue_if @skip do
|
236
|
-
@user.attributes = { :name => 'dkubb' }
|
236
|
+
@user.attributes = { :name => 'dkubb', @user.class.properties[:age] => '42' }
|
237
237
|
end
|
238
238
|
end
|
239
239
|
|
240
240
|
it 'should set the value' do
|
241
241
|
@user.name.should eql('dkubb')
|
242
242
|
end
|
243
|
+
|
244
|
+
it 'should typecast and set the value' do
|
245
|
+
@user.age.should eql(42)
|
246
|
+
end
|
243
247
|
end
|
244
248
|
|
245
249
|
describe 'when a non-public mutator is specified' do
|
data/lib/dm-core/support/mash.rb
CHANGED
@@ -20,7 +20,7 @@ module DataMapper
|
|
20
20
|
# DataMapper.setup(name, uri) returns the Adapter for convenience, so you can
|
21
21
|
# use code like this:
|
22
22
|
#
|
23
|
-
# adapter = DataMapper.setup(:default, 'mock://
|
23
|
+
# adapter = DataMapper.setup(:default, 'mock://127.0.0.1/mock')
|
24
24
|
# adapter.resource_naming_convention = NamingConventions::Resource::Underscored
|
25
25
|
module NamingConventions
|
26
26
|
|
@@ -78,6 +78,25 @@ module DataMapper
|
|
78
78
|
end
|
79
79
|
end # module Underscored
|
80
80
|
|
81
|
+
module FQN
|
82
|
+
def self.call(property)
|
83
|
+
model, name = property.model, property.name
|
84
|
+
|
85
|
+
fk_names = model.relationships.inject([]) { |names, rel|
|
86
|
+
if rel.respond_to?(:required?)
|
87
|
+
names + rel.source_key.map(&:name)
|
88
|
+
else
|
89
|
+
names
|
90
|
+
end
|
91
|
+
}
|
92
|
+
|
93
|
+
return name.to_s if fk_names.include?(name)
|
94
|
+
|
95
|
+
storage_name = model.storage_name(property.repository_name)
|
96
|
+
"#{DataMapper::Inflector.singularize(storage_name)}_#{name}"
|
97
|
+
end
|
98
|
+
end # module FQN
|
99
|
+
|
81
100
|
module Yaml
|
82
101
|
def self.call(property)
|
83
102
|
"#{DataMapper::Inflector.pluralize(DataMapper::Inflector.underscore(property.name.to_s))}.yaml"
|
data/lib/dm-core/version.rb
CHANGED
data/script/performance.rb
CHANGED
@@ -38,7 +38,7 @@ log_dir = DataMapper.root / 'log'
|
|
38
38
|
log_dir.mkdir unless log_dir.directory?
|
39
39
|
|
40
40
|
DataMapper::Logger.new(log_dir / 'dm.log', :off)
|
41
|
-
adapter = DataMapper.setup(:default, "mysql://root@
|
41
|
+
adapter = DataMapper.setup(:default, "mysql://root@127.0.0.1/dm_core_test?socket=#{socket_file}")
|
42
42
|
|
43
43
|
if configuration_options[:adapter]
|
44
44
|
sqlfile = File.join(File.dirname(__FILE__), '..', 'tmp', 'performance.sql')
|
data/script/profile.rb
CHANGED
@@ -82,7 +82,7 @@ end
|
|
82
82
|
|
83
83
|
# load the targets without references to a single source
|
84
84
|
load_collection = lambda do |query|
|
85
|
-
@author_model.get(*@author.key).articles(query)
|
85
|
+
@author_model.get!(*@author.key).articles(query)
|
86
86
|
end
|
87
87
|
|
88
88
|
@articles = load_collection.call(:title => 'Sample Article')
|
@@ -177,7 +177,7 @@ end
|
|
177
177
|
|
178
178
|
# load the targets without references to a single source
|
179
179
|
load_collection = lambda do |query|
|
180
|
-
@author_model.get(*@author.key).articles(query)
|
180
|
+
@author_model.get!(*@author.key).articles(query)
|
181
181
|
end
|
182
182
|
|
183
183
|
@articles = load_collection.call(:title => 'Sample Article')
|
@@ -73,7 +73,7 @@ describe 'Many to One Associations' do
|
|
73
73
|
user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test')
|
74
74
|
comment = @comment_model.create(:body => 'Cool spec', :user => user)
|
75
75
|
|
76
|
-
@comment = @comment_model.get(*comment.key)
|
76
|
+
@comment = @comment_model.get!(*comment.key)
|
77
77
|
@user = @comment.user
|
78
78
|
end
|
79
79
|
|
@@ -62,7 +62,7 @@ require 'spec_helper'
|
|
62
62
|
|
63
63
|
# load the targets without references to a single source
|
64
64
|
load_collection = lambda do |query|
|
65
|
-
@author_model.get(*@author.key).articles(query)
|
65
|
+
@author_model.get!(*@author.key).articles(query)
|
66
66
|
end
|
67
67
|
|
68
68
|
@articles = load_collection.call(:title => 'Sample Article')
|
@@ -72,7 +72,7 @@ describe 'One to One Associations' do
|
|
72
72
|
comment = @comment_model.create(:body => 'Cool spec')
|
73
73
|
user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test', :comment => comment)
|
74
74
|
|
75
|
-
@comment = @comment_model.get(*comment.key)
|
75
|
+
@comment = @comment_model.get!(*comment.key)
|
76
76
|
@user = @comment.user
|
77
77
|
end
|
78
78
|
|
@@ -164,7 +164,7 @@ describe 'One to One Through Associations' do
|
|
164
164
|
comment = @comment_model.create(:body => 'Cool spec')
|
165
165
|
user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test', :comment => comment)
|
166
166
|
|
167
|
-
@comment = @comment_model.get(*comment.key)
|
167
|
+
@comment = @comment_model.get!(*comment.key)
|
168
168
|
@user = @comment.user
|
169
169
|
end
|
170
170
|
|
@@ -53,7 +53,7 @@ describe DataMapper do
|
|
53
53
|
include DataMapper::Resource
|
54
54
|
end
|
55
55
|
begin
|
56
|
-
method(:subject).should raise_error(DataMapper::IncompleteModelError, 'EmptyObject must have at least one property or many to one relationship to be valid')
|
56
|
+
method(:subject).should raise_error(DataMapper::IncompleteModelError, 'EmptyObject must have at least one property or many to one relationship in default to be valid')
|
57
57
|
ensure
|
58
58
|
DataMapper::Model.descendants.delete(EmptyObject)
|
59
59
|
Object.send(:remove_const, :EmptyObject)
|
@@ -66,7 +66,7 @@ describe DataMapper do
|
|
66
66
|
property :name, String
|
67
67
|
end
|
68
68
|
begin
|
69
|
-
method(:subject).should raise_error(DataMapper::IncompleteModelError, 'KeylessObject must have a key to be valid')
|
69
|
+
method(:subject).should raise_error(DataMapper::IncompleteModelError, 'KeylessObject must have a key in default to be valid')
|
70
70
|
ensure
|
71
71
|
DataMapper::Model.descendants.delete(KeylessObject)
|
72
72
|
Object.send(:remove_const, :KeylessObject)
|
@@ -72,7 +72,7 @@ share_examples_for 'it creates a one accessor' do
|
|
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
|
@@ -111,13 +111,13 @@ share_examples_for 'it creates a one mutator' do
|
|
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
|
118
118
|
@car.save.should be(true)
|
119
119
|
@expected.should be_saved
|
120
|
-
@expected.model.get(*@expected.key).car.should == @car
|
120
|
+
@expected.model.get!(*@expected.key).car.should == @car
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
@@ -151,13 +151,13 @@ share_examples_for 'it creates a one mutator' do
|
|
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
|
158
158
|
@car.save.should be(true)
|
159
159
|
@return.should be_saved
|
160
|
-
@return.model.get(*@return.key).car.should == @car
|
160
|
+
@return.model.get!(*@return.key).car.should == @car
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
@@ -178,7 +178,7 @@ share_examples_for 'it creates a one mutator' do
|
|
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
|
|
@@ -210,13 +210,13 @@ 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
|
217
217
|
@car.save.should be(true)
|
218
218
|
@expected.should be_saved
|
219
|
-
@expected.model.get(*@expected.key).car.should == @car
|
219
|
+
@expected.model.get!(*@expected.key).car.should == @car
|
220
220
|
end
|
221
221
|
end
|
222
222
|
end
|
@@ -285,7 +285,7 @@ share_examples_for 'it creates a many accessor' do
|
|
285
285
|
Hash[ @model.key(@repository.name).zip(@expected.key) ]
|
286
286
|
)
|
287
287
|
|
288
|
-
@return = @car.model.get(*@car.key).__send__(@name)
|
288
|
+
@return = @car.model.get!(*@car.key).__send__(@name)
|
289
289
|
end
|
290
290
|
|
291
291
|
it 'should return a Collection' do
|
@@ -325,13 +325,13 @@ share_examples_for 'it creates a many mutator' do
|
|
325
325
|
|
326
326
|
it 'should persist the Collection' do
|
327
327
|
@car.save.should be(true)
|
328
|
-
@car.model.get(*@car.key).__send__(@name).should == @expected
|
328
|
+
@car.model.get!(*@car.key).__send__(@name).should == @expected
|
329
329
|
end
|
330
330
|
|
331
331
|
it 'should persist the associated Resource' do
|
332
332
|
@car.save.should be(true)
|
333
333
|
@expected.each { |resource| resource.should be_saved }
|
334
|
-
@expected.each { |resource| resource.model.get(*resource.key).car.should == @car }
|
334
|
+
@expected.each { |resource| resource.model.get!(*resource.key).car.should == @car }
|
335
335
|
end
|
336
336
|
end
|
337
337
|
|
@@ -360,13 +360,13 @@ share_examples_for 'it creates a many mutator' do
|
|
360
360
|
|
361
361
|
it 'should persist the Collection' do
|
362
362
|
@car.save.should be(true)
|
363
|
-
@car.model.get(*@car.key).__send__(@name).should == @return
|
363
|
+
@car.model.get!(*@car.key).__send__(@name).should == @return
|
364
364
|
end
|
365
365
|
|
366
366
|
it 'should persist the associated Resource' do
|
367
367
|
@car.save.should be(true)
|
368
368
|
@return.each { |resource| resource.should be_saved }
|
369
|
-
@return.each { |resource| resource.model.get(*resource.key).car.should == @car }
|
369
|
+
@return.each { |resource| resource.model.get!(*resource.key).car.should == @car }
|
370
370
|
end
|
371
371
|
end
|
372
372
|
|
@@ -387,7 +387,7 @@ share_examples_for 'it creates a many mutator' do
|
|
387
387
|
|
388
388
|
it 'should persist as an empty Collection' do
|
389
389
|
@car.save.should be(true)
|
390
|
-
@car.model.get(*@car.key).__send__(@name).should be_empty
|
390
|
+
@car.model.get!(*@car.key).__send__(@name).should be_empty
|
391
391
|
end
|
392
392
|
end
|
393
393
|
|
@@ -417,13 +417,13 @@ share_examples_for 'it creates a many mutator' do
|
|
417
417
|
|
418
418
|
it 'should persist the Resource' do
|
419
419
|
@car.save.should be(true)
|
420
|
-
@car.model.get(*@car.key).__send__(@name).should == @expected
|
420
|
+
@car.model.get!(*@car.key).__send__(@name).should == @expected
|
421
421
|
end
|
422
422
|
|
423
423
|
it 'should persist the associated Resource' do
|
424
424
|
@car.save.should be(true)
|
425
425
|
@expected.each { |resource| resource.should be_saved }
|
426
|
-
@expected.each { |resource| resource.model.get(*resource.key).car.should == @car }
|
426
|
+
@expected.each { |resource| resource.model.get!(*resource.key).car.should == @car }
|
427
427
|
end
|
428
428
|
end
|
429
429
|
end
|
@@ -592,7 +592,7 @@ describe DataMapper::Associations do
|
|
592
592
|
|
593
593
|
it 'should add the engine object to the car' do
|
594
594
|
pending 'Changing a belongs_to parent should add the object to the correct association' do
|
595
|
-
@car.engines.should
|
595
|
+
@car.engines.should include(@engine)
|
596
596
|
end
|
597
597
|
end
|
598
598
|
end
|
@@ -623,7 +623,7 @@ describe DataMapper::Associations do
|
|
623
623
|
|
624
624
|
it 'should add the engine to the car' do
|
625
625
|
pending 'Changing a belongs_to parent should add the object to the correct association' do
|
626
|
-
@car2.engines.should
|
626
|
+
@car2.engines.should include(@engine)
|
627
627
|
end
|
628
628
|
end
|
629
629
|
end
|
@@ -642,7 +642,7 @@ describe DataMapper::Associations do
|
|
642
642
|
|
643
643
|
it 'should add the engine to the car' do
|
644
644
|
pending 'a change to the foreign key should also change the related object' do
|
645
|
-
@car2.engines.should
|
645
|
+
@car2.engines.should include(@engine)
|
646
646
|
end
|
647
647
|
end
|
648
648
|
end
|
data/spec/public/model_spec.rb
CHANGED
@@ -117,11 +117,11 @@ describe DataMapper::Property::Discriminator do
|
|
117
117
|
end
|
118
118
|
|
119
119
|
it 'should persist the type' do
|
120
|
-
@announcement.model.get(*@announcement.key).type.should equal(@announcement_model)
|
120
|
+
@announcement.model.get!(*@announcement.key).type.should equal(@announcement_model)
|
121
121
|
end
|
122
122
|
|
123
123
|
it 'should be retrieved as an instance of the correct class' do
|
124
|
-
@announcement.model.get(*@announcement.key).should be_instance_of(@announcement_model)
|
124
|
+
@announcement.model.get!(*@announcement.key).should be_instance_of(@announcement_model)
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'should include descendants in finders' do
|
@@ -30,13 +30,24 @@ describe DataMapper::Property, 'Object type' do
|
|
30
30
|
it { should respond_to(:typecast) }
|
31
31
|
|
32
32
|
describe '#typecast' do
|
33
|
+
subject { @property.typecast(@value) }
|
34
|
+
|
33
35
|
before do
|
34
36
|
@value = { 'lang' => 'en_CA' }
|
35
37
|
end
|
36
38
|
|
37
|
-
|
39
|
+
context 'when the value is a primitive' do
|
40
|
+
it { should equal(@value) }
|
41
|
+
end
|
38
42
|
|
39
|
-
|
43
|
+
context 'when the value is not a primitive' do
|
44
|
+
before do
|
45
|
+
# simulate the value not being a primitive
|
46
|
+
@property.should_receive(:primitive?).with(@value).and_return(false)
|
47
|
+
end
|
48
|
+
|
49
|
+
it { should equal(@value) }
|
50
|
+
end
|
40
51
|
end
|
41
52
|
|
42
53
|
it { should respond_to(:dump) }
|
@@ -263,12 +263,6 @@ describe DataMapper::Property do
|
|
263
263
|
|
264
264
|
it 'triggers lazy loading for given resource'
|
265
265
|
|
266
|
-
it 'type casts given value' do
|
267
|
-
@property.set(@image, Addressable::URI.parse('http://test.example/'))
|
268
|
-
# get a string that has been typecasted using #to_str
|
269
|
-
@image.title.should == 'http://test.example/'
|
270
|
-
end
|
271
|
-
|
272
266
|
it 'sets new property value' do
|
273
267
|
@property.set(@image, 'Updated value')
|
274
268
|
@image.title.should == 'Updated value'
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
2
|
+
|
3
|
+
describe 'DataMapper::Resource' do
|
4
|
+
before :all do
|
5
|
+
class ::Author
|
6
|
+
include DataMapper::Resource
|
7
|
+
|
8
|
+
property :id, Serial
|
9
|
+
property :string_, String
|
10
|
+
property :bool_, Boolean
|
11
|
+
property :float_, Float
|
12
|
+
property :integer_, Integer
|
13
|
+
property :decimal_, Decimal
|
14
|
+
property :datetime_, DateTime
|
15
|
+
property :date_, Date
|
16
|
+
property :time_, Time
|
17
|
+
end
|
18
|
+
|
19
|
+
DataMapper.finalize
|
20
|
+
|
21
|
+
@model = Author
|
22
|
+
end
|
23
|
+
|
24
|
+
supported_by :all do
|
25
|
+
before do
|
26
|
+
@values = {
|
27
|
+
:string_ => Addressable::URI.parse('http://test.example/'),
|
28
|
+
:bool_ => true,
|
29
|
+
:float_ => 2.5,
|
30
|
+
:integer_ => 10,
|
31
|
+
:decimal_ => BigDecimal.new("999.95"),
|
32
|
+
:datetime_ => DateTime.parse('2010-10-11 12:13:14+0'),
|
33
|
+
:date_ => Date.parse('2010-10-11 12:13:14+0'),
|
34
|
+
:time_ => Time.parse('2010-10-11 12:13:14+0'),
|
35
|
+
}
|
36
|
+
@string_values = {
|
37
|
+
:string_ => 'http://test.example/',
|
38
|
+
:decimal_ => '999.95',
|
39
|
+
}
|
40
|
+
|
41
|
+
@resource = @model.create(@values)
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '.new' do
|
45
|
+
subject { @resource }
|
46
|
+
|
47
|
+
it { should_not be_dirty }
|
48
|
+
end
|
49
|
+
|
50
|
+
[:string_, :bool_, :float_, :integer_, :decimal_, :datetime_, :date_, :time_].each do |property|
|
51
|
+
describe "#{property.to_s[0...-1]} property mutator" do
|
52
|
+
before do
|
53
|
+
@resource.send("#{property}=", @string_values[property] || @values[property].to_s)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'type casts given equal value so resource remains clean' do
|
57
|
+
@resource.should_not be_dirty
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#attribute_set for #{property.to_s[0...-1]} property" do
|
62
|
+
before do
|
63
|
+
@resource.attribute_set(property, @string_values[property] || @values[property].to_s)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'type casts given equal value so resource remains clean' do
|
67
|
+
@resource.should_not be_dirty
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|