dm-core 0.10.0 → 0.10.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.
Files changed (39) hide show
  1. data/History.txt +25 -5
  2. data/Manifest.txt +1 -0
  3. data/README.txt +67 -23
  4. data/Rakefile +0 -2
  5. data/deps.rip +1 -1
  6. data/dm-core.gemspec +6 -6
  7. data/lib/dm-core/adapters/abstract_adapter.rb +3 -76
  8. data/lib/dm-core/adapters/data_objects_adapter.rb +8 -39
  9. data/lib/dm-core/associations/many_to_many.rb +28 -16
  10. data/lib/dm-core/associations/many_to_one.rb +1 -45
  11. data/lib/dm-core/associations/one_to_many.rb +1 -38
  12. data/lib/dm-core/associations/relationship.rb +43 -20
  13. data/lib/dm-core/collection.rb +33 -32
  14. data/lib/dm-core/model/property.rb +8 -8
  15. data/lib/dm-core/model/relationship.rb +10 -12
  16. data/lib/dm-core/property.rb +20 -85
  17. data/lib/dm-core/property_set.rb +8 -8
  18. data/lib/dm-core/query/conditions/comparison.rb +13 -71
  19. data/lib/dm-core/query/conditions/operation.rb +73 -47
  20. data/lib/dm-core/query/operator.rb +3 -45
  21. data/lib/dm-core/query/path.rb +5 -41
  22. data/lib/dm-core/query.rb +37 -108
  23. data/lib/dm-core/repository.rb +3 -79
  24. data/lib/dm-core/resource.rb +54 -49
  25. data/lib/dm-core/support/chainable.rb +0 -2
  26. data/lib/dm-core/support/equalizer.rb +23 -0
  27. data/lib/dm-core/types/object.rb +4 -4
  28. data/lib/dm-core/version.rb +1 -1
  29. data/lib/dm-core.rb +3 -11
  30. data/spec/public/model/relationship_spec.rb +4 -4
  31. data/spec/public/property_spec.rb +5 -449
  32. data/spec/public/sel_spec.rb +52 -2
  33. data/spec/public/shared/collection_shared_spec.rb +79 -26
  34. data/spec/public/shared/finder_shared_spec.rb +6 -6
  35. data/spec/public/shared/resource_shared_spec.rb +2 -2
  36. data/spec/semipublic/property_spec.rb +524 -9
  37. data/spec/semipublic/query_spec.rb +6 -6
  38. data/tasks/hoe.rb +2 -2
  39. metadata +24 -4
@@ -21,7 +21,7 @@ module DataMapper
21
21
  # @deprecated
22
22
  def self.descendants
23
23
  warn "DataMapper::Resource.descendants is deprecated, use DataMapper::Model.descendants instead (#{caller[0]})"
24
- DataMapper::Model.descendants
24
+ Model.descendants
25
25
  end
26
26
 
27
27
  # Deprecated API for updating attributes and saving Resource
@@ -118,6 +118,16 @@ module DataMapper
118
118
  @saved == true
119
119
  end
120
120
 
121
+ # Checks if this Resource instance is destroyed
122
+ #
123
+ # @return [Boolean]
124
+ # true if the resource has been destroyed
125
+ #
126
+ # @api public
127
+ def destroyed?
128
+ @destroyed == true
129
+ end
130
+
121
131
  # Checks if the resource has no changes to save
122
132
  #
123
133
  # @return [Boolean]
@@ -283,7 +293,7 @@ module DataMapper
283
293
  # @api public
284
294
  def reload
285
295
  if saved?
286
- reload_attributes(loaded_properties)
296
+ eager_load(loaded_properties)
287
297
  child_relationships.each { |relationship| relationship.get!(self).reload }
288
298
  end
289
299
 
@@ -364,13 +374,13 @@ module DataMapper
364
374
  # @api public
365
375
  def destroy!
366
376
  if saved? && repository.delete(Collection.new(query, [ self ])) == 1
377
+ @destroyed = true
367
378
  @collection.delete(self) if @collection
368
379
  reset
369
380
  freeze
370
- true
371
- else
372
- false
373
381
  end
382
+
383
+ destroyed?
374
384
  end
375
385
 
376
386
  # Compares another Resource for equality
@@ -388,9 +398,7 @@ module DataMapper
388
398
  # @api public
389
399
  def eql?(other)
390
400
  return true if equal?(other)
391
- return false unless instance_of?(other.class)
392
-
393
- cmp?(other, :eql?)
401
+ instance_of?(other.class) && cmp?(other, :eql?)
394
402
  end
395
403
 
396
404
  # Compares another Resource for equivalency
@@ -408,8 +416,8 @@ module DataMapper
408
416
  # @api public
409
417
  def ==(other)
410
418
  return true if equal?(other)
411
- return false unless other.respond_to?(:model) && model.base_model.equal?(other.model.base_model)
412
-
419
+ other.respond_to?(:model) &&
420
+ model.base_model.equal?(other.model.base_model) &&
413
421
  cmp?(other, :==)
