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