dm-core 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
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