dm-core 1.0.0.rc2 → 1.0.0.rc3

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.
Files changed (65) hide show
  1. data/Gemfile +1 -1
  2. data/LICENSE +1 -1
  3. data/README.rdoc +1 -1
  4. data/Rakefile +3 -4
  5. data/VERSION +1 -1
  6. data/dm-core.gemspec +7 -5
  7. data/lib/dm-core.rb +44 -0
  8. data/lib/dm-core/adapters.rb +1 -1
  9. data/lib/dm-core/adapters/abstract_adapter.rb +16 -0
  10. data/lib/dm-core/collection.rb +2 -2
  11. data/lib/dm-core/model.rb +64 -53
  12. data/lib/dm-core/model/property.rb +14 -6
  13. data/lib/dm-core/model/relationship.rb +10 -18
  14. data/lib/dm-core/property.rb +10 -10
  15. data/lib/dm-core/query.rb +8 -18
  16. data/lib/dm-core/resource.rb +3 -11
  17. data/lib/dm-core/resource/state.rb +13 -16
  18. data/lib/dm-core/resource/state/dirty.rb +11 -1
  19. data/lib/dm-core/resource/state/transient.rb +9 -1
  20. data/lib/dm-core/spec/lib/adapter_helpers.rb +5 -0
  21. data/lib/dm-core/spec/shared/adapter_spec.rb +2 -0
  22. data/lib/dm-core/spec/shared/resource_spec.rb +0 -31
  23. data/lib/dm-core/version.rb +1 -1
  24. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +2 -0
  25. data/spec/public/associations/many_to_many_spec.rb +2 -1
  26. data/spec/public/associations/many_to_one_spec.rb +1 -0
  27. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +1 -0
  28. data/spec/public/associations/one_to_many_spec.rb +2 -0
  29. data/spec/public/associations/one_to_one_spec.rb +2 -0
  30. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +1 -0
  31. data/spec/public/collection_spec.rb +2 -0
  32. data/spec/public/finalize_spec.rb +34 -0
  33. data/spec/public/model/hook_spec.rb +1 -0
  34. data/spec/public/model/property_spec.rb +1 -0
  35. data/spec/public/model/relationship_spec.rb +22 -0
  36. data/spec/public/model_spec.rb +138 -3
  37. data/spec/public/property/discriminator_spec.rb +1 -0
  38. data/spec/public/property/object_spec.rb +1 -0
  39. data/spec/public/property_spec.rb +13 -4
  40. data/spec/public/resource_spec.rb +1 -0
  41. data/spec/public/sel_spec.rb +2 -0
  42. data/spec/public/shared/collection_shared_spec.rb +0 -45
  43. data/spec/public/shared/finder_shared_spec.rb +110 -0
  44. data/spec/public/shared/property_shared_spec.rb +1 -1
  45. data/spec/rcov.opts +1 -1
  46. data/spec/semipublic/associations/many_to_many_spec.rb +3 -0
  47. data/spec/semipublic/associations/many_to_one_spec.rb +2 -0
  48. data/spec/semipublic/associations/one_to_many_spec.rb +2 -0
  49. data/spec/semipublic/associations/one_to_one_spec.rb +2 -0
  50. data/spec/semipublic/associations/relationship_spec.rb +6 -0
  51. data/spec/semipublic/query/conditions/comparison_spec.rb +3 -0
  52. data/spec/semipublic/query/conditions/operation_spec.rb +1 -0
  53. data/spec/semipublic/query/path_spec.rb +2 -0
  54. data/spec/semipublic/query_spec.rb +2 -3
  55. data/spec/semipublic/resource/state/clean_spec.rb +2 -1
  56. data/spec/semipublic/resource/state/deleted_spec.rb +2 -1
  57. data/spec/semipublic/resource/state/dirty_spec.rb +42 -20
  58. data/spec/semipublic/resource/state/immutable_spec.rb +7 -1
  59. data/spec/semipublic/resource/state/transient_spec.rb +69 -40
  60. data/spec/semipublic/resource/state_spec.rb +72 -66
  61. data/spec/semipublic/shared/property_shared_spec.rb +1 -0
  62. data/spec/semipublic/shared/resource_shared_spec.rb +1 -0
  63. data/spec/spec_helper.rb +0 -10
  64. data/tasks/spec.rake +3 -0
  65. metadata +9 -7
