ardm-core 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +2 -2
  4. data/Gemfile +1 -11
  5. data/ardm-core.gemspec +3 -3
  6. data/lib/dm-core.rb +2 -2
  7. data/lib/dm-core/adapters/abstract_adapter.rb +1 -1
  8. data/lib/dm-core/associations/many_to_one.rb +6 -4
  9. data/lib/dm-core/collection.rb +1 -0
  10. data/lib/dm-core/model.rb +3 -2
  11. data/lib/dm-core/model/property.rb +2 -1
  12. data/lib/dm-core/property.rb +4 -2
  13. data/lib/dm-core/query.rb +1 -1
  14. data/lib/dm-core/resource.rb +8 -1
  15. data/lib/dm-core/resource/persistence_state/transient.rb +14 -1
  16. data/lib/dm-core/spec/lib/adapter_helpers.rb +2 -0
  17. data/lib/dm-core/spec/lib/spec_helper.rb +2 -3
  18. data/lib/dm-core/spec/setup.rb +4 -2
  19. data/lib/dm-core/spec/shared/adapter_spec.rb +116 -77
  20. data/lib/dm-core/spec/shared/resource_spec.rb +5 -1
  21. data/lib/dm-core/support/mash.rb +1 -1
  22. data/lib/dm-core/support/naming_conventions.rb +20 -1
  23. data/lib/dm-core/support/ordered_set.rb +1 -0
  24. data/lib/dm-core/support/subject_set.rb +1 -0
  25. data/lib/dm-core/version.rb +1 -1
  26. data/script/performance.rb +1 -1
  27. data/script/profile.rb +1 -1
  28. data/spec/public/associations/many_to_many_spec.rb +2 -2
  29. data/spec/public/associations/many_to_one_spec.rb +1 -1
  30. data/spec/public/associations/one_to_many_spec.rb +1 -1
  31. data/spec/public/associations/one_to_one_spec.rb +2 -2
  32. data/spec/public/finalize_spec.rb +2 -2
  33. data/spec/public/model/relationship_spec.rb +19 -19
  34. data/spec/public/model_spec.rb +1 -1
  35. data/spec/public/property/discriminator_spec.rb +2 -2
  36. data/spec/public/property/object_spec.rb +13 -2
  37. data/spec/public/property_spec.rb +0 -6
  38. data/spec/public/resource/state_spec.rb +72 -0
  39. data/spec/public/resource_spec.rb +5 -5
  40. data/spec/public/shared/association_collection_shared_spec.rb +1 -1
  41. data/spec/public/shared/collection_shared_spec.rb +24 -24
  42. data/spec/public/shared/finder_shared_spec.rb +26 -8
  43. data/spec/spec.opts +1 -3
  44. data/tasks/ci.rake +1 -1
  45. data/tasks/spec.rake +0 -21
  46. data/tasks/yardstick.rake +1 -1
  47. 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
@@ -139,7 +139,7 @@ module DataMapper
139
139
 
140
140
  # @return [Hash] The mash as a Hash with string keys.
141
141
  def to_hash
142
- Hash.new(default).merge(self)
142
+ Hash.new(default).replace(self)
143
143
  end
144
144
 
145
145
  protected
@@ -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://localhost/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"
@@ -316,6 +316,7 @@ module DataMapper
316
316
  #
317
317
  # @api private
318
318
  def each
319
+ return to_enum unless block_given?
319
320
  entries.each { |entry| yield(entry) }
320
321
  self
321
322
  end
@@ -207,6 +207,7 @@ module DataMapper
207
207
  #
208
208
  # @api private
209
209
  def each
210
+ return to_enum unless block_given?
210
211
  entries.each { |entry| yield(entry) }
211
212
  self
212
213
  end
@@ -1,3 +1,3 @@
1
1
  module DataMapper
2
- VERSION = '1.2.1'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -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@localhost/dm_core_test?socket=#{socket_file}")
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')
@@ -28,7 +28,7 @@ SOCKET_FILE = Pathname.glob(%w[
28
28
  configuration_options = {
29
29
  :adapter => 'mysql',
30
30
  :database => 'dm_core_test',
31
- :host => 'localhost',
31
+ :host => '127.0.0.1',
32
32
  :username => 'root',
33
33
  :password => '',
34
34
  :socket => SOCKET_FILE,
@@ -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 be_include(@engine)
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 be_include(@engine)
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 be_include(@engine)
645
+ @car2.engines.should include(@engine)
646
646
  end
647
647
  end
648
648
  end
@@ -111,7 +111,7 @@ describe DataMapper::Model do
111
111
  end
112
112
 
113
113
  it 'should add the resources to the alternate repository' do
114
- @article.model.get(*@heff1.key).should_not be_nil
114
+ @article.model.get!(*@heff1.key).should_not be_nil
115
115
  end
116
116
  end
117
117
  end
@@ -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
- subject { @property.typecast(@value) }
39
+ context 'when the value is a primitive' do
40
+ it { should equal(@value) }
41
+ end
38
42
 
39
- it { should equal(@value) }
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