414
422
  end
415
423
 
@@ -429,7 +437,7 @@ module DataMapper
429
437
  raise ArgumentError, "Cannot compare a #{other.model} instance with a #{model} instance"
430
438
  end
431
439
  cmp = 0
432
- model.default_order(repository_name).map do |direction|
440
+ model.default_order(repository_name).each do |direction|
433
441
  cmp = direction.get(self) <=> direction.get(other)
434
442
  break if cmp != 0
435
443
  end
@@ -506,27 +514,6 @@ module DataMapper
506
514
  properties[name].loaded?(self)
507
515
  end
508
516
 
509
- # Fetches all the names of the attributes that have been loaded,
510
- # even if they are lazy but have been called
511
- #
512
- # @example
513
- # class Foo
514
- # include DataMapper::Resource
515
- #
516
- # property :name, String
517
- # property :description, Text, :lazy => false
518
- # end
519
- #
520
- # Foo.new.loaded_properties #=> [ #<Property @model=Foo @name=:name> ]
521
- #
522
- # @return [Array(Property)]
523
- # names of attributes that have been loaded
524
- #
525
- # @api private
526
- def loaded_properties
527
- properties.select { |property| property.loaded?(self) }
528
- end
529
-
530
517
  # Checks if an attribute has unsaved changes
531
518
  #
532
519
  # @param [Symbol] name
@@ -690,10 +677,9 @@ module DataMapper
690
677
  model.relationships(repository_name)
691
678
  end
692
679
 
693
- # Returns identity map of repository this object
694
- # was loaded from
680
+ # Returns the identity map for the model from the repository
695
681
  #
696
- # @return [DataMapper::IdentityMap]
682
+ # @return [IdentityMap]
697
683
  # identity map of repository this object was loaded from
698
684
  #
699
685
  # @api semipublic
@@ -701,26 +687,41 @@ module DataMapper
701
687
  repository.identity_map(model)
702
688
  end
703
689
 
704
- # Reloads attributes that belong to given lazy loading
705
- # context, and not yet loaded
690
+ # Fetches all the names of the attributes that have been loaded,
691
+ # even if they are lazy but have been called
692
+ #
693
+ # @return [Array<Property>]
694
+ # names of attributes that have been loaded
706
695
  #
707
696
  # @api private
708
- def lazy_load(property_names)
709
- reload_attributes(properties.in_context(property_names) - loaded_properties)
697
+ def loaded_properties
698
+ properties.select { |property| property.loaded?(self) }
699
+ end
700
+
701
+ # Lazy loads attributes not yet loaded
702
+ #
703
+ # @param [Array<Property>] fields
704
+ # the properties to reload
705
+ #
706
+ # @return [self]
707
+ #
708
+ # @api private
709
+ def lazy_load(fields)
710
+ eager_load(fields - loaded_properties)
710
711
  end
711
712
 
712
713
  # Reloads specified attributes
713
714
  #
714
- # @param [Enumerable(Symbol)] attributes
715
- # name(s) of attribute(s) to reload
715
+ # @param [Array<Property>] fields
716
+ # the properties to reload
716
717
  #
717
718
  # @return [Resource]
718
719
  # the receiver, the current Resource instance
719
720
  #
720
721
  # @api private
721
- def reload_attributes(attributes)
722
- unless attributes.empty? || new?
723
- collection.reload(:fields => attributes)
722
+ def eager_load(fields)
723
+ unless fields.empty? || new?
724
+ collection.reload(:fields => fields)
724
725
  end
725
726
 
726
727
  self
@@ -751,9 +752,9 @@ module DataMapper
751
752
  parent_relationships
752
753
  end
753
754
 
754
- # Returns array of child relationships for which this resource is parent and is loaded
755
+ # Returns loaded child relationships
755
756
  #
756
- # @return [Array<DataMapper::Associations::OneToMany::Relationship>]
757
+ # @return [Array<Associations::OneToMany::Relationship>]
757
758
  # array of child relationships for which this resource is parent and is loaded
758
759
  #
759
760
  # @api private
@@ -770,14 +771,13 @@ module DataMapper
770
771
  end
771
772
 
772
773
  many_to_many, other = child_relationships.partition do |relationship|
773
- relationship.kind_of?(DataMapper::Associations::ManyToMany::Relationship)
774
+ relationship.kind_of?(Associations::ManyToMany::Relationship)
774
775
  end
775
776
 
776
777
  many_to_many + other
777
778
  end
778
779
 
779
- # Saves this Resource instance to the repository,
780
- # setting default values for any unset properties
780
+ # Creates the resource with default values
781
781
  #
782
782
  # If resource is not dirty or a new (not yet saved),
783
783
  # this method returns false
@@ -878,6 +878,11 @@ module DataMapper
878
878
 
879
879
  # Raises an exception if #update is performed on a dirty resource
880
880
  #