@@ -473,7 +473,7 @@ module DataMapper
473
473
  #
474
474
  # @api public
475
475
  def unique?
476
- @unique
476
+ !!@unique
477
477
  end
478
478
 
479
479
  # Returns the hash of the property name
@@ -491,11 +491,11 @@ module DataMapper
491
491
 
492
492
  # Returns index name if property has index.
493
493
  #
494
- # @return [true, Symbol, Array, nil]
494
+ # @return [Boolean, Symbol, Array]
495
495
  # returns true if property is indexed by itself
496
496
  # returns a Symbol if the property is indexed with other properties
497
497
  # returns an Array if the property belongs to multiple indexes
498
- # returns nil if the property does not belong to any indexes
498
+ # returns false if the property does not belong to any indexes
499
499
  #
500
500
  # @api public
501
501
  def index
@@ -505,11 +505,11 @@ module DataMapper
505
505
  # Returns true if property has unique index. Serial properties and
506
506
  # keys are unique by default.
507
507
  #
508
- # @return [true, Symbol, Array, nil]
508
+ # @return [Boolean, Symbol, Array]
509
509
  # returns true if property is indexed by itself
510
510
  # returns a Symbol if the property is indexed with other properties
511
511
  # returns an Array if the property belongs to multiple indexes
512
- # returns nil if the property does not belong to any indexes
512
+ # returns false if the property does not belong to any indexes
513
513
  #
514
514
  # @api public
515
515
  def unique_index
@@ -794,7 +794,7 @@ module DataMapper
794
794
 
795
795
  @repository_name = model.repository_name
796
796
  @model = model
797
- @name = name.to_s.sub(/\?$/, '').to_sym
797
+ @name = name.to_s.chomp('?').to_sym
798
798
  @options = predefined_options.merge(options).freeze
799
799
  @instance_variable_name = "@#{@name}".freeze
800
800
 
@@ -804,13 +804,13 @@ module DataMapper
804
804
  @default = @options[:default]
805
805
 
806
806
  @serial = @options.fetch(:serial, false)
807
- @key = @options.fetch(:key, @serial || false)
807
+ @key = @options.fetch(:key, @serial)
808
+ @unique = @options.fetch(:unique, @key ? :key : false)
808
809
  @required = @options.fetch(:required, @key)
809
810
  @allow_nil = @options.fetch(:allow_nil, !@required)
810
811
  @allow_blank = @options.fetch(:allow_blank, !@required)
811
- @index = @options.fetch(:index, nil)
812
- @unique_index = @options.fetch(:unique_index, nil)
813
- @unique = @options.fetch(:unique, @serial || @key || false)
812
+ @index = @options.fetch(:index, false)
813
+ @unique_index = @options.fetch(:unique_index, @unique)
814
814
  @lazy = @options.fetch(:lazy, false) && !@key
815
815
 
816
816
  determine_visibility
data/lib/dm-core/query.rb CHANGED
@@ -324,10 +324,10 @@ module DataMapper
324
324
  # @api semipublic
325
325
  def reverse!
326
326
  # reverse the sort order
327
- @order.map! { |direction| direction.reverse! }
327
+ @order.map! { |direction| direction.dup.reverse! }
328
328
 
329
329
  # copy the order to the options
330
- @options = @options.merge(:order => @order.map { |direction| direction.dup }).freeze
330
+ @options = @options.merge(:order => @order).freeze
331
331
 
332
332
  self
333
333
  end
@@ -1171,22 +1171,12 @@ module DataMapper
1171
1171
  add_condition(condition)
1172
1172
  end
1173
1173
 
