dm-core 1.2.0 → 1.2.1
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 +7 -0
- data/.gitignore +38 -0
- data/.travis.yml +45 -0
- data/Gemfile +5 -6
- data/Rakefile +1 -24
- data/dm-core.gemspec +18 -296
- data/lib/dm-core/collection.rb +1 -0
- data/lib/dm-core/model.rb +1 -0
- data/lib/dm-core/model/property.rb +1 -0
- data/lib/dm-core/property.rb +4 -2
- data/lib/dm-core/query.rb +4 -4
- 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/spec_helper.rb +2 -3
- data/lib/dm-core/spec/setup.rb +3 -1
- 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/ordered_set.rb +1 -0
- data/lib/dm-core/support/subject_set.rb +1 -0
- data/lib/dm-core/version.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/model/relationship_spec.rb +16 -16
- 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/collection_shared_spec.rb +4 -4
- data/spec/public/shared/finder_shared_spec.rb +26 -8
- data/spec/spec.opts +1 -3
- metadata +206 -100
data/lib/dm-core/collection.rb
CHANGED
data/lib/dm-core/model.rb
CHANGED
@@ -234,6 +234,7 @@ module DataMapper
|
|
234
234
|
#{writer_visibility}
|
235
235
|
def #{writer_name}(value)
|
236
236
|
property = properties[#{name.inspect}]
|
237
|
+
value = property.typecast(value)
|
237
238
|
self.persistence_state = persistence_state.set(property, value)
|
238
239
|
persistence_state.get(property)
|
239
240
|
end
|
data/lib/dm-core/property.rb
CHANGED
@@ -622,7 +622,7 @@ module DataMapper
|
|
622
622
|
#
|
623
623
|
# @api private
|
624
624
|
def set(resource, value)
|
625
|
-
set!(resource,
|
625
|
+
set!(resource, value)
|
626
626
|
end
|
627
627
|
|
628
628
|
# Set the ivar value in the resource
|
@@ -682,8 +682,10 @@ module DataMapper
|
|
682
682
|
def typecast(value)
|
683
683
|
if value.nil? || primitive?(value)
|
684
684
|
value
|
685
|
-
elsif respond_to?(:typecast_to_primitive)
|
685
|
+
elsif respond_to?(:typecast_to_primitive, true)
|
686
686
|
typecast_to_primitive(value)
|
687
|
+
else
|
688
|
+
value
|
687
689
|
end
|
688
690
|
end
|
689
691
|
|
data/lib/dm-core/query.rb
CHANGED
@@ -1017,7 +1017,7 @@ module DataMapper
|
|
1017
1017
|
add_condition(condition)
|
1018
1018
|
|
1019
1019
|
when Hash
|
1020
|
-
condition.each { |
|
1020
|
+
condition.each { |key, value| append_condition(key, value) }
|
1021
1021
|
|
1022
1022
|
when Array
|
1023
1023
|
statement, *bind_values = *condition
|
@@ -1053,6 +1053,9 @@ module DataMapper
|
|
1053
1053
|
@order = Array(@order)
|
1054
1054
|
@order = @order.map do |order|
|
1055
1055
|
case order
|
1056
|
+
when Direction
|
1057
|
+
order.dup
|
1058
|
+
|
1056
1059
|
when Operator
|
1057
1060
|
target = order.target
|
1058
1061
|
property = target.kind_of?(Property) ? target : @properties[target]
|
@@ -1065,9 +1068,6 @@ module DataMapper
|
|
1065
1068
|
when Property
|
1066
1069
|
Direction.new(order)
|
1067
1070
|
|
1068
|
-
when Direction
|
1069
|
-
order.dup
|
1070
|
-
|
1071
1071
|
when Path
|
1072
1072
|
Direction.new(order.property)
|
1073
1073
|
|
data/lib/dm-core/resource.rb
CHANGED
@@ -280,7 +280,10 @@ module DataMapper
|
|
280
280
|
# @api public
|
281
281
|
def attribute_set(name, value)
|
282
282
|
property = properties[name]
|
283
|
-
|
283
|
+
if property
|
284
|
+
value = property.typecast(value)
|
285
|
+
self.persistence_state = persistence_state.set(property, value)
|
286
|
+
end
|
284
287
|
end
|
285
288
|
|
286
289
|
alias_method :[]=, :attribute_set
|
@@ -335,6 +338,10 @@ module DataMapper
|
|
335
338
|
raise ArgumentError, "The attribute '#{name}' is not accessible in #{model}"
|
336
339
|
end
|
337
340
|
when Associations::Relationship, Property
|
341
|
+
# only call a public #typecast (e.g. on Property instances)
|
342
|
+
if name.respond_to?(:typecast)
|
343
|
+
value = name.typecast(value)
|
344
|
+
end
|
338
345
|
self.persistence_state = persistence_state.set(name, value)
|
339
346
|
end
|
340
347
|
end
|
@@ -50,7 +50,20 @@ module DataMapper
|
|
50
50
|
|
51
51
|
def set_default_value(subject)
|
52
52
|
return if subject.loaded?(resource) || !subject.default?
|
53
|
-
|
53
|
+
default = typecast_default(subject, subject.default_for(resource))
|
54
|
+
set(subject, default)
|
55
|
+
end
|
56
|
+
|
57
|
+
def typecast_default(subject, default)
|
58
|
+
return default unless subject.respond_to?(:typecast)
|
59
|
+
|
60
|
+
typecasted_default = subject.send(:typecast, default)
|
61
|
+
unless typecasted_default.eql?(default)
|
62
|
+
warn "Automatic typecasting of default property values is deprecated " +
|
63
|
+
"(#{default.inspect} was casted to #{typecasted_default.inspect}). " +
|
64
|
+
"Specify the correct type for #{resource.class}."
|
65
|
+
end
|
66
|
+
typecasted_default
|
54
67
|
end
|
55
68
|
|
56
69
|
def track(subject)
|
@@ -45,12 +45,11 @@ module DataMapper
|
|
45
45
|
next if object.kind_of?(DataMapper::Logger) ||
|
46
46
|
object.kind_of?(DataMapper::DescendantSet) ||
|
47
47
|
object.kind_of?(DataMapper::Adapters::AbstractAdapter) ||
|
48
|
-
object.class.name[0, 13] == 'DataObjects::'
|
48
|
+
object.class.name.to_s[0, 13] == 'DataObjects::'
|
49
49
|
|
50
50
|
# skip classes and modules in the DataMapper namespace
|
51
51
|
next if object.kind_of?(Module) &&
|
52
|
-
|
53
|
-
object.name[0, 12] == 'DataMapper::'
|
52
|
+
object.name.to_s[0, 12] == 'DataMapper::'
|
54
53
|
|
55
54
|
# skip when the ivar is no longer defined in the object
|
56
55
|
next unless object.instance_variable_defined?(ivar)
|
data/lib/dm-core/spec/setup.rb
CHANGED
@@ -115,7 +115,9 @@ module DataMapper
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def connection_uri
|
118
|
-
"#{adapter_name}://#{username}
|
118
|
+
"#{adapter_name}://#{username}%s@#{host}/#{storage_name}".tap do |s|
|
119
|
+
return s % ((password.empty?) ? "" : ":#{password}")
|
120
|
+
end
|
119
121
|
end
|
120
122
|
|
121
123
|
def storage_name
|
@@ -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
data/lib/dm-core/version.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
|
|
@@ -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
|
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'
|