881
+ # @param [Symbol] method
882
+ # the name of the method to use in the exception
883
+ #
884
+ # @return [undefined]
885
+ #
881
886
  # @raise [UpdateConflictError]
882
887
  # raise if the resource is dirty
883
888
  #
@@ -1,5 +1,3 @@
1
- # TODO: move this to Extlib::Chainable
2
-
3
1
  module DataMapper
4
2
  module Chainable
5
3
 
@@ -0,0 +1,23 @@
1
+ module DataMapper
2
+ module Equalizer
3
+ def equalize(*methods)
4
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
5
+ def eql?(other)
6
+ return true if equal?(other)
7
+ instance_of?(other.class) &&
8
+ #{methods.map { |method| "#{method}.eql?(other.#{method})" }.join(' && ')}
9
+ end
10
+
11
+ def ==(other)
12
+ return true if equal?(other)
13
+ #{methods.map { |method| "other.respond_to?(#{method.inspect})" }.join(' && ')} &&
14
+ #{methods.map { |method| "#{method} == other.#{method}" }.join(' && ')}
15
+ end
16
+
17
+ def hash
18
+ [ #{methods.join(', ')} ].hash
19
+ end
20
+ RUBY
21
+ end
22
+ end
23
+ end
@@ -2,8 +2,8 @@ module DataMapper
2
2
  module Types
3
3
  class Object < Type
4
4
  primitive String
5
- size 65535
6
- lazy true
5
+ length 65535
6
+ lazy true
7
7
 
8
8
  # TODO: document
9
9
  # @api private
@@ -14,13 +14,13 @@ module DataMapper
14
14
  # TODO: document
15
15
  # @api private
16
16
  def self.dump(value, property)
17
- Base64.encode64(Marshal.dump(value))
17
+ [ Marshal.dump(value) ].pack('m')
18
18
  end
19
19
 
20
20
  # TODO: document
21
21
  # @api private
22
22
  def self.load(value, property)
23
- value.nil? ? nil : Marshal.load(Base64.decode64(value))
23
+ Marshal.load(value.unpack('m').first) unless value.nil?
24
24
  end
25
25
  end
26
26
  end
@@ -1,3 +1,3 @@
1
1
  module DataMapper
2
- VERSION = '0.10.0'.freeze
2
+ VERSION = '0.10.1'.freeze
3
3
  end
data/lib/dm-core.rb CHANGED
@@ -1,13 +1,4 @@
1
- # This file begins the loading sequence.
2
- #
3
- # Quick Overview:
4
- # * Requires fastthread, support libs, and base.
5
- # * Sets the application root and environment for compatibility with frameworks
6
- # such as Rails or Merb.
7
- #
8
-
9
1
  require 'addressable/uri'
10
- require 'base64'
11
2
  require 'bigdecimal'
12
3
  require 'bigdecimal/util'
13
4
  require 'date'
@@ -27,6 +18,7 @@ dir = Pathname(__FILE__).dirname.expand_path / 'dm-core'
27
18
 
28
19
  require dir / 'support' / 'chainable'
29
20
  require dir / 'support' / 'deprecate'
21
+ require dir / 'support' / 'equalizer'
30
22
 
31
23
  require dir / 'model'
32
24
  require dir / 'model' / 'descendant_set'
@@ -117,9 +109,9 @@ DataMapper::Logger.new(StringIO.new, :fatal)
117
109
  # === Logging
118
110
  # To turn on error logging to STDOUT, issue:
119
111
  #
120
- # DataMapper::Logger.new(STDOUT, :debug)
112
+ # DataMapper::Logger.new($stdout, :debug)
121
113
  #
122
- # You can pass a file location ("/path/to/log/file.log") in place of STDOUT.
114
+ # You can pass a file location ("/path/to/log/file.log") in place of $stdout.
123
115
  # see DataMapper::Logger for more information.
124
116
  #
125
117
  module DataMapper
@@ -799,8 +799,8 @@ describe DataMapper::Associations do
799
799
  @engine_relationship = ElectricCar.relationships(@repository.name)[:engine]
800
800
  end
801
801
 
802
- it 'should have a source model equal to the descendant' do
803
- @engine_relationship.source_model.should equal(ElectricCar)
802
+ it 'should have a source model equal to the ancestor' do
803
+ @engine_relationship.source_model.should equal(Car)
804
804
  end
805
805
 
806
806
  it 'should have a child key prefix the same as the inverse relationship' do
@@ -823,8 +823,8 @@ describe DataMapper::Associations do
823
823
  @engine_relationship = ElectricCar.relationships(@repository.name)[:engine]
824
824
  end
825
825
 
826
- it 'should have a source model equal to the descendant' do
827
- @engine_relationship.source_model.should equal(ElectricCar)
826
+ it 'should have a source model equal to the ancestor' do
827
+ @engine_relationship.source_model.should equal(Car)
828
828
  end
829
829
 
830
830
  it 'should have a child key prefix inferred from the source model name' do