1174
- if RUBY_VERSION >= '1.9'
1175
- def equality_operator_for_type(bind_value)
1176
- case bind_value
1177
- when Enumerable then :in
1178
- when Regexp then :regexp
1179
- else :eql
1180
- end
1181
- end
1182
- else
1183
- def equality_operator_for_type(bind_value)
1184
- case bind_value
1185
- when String then :eql
1186
- when Enumerable then :in
1187
- when Regexp then :regexp
1188
- else :eql
1189
- end
1174
+ def equality_operator_for_type(bind_value)
1175
+ case bind_value
1176
+ when Model, String then :eql
1177
+ when Enumerable then :in
1178
+ when Regexp then :regexp
1179
+ else :eql
1190
1180
  end
1191
1181
  end
1192
1182
 
@@ -755,8 +755,8 @@ module DataMapper
755
755
  # attribute values used in the new instance
756
756
  #
757
757
  # @api public
758
- def initialize(attributes = {}, &block) # :nodoc:
759
- self.attributes = attributes
758
+ def initialize(attributes = {}) # :nodoc:
759
+ self.attributes = attributes || {}
760
760
  end
761
761
 
762
762
  # @api private
@@ -1009,7 +1009,7 @@ module DataMapper
1009
1009
  #
1010
1010
  # @api private
1011
1011
  def _update
1012
- self.persisted_state = persisted_state.commit if valid_attributes?
1012
+ self.persisted_state = persisted_state.commit
1013
1013
  clean?
1014
1014
  end
1015
1015
 
@@ -1168,14 +1168,6 @@ module DataMapper
1168
1168
  persisted_state.__send__(:set_default_value, subject)
1169
1169
  end
1170
1170
 
1171
- # @api private
1172
- def valid_attributes?
1173
- original_attributes.each_key do |property|
1174
- return false if property.kind_of?(Property) && !property.valid?(property.get!(self))
1175
- end
1176
- true
1177
- end
1178
-
1179
1171
  # Execute all the queued up hooks for a given type and name
1180
1172
  #
1181
1173
  # @param [Symbol] type
@@ -3,6 +3,10 @@ module DataMapper
3
3
 
4
4
  # the state of the resource (abstract)
5
5
  class State
6
+ extend Equalizer
7
+
8
+ equalize :resource
9
+
6
10
  attr_reader :resource
7
11
 
8
12
  def initialize(resource)
@@ -30,20 +34,6 @@ module DataMapper
30
34
  raise NotImplementedError, "#{self.class}#rollback should be implemented"
31
35
  end
32
36
 
33
- def eql?(other)
34
- instance_of?(other.class) &&
35
- hash == other.hash
36
- end
37
-
38
- def ==(other)
39
- self.class <=> other.class &&
40
- hash == other.hash
41
- end
42
-
43
- def hash
44
- resource.object_id.hash
45
- end
46
-
47
37
  private
48
38
 
49
39
  def model
@@ -70,8 +60,15 @@ module DataMapper
70
60
  identity_map[resource.key] = resource
71
61
  end
72
62
 
73
- def reset_original_attributes
74
- original_attributes.clear
63
+ def set_child_keys
64
+ relationships.each do |relationship|
65
+ set_child_key(relationship)
66
+ end
67
+ end
68
+
69
+ def set_child_key(relationship)
70
+ return unless relationship.loaded?(resource) && relationship.respond_to?(:resource_for)
71
+ set(relationship, get(relationship))
75
72
  end
76
73
 
77
74
  end # class State
@@ -17,11 +17,14 @@ module DataMapper
17
17
 
18
18
  def commit
19
19
  remove_from_identity_map
20
+ set_child_keys
21
+ return self unless valid_attributes?
20
22
  update_resource
21
23
  reset_original_attributes
22
24
  reset_resource_key
23
- add_to_identity_map
24
25
  Clean.new(resource)
26
+ ensure
27
+ add_to_identity_map
25
28
  end
26
29
 
27
30
  def rollback
