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.
- data/History.txt +25 -5
- data/Manifest.txt +1 -0
- data/README.txt +67 -23
- data/Rakefile +0 -2
- data/deps.rip +1 -1
- data/dm-core.gemspec +6 -6
- data/lib/dm-core/adapters/abstract_adapter.rb +3 -76
- data/lib/dm-core/adapters/data_objects_adapter.rb +8 -39
- data/lib/dm-core/associations/many_to_many.rb +28 -16
- data/lib/dm-core/associations/many_to_one.rb +1 -45
- data/lib/dm-core/associations/one_to_many.rb +1 -38
- data/lib/dm-core/associations/relationship.rb +43 -20
- data/lib/dm-core/collection.rb +33 -32
- data/lib/dm-core/model/property.rb +8 -8
- data/lib/dm-core/model/relationship.rb +10 -12
- data/lib/dm-core/property.rb +20 -85
- data/lib/dm-core/property_set.rb +8 -8
- data/lib/dm-core/query/conditions/comparison.rb +13 -71
- data/lib/dm-core/query/conditions/operation.rb +73 -47
- data/lib/dm-core/query/operator.rb +3 -45
- data/lib/dm-core/query/path.rb +5 -41
- data/lib/dm-core/query.rb +37 -108
- data/lib/dm-core/repository.rb +3 -79
- data/lib/dm-core/resource.rb +54 -49
- data/lib/dm-core/support/chainable.rb +0 -2
- data/lib/dm-core/support/equalizer.rb +23 -0
- data/lib/dm-core/types/object.rb +4 -4
- data/lib/dm-core/version.rb +1 -1
- data/lib/dm-core.rb +3 -11
- data/spec/public/model/relationship_spec.rb +4 -4
- data/spec/public/property_spec.rb +5 -449
- data/spec/public/sel_spec.rb +52 -2
- data/spec/public/shared/collection_shared_spec.rb +79 -26
- data/spec/public/shared/finder_shared_spec.rb +6 -6
- data/spec/public/shared/resource_shared_spec.rb +2 -2
- data/spec/semipublic/property_spec.rb +524 -9
- data/spec/semipublic/query_spec.rb +6 -6
- data/tasks/hoe.rb +2 -2
- metadata +24 -4
@@ -6,7 +6,7 @@ module DataMapper
|
|
6
6
|
class Relationship
|
7
7
|
include Extlib::Assertions
|
8
8
|
|
9
|
-
OPTIONS = [ :child_repository_name, :parent_repository_name, :child_key, :parent_key, :min, :max, :inverse ].to_set
|
9
|
+
OPTIONS = [ :child_repository_name, :parent_repository_name, :child_key, :parent_key, :min, :max, :inverse, :reader_visibility, :writer_visibility ].to_set
|
10
10
|
|
11
11
|
# Relationship name
|
12
12
|
#
|
@@ -94,6 +94,22 @@ module DataMapper
|
|
94
94
|
# @api semipublic
|
95
95
|
attr_reader :max
|
96
96
|
|
97
|
+
# Returns the visibility for the source accessor
|
98
|
+
#
|
99
|
+
# @return [Symbol]
|
100
|
+
# the visibility for the accessor added to the source
|
101
|
+
#
|
102
|
+
# @api semipublic
|
103
|
+
attr_reader :reader_visibility
|
104
|
+
|
105
|
+
# Returns the visibility for the source mutator
|
106
|
+
#
|
107
|
+
# @return [Symbol]
|
108
|
+
# the visibility for the mutator added to the source
|
109
|
+
#
|
110
|
+
# @api semipublic
|
111
|
+
attr_reader :writer_visibility
|
112
|
+
|
97
113
|
# Returns query options for relationship.
|
98
114
|
#
|
99
115
|
# For this base class, always returns query options
|
@@ -352,7 +368,6 @@ module DataMapper
|
|
352
368
|
def ==(other)
|
353
369
|
return true if equal?(other)
|
354
370
|
return false if kind_of_inverse?(other)
|
355
|
-
|
356
371
|
other.respond_to?(:cmp_repository?, true) &&
|
357
372
|
other.respond_to?(:cmp_model?, true) &&
|
358
373
|
other.respond_to?(:cmp_key?, true) &&
|
@@ -427,6 +442,8 @@ module DataMapper
|
|
427
442
|
@parent_properties = @options[:parent_key].try_dup.freeze
|
428
443
|
@min = @options[:min]
|
429
444
|
@max = @options[:max]
|
445
|
+
@reader_visibility = @options.fetch(:reader_visibility, :public)
|
446
|
+
@writer_visibility = @options.fetch(:writer_visibility, :public)
|
430
447
|
|
431
448
|
# TODO: normalize the @query to become :conditions => AndOperation
|
432
449
|
# - Property/Relationship/Path should be left alone
|
@@ -478,22 +495,38 @@ module DataMapper
|
|
478
495
|
object
|
479
496
|
end
|
480
497
|
|
481
|
-
#
|
482
|
-
#
|
483
|
-
# Must be implemented by subclasses.
|
498
|
+
# Dynamically defines reader method for source side of association
|
499
|
+
# (for instance, method article for model Paragraph)
|
484
500
|
#
|
485
501
|
# @api semipublic
|
486
502
|
def create_reader
|
487
|
-
|
503
|
+
reader_name = name.to_s
|
504
|
+
|
505
|
+
return if source_model.resource_method_defined?(reader_name)
|
506
|
+
|
507
|
+
source_model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
508
|
+
#{reader_visibility} # public
|
509
|
+
def #{reader_name}(query = nil) # def author(query = nil)
|
510
|
+
relationships[#{name.inspect}].get(self, query) # relationships[:author].get(self, query)
|
511
|
+
end # end
|
512
|
+
RUBY
|
488
513
|
end
|
489
514
|
|
490
|
-
#
|
491
|
-
#
|
492
|
-
# Must be implemented by subclasses.
|
515
|
+
# Dynamically defines writer method for source side of association
|
516
|
+
# (for instance, method article= for model Paragraph)
|
493
517
|
#
|
494
518
|
# @api semipublic
|
495
519
|
def create_writer
|
496
|
-
|
520
|
+
writer_name = "#{name}="
|
521
|
+
|
522
|
+
return if source_model.resource_method_defined?(writer_name)
|
523
|
+
|
524
|
+
source_model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
525
|
+
#{writer_visibility} # public
|
526
|
+
def #{writer_name}(target) # def author=(target)
|
527
|
+
relationships[#{name.inspect}].set(self, target) # relationships[:author].set(self, target)
|
528
|
+
end # end
|
529
|
+
RUBY
|
497
530
|
end
|
498
531
|
|
499
532
|
# Sets the association targets in the resource
|
@@ -569,16 +602,6 @@ module DataMapper
|
|
569
602
|
options.only(*OPTIONS - [ :min, :max ]).update(:inverse => self)
|
570
603
|
end
|
571
604
|
|
572
|
-
# TODO: document
|
573
|
-
# @api private
|
574
|
-
def options_with_inverse
|
575
|
-
if child_model? && parent_model?
|
576
|
-
options.merge(:inverse => inverse)
|
577
|
-
else
|
578
|
-
options.merge(:inverse => inverse_name)
|
579
|
-
end
|
580
|
-
end
|
581
|
-
|
582
605
|
# TODO: document
|
583
606
|
# @api private
|
584
607
|
def kind_of_inverse?(other)
|
data/lib/dm-core/collection.rb
CHANGED
@@ -534,9 +534,10 @@ module DataMapper
|
|
534
534
|
# the last Resource in the Collection
|
535
535
|
#
|
536
536
|
# @api public
|
537
|
-
def pop
|
538
|
-
|
539
|
-
|
537
|
+
def pop(*)
|
538
|
+
if removed = super
|
539
|
+
resources_removed(removed)
|
540
|
+
end
|
540
541
|
end
|
541
542
|
|
542
543
|
# Removes and returns the first Resource in the Collection
|
@@ -545,9 +546,10 @@ module DataMapper
|
|
545
546
|
# the first Resource in the Collection
|
546
547
|
#
|
547
548
|
# @api public
|
548
|
-
def shift
|
549
|
-
|
550
|
-
|
549
|
+
def shift(*)
|
550
|
+
if removed = super
|
551
|
+
resources_removed(removed)
|
552
|
+
end
|
551
553
|
end
|
552
554
|
|
553
555
|
# Remove Resource from the Collection
|
@@ -566,8 +568,9 @@ module DataMapper
|
|
566
568
|
#
|
567
569
|
# @api public
|
568
570
|
def delete(resource)
|
569
|
-
|
570
|
-
|
571
|
+
if resource = super
|
572
|
+
resource_removed(resource)
|
573
|
+
end
|
571
574
|
end
|
572
575
|
|
573
576
|
# Remove Resource from the Collection by offset
|
@@ -586,8 +589,9 @@ module DataMapper
|
|
586
589
|
#
|
587
590
|
# @api public
|
588
591
|
def delete_at(offset)
|
589
|
-
|
590
|
-
|
592
|
+
if resource = super
|
593
|
+
resource_removed(resource)
|
594
|
+
end
|
591
595
|
end
|
592
596
|
|
593
597
|
# Deletes every Resource for which block evaluates to true.
|
@@ -1103,36 +1107,33 @@ module DataMapper
|
|
1103
1107
|
#
|
1104
1108
|
# @api private
|
1105
1109
|
def default_attributes
|
1106
|
-
@default_attributes
|
1107
|
-
begin
|
1108
|
-
unless query.conditions.kind_of?(Query::Conditions::AndOperation)
|
1109
|
-
return
|
1110
|
-
end
|
1110
|
+
return @default_attributes if @default_attributes
|
1111
1111
|
|
1112
|
-
|
1112
|
+
default_attributes = {}
|
1113
1113
|
|
1114
|
-
|
1115
|
-
relationships = self.relationships.values
|
1116
|
-
properties = model.properties(repository_name)
|
1117
|
-
key = model.key(repository_name)
|
1114
|
+
conditions = query.conditions
|
1118
1115
|
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1116
|
+
if conditions.kind_of?(Query::Conditions::AndOperation)
|
1117
|
+
repository_name = repository.name
|
1118
|
+
relationships = self.relationships.values
|
1119
|
+
properties = model.properties(repository_name)
|
1120
|
+
key = model.key(repository_name)
|
1124
1121
|
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1122
|
+
# if all the key properties are included in the conditions,
|
1123
|
+
# then do not allow them to be default attributes
|
1124
|
+
if query.condition_properties.to_set.superset?(key.to_set)
|
1125
|
+
properties -= key
|
1126
|
+
end
|
1130
1127
|
|
1128
|
+
conditions.each do |condition|
|
1129
|
+
if condition.kind_of?(Query::Conditions::EqualToComparison) &&
|
1130
|
+
(properties.include?(condition.subject) || (condition.relationship? && condition.subject.source_model == model))
|
1131
1131
|
default_attributes[condition.subject] = condition.value
|
1132
1132
|
end
|
1133
|
-
|
1134
|
-
default_attributes.freeze
|
1135
1133
|
end
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
@default_attributes = default_attributes.freeze
|
1136
1137
|
end
|
1137
1138
|
|
1138
1139
|
# Set the default attributes for a non-frozen resource
|
@@ -24,9 +24,8 @@ module DataMapper
|
|
24
24
|
model.instance_variable_set(:@paranoid_properties, @paranoid_properties.dup)
|
25
25
|
|
26
26
|
@properties.each do |repository_name, properties|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
27
|
+
model_properties = model.properties(repository_name)
|
28
|
+
properties.each { |property| model_properties[property.name] ||= property }
|
30
29
|
end
|
31
30
|
|
32
31
|
super
|
@@ -74,8 +73,10 @@ module DataMapper
|
|
74
73
|
context = options.fetch(:lazy, :default)
|
75
74
|
context = :default if context == true
|
76
75
|
|
77
|
-
|
78
|
-
|
76
|
+
properties = properties(repository_name)
|
77
|
+
|
78
|
+
Array(context).each do |context|
|
79
|
+
properties.lazy_context(context) << self
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
@@ -83,8 +84,7 @@ module DataMapper
|
|
83
84
|
# added after the child classes' properties have been copied from
|
84
85
|
# the parent
|
85
86
|
descendants.each do |descendant|
|
86
|
-
|
87
|
-
descendant.property(name, type, options)
|
87
|
+
descendant.properties(repository_name)[name] ||= property
|
88
88
|
end
|
89
89
|
|
90
90
|
create_reader_for(property)
|
@@ -156,7 +156,7 @@ module DataMapper
|
|
156
156
|
|
157
157
|
descendants.each do |model|
|
158
158
|
model.properties(repository_name).each do |property|
|
159
|
-
properties
|
159
|
+
properties[property.name] ||= property
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
@@ -27,15 +27,11 @@ module DataMapper
|
|
27
27
|
#
|
28
28
|
# @api private
|
29
29
|
def inherited(model)
|
30
|
-
|
31
|
-
model.instance_variable_set(:@relationships, duped_relationships = {})
|
30
|
+
model.instance_variable_set(:@relationships, {})
|
32
31
|
|
33
32
|
@relationships.each do |repository_name, relationships|
|
34
|
-
|
35
|
-
|
36
|
-
relationships.each do |name, relationship|
|
37
|
-
dup[name] = relationship.inherited_by(model)
|
38
|
-
end
|
33
|
+
model_relationships = model.relationships(repository_name)
|
34
|
+
relationships.each { |name, relationship| model_relationships[name] ||= relationship }
|
39
35
|
end
|
40
36
|
|
41
37
|
super
|
@@ -120,9 +116,11 @@ module DataMapper
|
|
120
116
|
|
121
117
|
model ||= options.delete(:model)
|
122
118
|
|
119
|
+
repository_name = repository.name
|
120
|
+
|
123
121
|
# TODO: change to :target_respository_name and :source_repository_name
|
124
122
|
options[:child_repository_name] = options.delete(:repository)
|
125
|
-
options[:parent_repository_name] =
|
123
|
+
options[:parent_repository_name] = repository_name
|
126
124
|
|
127
125
|
klass = if options[:max] > 1
|
128
126
|
options.key?(:through) ? Associations::ManyToMany::Relationship : Associations::OneToMany::Relationship
|
@@ -130,10 +128,10 @@ module DataMapper
|
|
130
128
|
Associations::OneToOne::Relationship
|
131
129
|
end
|
132
130
|
|
133
|
-
relationship = relationships(
|
131
|
+
relationship = relationships(repository_name)[name] = klass.new(name, model, self, options)
|
134
132
|
|
135
133
|
descendants.each do |descendant|
|
136
|
-
descendant.relationships(
|
134
|
+
descendant.relationships(repository_name)[name] ||= relationship
|
137
135
|
end
|
138
136
|
|
139
137
|
relationship
|
@@ -186,10 +184,10 @@ module DataMapper
|
|
186
184
|
options[:child_repository_name] = repository_name
|
187
185
|
options[:parent_repository_name] = options.delete(:repository)
|
188
186
|
|
189
|
-
relationship = relationships(
|
187
|
+
relationship = relationships(repository_name)[name] = Associations::ManyToOne::Relationship.new(name, self, model, options)
|
190
188
|
|
191
189
|
descendants.each do |descendant|
|
192
|
-
descendant.relationships(
|
190
|
+
descendant.relationships(repository_name)[name] ||= relationship
|
193
191
|
end
|
194
192
|
|
195
193
|
relationship
|
data/lib/dm-core/property.rb
CHANGED
@@ -293,10 +293,13 @@ module DataMapper
|
|
293
293
|
class Property
|
294
294
|
include Extlib::Assertions
|
295
295
|
extend Deprecate
|
296
|
+
extend Equalizer
|
296
297
|
|
297
298
|
deprecate :unique, :unique?
|
298
299
|
deprecate :size, :length
|
299
300
|
|
301
|
+
equalize :model, :name
|
302
|
+
|
300
303
|
# NOTE: PLEASE update OPTIONS in DataMapper::Type when updating
|
301
304
|
# them here
|
302
305
|
OPTIONS = [
|
@@ -363,56 +366,6 @@ module DataMapper
|
|
363
366
|
@unique
|
364
367
|
end
|
365
368
|
|
366
|
-
# Compares another Property for equivalency
|
367
|
-
#
|
368
|
-
# TODO: needs example
|
369
|
-
#
|
370
|
-
# @param [Property] other
|
371
|
-
# the other Property to compare with
|
372
|
-
#
|
373
|
-
# @return [Boolean]
|
374
|
-
# true if they are equivalent, false if not
|
375
|
-
#
|
376
|
-
# @api semipublic
|
377
|
-
def ==(other)
|
378
|
-
if equal?(other)
|
379
|
-
return true
|
380
|
-
end
|
381
|
-
|
382
|
-
unless other.respond_to?(:model)
|
383
|
-
return false
|
384
|
-
end
|
385
|
-
|
386
|
-
unless other.respond_to?(:name)
|
387
|
-
return false
|
388
|
-
end
|
389
|
-
|
390
|
-
cmp?(other, :==)
|
391
|
-
end
|
392
|
-
|
393
|
-
# Compares another Property for equality
|
394
|
-
#
|
395
|
-
# TODO: needs example
|
396
|
-
#
|
397
|
-
# @param [Property] other
|
398
|
-
# the other Property to compare with
|
399
|
-
#
|
400
|
-
# @return [Boolean]
|
401
|
-
# true if they are equal, false if not
|
402
|
-
#
|
403
|
-
# @api semipublic
|
404
|
-
def eql?(other)
|
405
|
-
if equal?(other)
|
406
|
-
return true
|
407
|
-
end
|
408
|
-
|
409
|
-
unless instance_of?(other.class)
|
410
|
-
return false
|
411
|
-
end
|
412
|
-
|
413
|
-
cmp?(other, :eql?)
|
414
|
-
end
|
415
|
-
|
416
369
|
# Returns the hash of the property name
|
417
370
|
#
|
418
371
|
# This is necessary to allow comparisons between different properties
|
@@ -640,11 +593,19 @@ module DataMapper
|
|
640
593
|
#
|
641
594
|
# @api private
|
642
595
|
def lazy_load(resource)
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
596
|
+
resource.send(:lazy_load, lazy_load_properties)
|
597
|
+
end
|
598
|
+
|
599
|
+
# TODO: document
|
600
|
+
# @api private
|
601
|
+
def lazy_load_properties
|
602
|
+
@lazy_load_properties ||= properties.in_context(lazy? ? [ self ] : properties.defaults)
|
603
|
+
end
|
604
|
+
|
605
|
+
# TODO: document
|
606
|
+
# @api private
|
607
|
+
def properties
|
608
|
+
@properties ||= model.properties(repository_name)
|
648
609
|
end
|
649
610
|
|
650
611
|
# typecasts values into a primitive (Ruby class that backs DataMapper
|
@@ -673,7 +634,7 @@ module DataMapper
|
|
673
634
|
# @return [rue, String, Float, Integer, BigDecimal, DateTime, Date, Time, Class]
|
674
635
|
# The typecasted +value+
|
675
636
|
#
|
676
|
-
# @api
|
637
|
+
# @api semipublic
|
677
638
|
def typecast(value)
|
678
639
|
return type.typecast(value, self) if type.respond_to?(:typecast)
|
679
640
|
return value if primitive?(value) || value.nil?
|
@@ -903,19 +864,16 @@ module DataMapper
|
|
903
864
|
raise ArgumentError, "options[#{key.inspect}] must not be nil"
|
904
865
|
end
|
905
866
|
|
906
|
-
when :serial, :key, :nullable, :
|
867
|
+
when :serial, :key, :nullable, :auto_validation
|
907
868
|
unless value == true || value == false
|
908
869
|
raise ArgumentError, "options[#{key.inspect}] must be either true or false"
|
909
870
|
end
|
910
871
|
|
911
|
-
when :lazy
|
912
|
-
unless value == true || value == false || value.kind_of?(Symbol) || (value.kind_of?(Array) && value.all? { |val| val.kind_of?(Symbol) })
|
872
|
+
when :index, :unique_index, :unique, :lazy
|
873
|
+
unless value == true || value == false || value.kind_of?(Symbol) || (value.kind_of?(Array) && value.any? && value.all? { |val| val.kind_of?(Symbol) })
|
913
874
|
raise ArgumentError, "options[#{key.inspect}] must be either true, false, a Symbol or an Array of Symbols"
|
914
875
|
end
|
915
876
|
|
916
|
-
when :index, :unique_index
|
917
|
-
assert_kind_of "options[#{key.inspect}]", value, Symbol, Array, TrueClass
|
918
|
-
|
919
877
|
when :length
|
920
878
|
assert_kind_of "options[#{key.inspect}]", value, Range, Integer
|
921
879
|
|
@@ -1184,28 +1142,5 @@ module DataMapper
|
|
1184
1142
|
rescue NameError
|
1185
1143
|
value
|
1186
1144
|
end
|
1187
|
-
|
1188
|
-
# Return true if +other+'s is equivalent or equal to +self+'s
|
1189
|
-
#
|
1190
|
-
# @param [Property] other
|
1191
|
-
# The Property whose attributes are to be compared with +self+'s
|
1192
|
-
# @param [Symbol] operator
|
1193
|
-
# The comparison operator to use to compare the attributes
|
1194
|
-
#
|
1195
|
-
# @return [Boolean]
|
1196
|
-
# The result of the comparison of +other+'s attributes with +self+'s
|
1197
|
-
#
|
1198
|
-
# @api private
|
1199
|
-
def cmp?(other, operator)
|
1200
|
-
unless model.base_model.send(operator, other.model.base_model)
|
1201
|
-
return false
|
1202
|
-
end
|
1203
|
-
|
1204
|
-
unless name.send(operator, other.name)
|
1205
|
-
return false
|
1206
|
-
end
|
1207
|
-
|
1208
|
-
true
|
1209
|
-
end
|
1210
1145
|
end # class Property
|
1211
1146
|
end # module DataMapper
|
data/lib/dm-core/property_set.rb
CHANGED
@@ -132,10 +132,10 @@ module DataMapper
|
|
132
132
|
|
133
133
|
# TODO: document
|
134
134
|
# @api private
|
135
|
-
def property_contexts(
|
135
|
+
def property_contexts(property)
|
136
136
|
contexts = []
|
137
|
-
lazy_contexts.each do |context,
|
138
|
-
contexts << context if
|
137
|
+
lazy_contexts.each do |context, properties|
|
138
|
+
contexts << context if properties.include?(property)
|
139
139
|
end
|
140
140
|
contexts
|
141
141
|
end
|
@@ -148,16 +148,16 @@ module DataMapper
|
|
148
148
|
|
149
149
|
# TODO: document
|
150
150
|
# @api private
|
151
|
-
def in_context(
|
152
|
-
|
153
|
-
if (contexts = property_contexts(
|
151
|
+
def in_context(properties)
|
152
|
+
properties_in_context = properties.map do |property|
|
153
|
+
if (contexts = property_contexts(property)).any?
|
154
154
|
lazy_contexts.values_at(*contexts)
|
155
155
|
else
|
156
|
-
|
156
|
+
property
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
160
|
-
|
160
|
+
properties_in_context.flatten.uniq
|
161
161
|
end
|
162
162
|
|
163
163
|
private
|
@@ -108,9 +108,12 @@ module DataMapper
|
|
108
108
|
# A base class for the various comparison classes.
|
109
109
|
class AbstractComparison
|
110
110
|
extend Deprecate
|
111
|
+
extend Equalizer
|
111
112
|
|
112
113
|
deprecate :property, :subject
|
113
114
|
|
115
|
+
equalize :slug, :subject, :value
|
116
|
+
|
114
117
|
# The property or relationship which is being matched against
|
115
118
|
#
|
116
119
|
# @return [Property, Associations::Relationship]
|
@@ -188,6 +191,16 @@ module DataMapper
|
|
188
191
|
slug ? @slug = slug : @slug
|
189
192
|
end
|
190
193
|
|
194
|
+
# Return the comparison class slug
|
195
|
+
#
|
196
|
+
# @return [Symbol]
|
197
|
+
# the comparison class slug
|
198
|
+
#
|
199
|
+
# @api private
|
200
|
+
def slug
|
201
|
+
self.class.slug
|
202
|
+
end
|
203
|
+
|
191
204
|
# Tests that the Comparison is valid
|
192
205
|
#
|
193
206
|
# Subclasses can overload this to customise the means by which they
|
@@ -227,57 +240,6 @@ module DataMapper
|
|
227
240
|
subject.kind_of?(Property)
|
228
241
|
end
|
229
242
|
|
230
|
-
# Computes a hash-code for this Comparison
|
231
|
-
#
|
232
|
-
# Two Comparisons of the same class, and with the same subject and
|
233
|
-
# value will have the same hash-code.
|
234
|
-
#
|
235
|
-
# @return [Fixnum] The computed hash-code.
|
236
|
-
#
|
237
|
-
# @api semipublic
|
238
|
-
def hash
|
239
|
-
[ self.class, @subject, @value ].hash
|
240
|
-
end
|
241
|
-
|
242
|
-
# Returns true if this object equals +other+
|
243
|
-
#
|
244
|
-
# The objects are considered equal if they are the same object, or
|
245
|
-
# have the same slug, subject and value.
|
246
|
-
#
|
247
|
-
# @param [Object] other
|
248
|
-
# Another object to be compared against this one.
|
249
|
-
#
|
250
|
-
# @return [Boolean]
|
251
|
-
#
|
252
|
-
# @api semipublic
|
253
|
-
def ==(other)
|
254
|
-
return true if equal?(other)
|
255
|
-
|
256
|
-
return false unless other.class.respond_to?(:slug)
|
257
|
-
return false unless other.respond_to?(:subject)
|
258
|
-
return false unless other.respond_to?(:value)
|
259
|
-
|
260
|
-
cmp?(other, :==)
|
261
|
-
end
|
262
|
-
|
263
|
-
# Returns true if this object equals +other+
|
264
|
-
#
|
265
|
-
# The objects are considered equal if they are the same object, or are
|
266
|
-
# the same class, and have the same slug, subject and value.
|
267
|
-
#
|
268
|
-
# @param [Object] other
|
269
|
-
# Another object to be compared against this one.
|
270
|
-
#
|
271
|
-
# @return [Boolean]
|
272
|
-
#
|
273
|
-
# @api semipublic
|
274
|
-
def eql?(other)
|
275
|
-
return true if equal?(other)
|
276
|
-
return false unless instance_of?(other.class)
|
277
|
-
|
278
|
-
cmp?(other, :eql?)
|
279
|
-
end
|
280
|
-
|
281
243
|
# Returns a human-readable representation of this object
|
282
244
|
#
|
283
245
|
# @return [String]
|
@@ -334,26 +296,6 @@ module DataMapper
|
|
334
296
|
@loaded_value = @loaded_value.dup
|
335
297
|
end
|
336
298
|
|
337
|
-
# Compares this comparison with +other+ using the given +operator+
|
338
|
-
#
|
339
|
-
# Checks that the slug, subject and value all return true when
|
340
|
-
# compared with their counterparts in +other+ with +operator+.
|
341
|
-
#
|
342
|
-
# @param [AbstractComparison] other
|
343
|
-
# Another object to be compared against this one.
|
344
|
-
#
|
345
|
-
# @see AbstractComparison#==
|
346
|
-
# @see AbstractComparison#eql?
|
347
|
-
#
|
348
|
-
# @return [Boolean]
|
349
|
-
#
|
350
|
-
# @api private
|
351
|
-
def cmp?(other, operator)
|
352
|
-
self.class.slug.send(operator, other.class.slug) &&
|
353
|
-
subject.send(operator, other.subject) &&
|
354
|
-
value.send(operator, other.value)
|
355
|
-
end
|
356
|
-
|
357
299
|
# Typecasts the given +val+ using subject#typecast
|
358
300
|
#
|
359
301
|
# If the subject has no typecast method the value is returned without
|