@@ -80,6 +83,13 @@ module DataMapper
80
83
  original_attributes.clear
81
84
  end
82
85
 
86
+ def valid_attributes?
87
+ original_attributes.each_key do |property|
88
+ return false if property.kind_of?(Property) && !property.valid?(property.get!(resource))
89
+ end
90
+ true
91
+ end
92
+
83
93
  end # class Dirty
84
94
  end # class State
85
95
  end # module Resource
@@ -19,10 +19,11 @@ module DataMapper
19
19
  end
20
20
 
21
21
  def commit
22
+ set_child_keys
22
23
  set_default_values
24
+ return self unless valid_attributes?
23
25
  create_resource
24
26
  set_repository
25
- reset_original_attributes
26
27
  add_to_identity_map
27
28
  Clean.new(resource)
28
29
  end
@@ -64,6 +65,13 @@ module DataMapper
64
65
  resource.instance_variable_set(:@_repository, repository)
65
66
  end
66
67
 
68
+ def valid_attributes?
69
+ properties.all? do |property|
70
+ value = get(property)
71
+ property.serial? && value.nil? || property.valid?(value)
72
+ end
73
+ end
74
+
67
75
  end # class Transient
68
76
  end # class State
69
77
  end # module Resource
@@ -26,6 +26,11 @@ module DataMapper
26
26
 
27
27
  # create all tables and constraints before each spec
28
28
  if @repository.respond_to?(:auto_migrate!)
29
+ # If we are going to auto-migrate, we must also finalize
30
+ @repository.scope do
31
+ DataMapper.finalize
32
+ end
33
+
29
34
  @repository.auto_migrate!
30
35
  end
31
36
  end
@@ -34,6 +34,8 @@ share_examples_for 'An Adapter' do
34
34
  property :striped, Boolean
35
35
  end
36
36
 
37
+ DataMapper.finalize
38
+
37
39
  # create all tables and constraints before each spec
38
40
  if @repository.respond_to?(:auto_migrate!)
39
41
  Heffalump.auto_migrate!
@@ -1177,37 +1177,6 @@ share_examples_for 'A public Resource' do
1177
1177
  end
1178
1178
  end
1179
1179
 
1180
- describe 'invalid resources' do
1181
- before do
1182
- class ::EmptyObject
1183
- include DataMapper::Resource
1184
- end
1185
-
1186
- class ::KeylessObject
1187
- include DataMapper::Resource
1188
- property :name, String
1189
- end
1190
- end
1191
-
1192
- it 'should raise an error for a resource without attributes' do
1193
- lambda { EmptyObject.new }.should raise_error
1194
- end
1195
-
1196
- it 'should raise an error for a resource without a key' do
1197
- lambda { KeylessObject.new }.should raise_error
1198
- end
1199
-
1200
- after do
1201
- # clean out invalid models so that global model cleanup
1202
- # does not throw an exception when working with models
1203
- # in an invalid state
1204
- [ EmptyObject, KeylessObject ].each do |model|
1205
- Object.send(:remove_const, model.name.to_sym)
1206
- DataMapper::Model.descendants.delete(model)
1207
- end
1208
- end
1209
- end
1210
-
1211
1180
  describe 'lazy loading' do
1212
1181
  before :all do
1213
1182
  rescue_if @skip do
@@ -1,3 +1,3 @@
1
1
  module DataMapper
2
- VERSION = '1.0.0.rc2'
2
+ VERSION = '1.0.0.rc3'
3
3
  end
@@ -38,6 +38,8 @@ describe 'Many to Many Associations read across multiple join associations' do
38
38
 
39
39
  has n, :sale_items
40
40
  end
41
+
42
+ DataMapper.finalize
41
43
  end
42
44
 
43
45
  supported_by :all do
@@ -66,7 +66,7 @@ end
66
66
  @publication_model = Blog::Publication
67
67
 
68
68
  # initialize the join model
69
- Blog::Author.relationships(:default)[:articles].through
69
+ DataMapper.finalize
70
70
 
71
71
  @join_model = Blog::ArticleAuthor
72
72
  end
@@ -157,6 +157,7 @@ end
157
157
  @author_model = Blog::Author
158
158
  @article_model = Blog::Article
159
159
  @publication_model = Blog::Publication
160
+ DataMapper.finalize
160
161
 
161
162
  @join_model = Blog::Site
162
163
  end
@@ -59,6 +59,7 @@ describe 'Many to One Associations' do
59
59
 
60
60
  property :name, String, :key => true, :default => 'a default value'
61
61
  end
62
+ DataMapper.finalize
62
63
 
63
64
  @user_model = Blog::User
64
65
  @author_model = Blog::Author
@@ -20,6 +20,7 @@ describe 'Many to One Associations when foreign key is part of a composite key,
20
20
 
21
21
  has n, :many_models, :child_key => [ :integer_key ]
22
22
  end
23
+ DataMapper.finalize
23
24
  end
24
25
 
25
26
  supported_by :all do
@@ -44,6 +44,8 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_hel
44
44
  end
45
45
  end
46
46
 
47
+ DataMapper.finalize
48
+
47
49
  @author_model = Blog::Author
48
50
  @article_model = Blog::Article
49
51
  @publication_model = Blog::Publication
@@ -58,6 +58,7 @@ describe 'One to One Associations' do
58
58
 
59
59
  property :name, String, :key => true, :default => 'a default value'
60
60
  end
61
+ DataMapper.finalize
61
62
 
62
63
  @user_model = Blog::User
63
64
  @author_model = Blog::Author
@@ -148,6 +149,7 @@ describe 'One to One Through Associations' do
148
149
 
149
150
  property :name, String, :key => true, :default => 'a default value'
150
151
  end
152
+ DataMapper.finalize
151
153
 
152
154
  @referral_model = Blog::Referral
153
155
  @user_model = Blog::User
@@ -22,6 +22,7 @@ describe 'One to One Associations when foreign key is part of a composite key an
22
22
 
23
23
  belongs_to :parent_model, :child_key => [ :integer_key, :boolean_key ]
24
24
  end
25
+ DataMapper.finalize
25
26
  end
26
27
 
27
28
  supported_by :all do
@@ -34,6 +34,8 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
34
34
  end
35
35
  end
36
36
 
37
+ DataMapper.finalize
38
+
37
39
  @article_model = Blog::Article
38
40
  @publication_model = Blog::Publication
39
41
  end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe DataMapper do
4
+ describe '.setup' do
5
+ it "should not raise with valid models" do
6
+ class ::ValidObject
7
+ include DataMapper::Resource
8
+ property :id, Integer, :key => true
9
+ end
10
+ lambda { DataMapper.finalize }.should_not raise_error
11
+ DataMapper::Model.descendants.delete(ValidObject)
12
+ Object.send(:remove_const, :ValidObject)
13
+ end
14
+
15
+ it "should raise on an empty model" do
16
+ class ::EmptyObject
17
+ include DataMapper::Resource
18
+ end
19
+ lambda { DataMapper.finalize }.should raise_error
20
+ DataMapper::Model.descendants.delete(EmptyObject)
21
+ Object.send(:remove_const, :EmptyObject)
22
+ end
23
+
24
+ it "should raise on a keyless model" do
25
+ class ::KeylessObject
26
+ include DataMapper::Resource
27
+ property :name, String
28
+ end
29
+ lambda { DataMapper.finalize }.should raise_error
30
+ DataMapper::Model.descendants.delete(KeylessObject)
31
+ Object.send(:remove_const, :KeylessObject)
32
+ end
33
+ end
34
+ end
@@ -12,6 +12,7 @@ describe DataMapper::Model::Hook do
12
12
  end
13
13
 
14
14
  class ::ModelHookSpecsSubclass < ModelHookSpecs; end
15
+ DataMapper.finalize
15
16
  end
16
17
 
17
18
  before :all do