dm-core 1.0.2 → 1.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +28 -94
- data/LICENSE +1 -1
- data/README.rdoc +44 -11
- data/Rakefile +1 -7
- data/VERSION +1 -1
- data/dm-core.gemspec +398 -299
- data/lib/dm-core.rb +23 -13
- data/lib/dm-core/adapters/abstract_adapter.rb +1 -1
- data/lib/dm-core/associations/many_to_many.rb +1 -3
- data/lib/dm-core/associations/many_to_one.rb +54 -36
- data/lib/dm-core/associations/one_to_many.rb +1 -2
- data/lib/dm-core/associations/relationship.rb +11 -2
- data/lib/dm-core/collection.rb +3 -7
- data/lib/dm-core/core_ext/symbol.rb +1 -1
- data/lib/dm-core/identity_map.rb +0 -5
- data/lib/dm-core/model.rb +11 -21
- data/lib/dm-core/model/property.rb +43 -58
- data/lib/dm-core/model/relationship.rb +49 -44
- data/lib/dm-core/property.rb +106 -130
- data/lib/dm-core/property/date_time.rb +1 -3
- data/lib/dm-core/property/decimal.rb +11 -7
- data/lib/dm-core/property/integer.rb +2 -2
- data/lib/dm-core/property/lookup.rb +3 -16
- data/lib/dm-core/property/numeric.rb +3 -3
- data/lib/dm-core/property/object.rb +2 -11
- data/lib/dm-core/property/string.rb +1 -1
- data/lib/dm-core/property_set.rb +34 -54
- data/lib/dm-core/query.rb +85 -56
- data/lib/dm-core/query/conditions/comparison.rb +3 -6
- data/lib/dm-core/query/direction.rb +0 -4
- data/lib/dm-core/query/path.rb +22 -6
- data/lib/dm-core/relationship_set.rb +74 -0
- data/lib/dm-core/resource.rb +21 -32
- data/lib/dm-core/resource/state.rb +3 -4
- data/lib/dm-core/spec/lib/spec_helper.rb +1 -4
- data/lib/dm-core/spec/setup.rb +12 -5
- data/lib/dm-core/spec/shared/public/property_spec.rb +35 -21
- data/lib/dm-core/spec/shared/resource_spec.rb +1 -1
- data/lib/dm-core/spec/shared/semipublic/property_spec.rb +9 -9
- data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
- data/lib/dm-core/support/deprecate.rb +1 -1
- data/lib/dm-core/support/descendant_set.rb +12 -5
- data/lib/dm-core/support/ordered_set.rb +382 -0
- data/lib/dm-core/support/subject_set.rb +252 -0
- data/lib/dm-core/version.rb +1 -1
- data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +1 -2
- data/spec/public/associations/many_to_many_spec.rb +11 -9
- data/spec/public/associations/many_to_one_spec.rb +1 -1
- data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +1 -1
- data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +2 -2
- data/spec/public/associations/one_to_many_spec.rb +6 -5
- data/spec/public/associations/one_to_one_spec.rb +1 -1
- data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +1 -1
- data/spec/public/collection_spec.rb +7 -6
- data/spec/public/finalize_spec.rb +1 -1
- data/spec/public/model/hook_spec.rb +4 -3
- data/spec/public/model/property_spec.rb +9 -3
- data/spec/public/model/relationship_spec.rb +2 -4
- data/spec/public/model_spec.rb +1 -1
- data/spec/public/property/binary_spec.rb +1 -1
- data/spec/public/property/boolean_spec.rb +1 -1
- data/spec/public/property/class_spec.rb +1 -1
- data/spec/public/property/date_spec.rb +1 -1
- data/spec/public/property/date_time_spec.rb +1 -1
- data/spec/public/property/decimal_spec.rb +7 -6
- data/spec/public/property/discriminator_spec.rb +1 -1
- data/spec/public/property/float_spec.rb +1 -1
- data/spec/public/property/integer_spec.rb +1 -1
- data/spec/public/property/object_spec.rb +2 -2
- data/spec/public/property/serial_spec.rb +1 -1
- data/spec/public/property/string_spec.rb +1 -1
- data/spec/public/property/text_spec.rb +6 -3
- data/spec/public/property/time_spec.rb +1 -1
- data/spec/public/property_spec.rb +13 -11
- data/spec/public/resource_spec.rb +43 -1
- data/spec/public/sel_spec.rb +1 -1
- data/spec/public/setup_spec.rb +1 -1
- data/spec/public/shared/collection_shared_spec.rb +6 -1
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +1 -1
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +1 -1
- data/spec/semipublic/associations/many_to_many_spec.rb +1 -1
- data/spec/semipublic/associations/many_to_one_spec.rb +1 -1
- data/spec/semipublic/associations/one_to_many_spec.rb +1 -1
- data/spec/semipublic/associations/one_to_one_spec.rb +1 -1
- data/spec/semipublic/associations/relationship_spec.rb +1 -1
- data/spec/semipublic/associations_spec.rb +1 -1
- data/spec/semipublic/collection_spec.rb +1 -1
- data/spec/semipublic/model_spec.rb +1 -1
- data/spec/semipublic/property/binary_spec.rb +1 -1
- data/spec/semipublic/property/boolean_spec.rb +1 -1
- data/spec/semipublic/property/class_spec.rb +1 -1
- data/spec/semipublic/property/date_spec.rb +1 -1
- data/spec/semipublic/property/date_time_spec.rb +1 -1
- data/spec/semipublic/property/decimal_spec.rb +6 -5
- data/spec/semipublic/property/discriminator_spec.rb +1 -1
- data/spec/semipublic/property/float_spec.rb +1 -1
- data/spec/semipublic/property/integer_spec.rb +1 -1
- data/spec/semipublic/property/lookup_spec.rb +8 -5
- data/spec/semipublic/property/serial_spec.rb +1 -1
- data/spec/semipublic/property/string_spec.rb +1 -1
- data/spec/semipublic/property/text_spec.rb +1 -1
- data/spec/semipublic/property/time_spec.rb +1 -1
- data/spec/semipublic/property_spec.rb +32 -7
- data/spec/semipublic/query/conditions/comparison_spec.rb +1 -264
- data/spec/semipublic/query/conditions/operation_spec.rb +1 -2
- data/spec/semipublic/query/path_spec.rb +27 -1
- data/spec/semipublic/query_spec.rb +87 -36
- data/spec/semipublic/resource/state/clean_spec.rb +1 -2
- data/spec/semipublic/resource/state/deleted_spec.rb +1 -2
- data/spec/semipublic/resource/state/dirty_spec.rb +1 -2
- data/spec/semipublic/resource/state/immutable_spec.rb +1 -2
- data/spec/semipublic/resource/state/transient_spec.rb +7 -2
- data/spec/semipublic/resource/state_spec.rb +1 -1
- data/spec/semipublic/resource_spec.rb +1 -1
- data/spec/unit/array_spec.rb +1 -0
- data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
- data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
- data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
- data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
- data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
- data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
- data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
- data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
- data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
- data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
- data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
- data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
- data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
- data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
- data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
- data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
- data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
- data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
- data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
- data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
- data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
- data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
- data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
- data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
- data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
- data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
- data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
- data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
- data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
- data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
- data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
- data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
- data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
- data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
- data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
- data/spec/unit/hash_spec.rb +2 -1
- data/spec/unit/hook_spec.rb +1 -0
- data/spec/unit/lazy_array_spec.rb +2 -1
- data/spec/unit/module_spec.rb +2 -1
- data/spec/unit/object_spec.rb +1 -0
- data/spec/unit/try_dup_spec.rb +1 -0
- data/tasks/spec.rake +0 -3
- metadata +149 -52
- data/.gitignore +0 -37
- data/lib/dm-core/type.rb +0 -216
- data/lib/dm-core/types/boolean.rb +0 -9
- data/lib/dm-core/types/decimal.rb +0 -9
- data/lib/dm-core/types/discriminator.rb +0 -50
- data/lib/dm-core/types/object.rb +0 -25
- data/lib/dm-core/types/serial.rb +0 -11
- data/lib/dm-core/types/text.rb +0 -11
- data/tasks/local_gemfile.rake +0 -16
- data/tasks/metrics.rake +0 -37
@@ -19,9 +19,7 @@ module DataMapper
|
|
19
19
|
#
|
20
20
|
# @api private
|
21
21
|
def typecast_to_primitive(value)
|
22
|
-
if value.respond_to?(:
|
23
|
-
value.to_datetime
|
24
|
-
elsif value.respond_to?(:to_mash)
|
22
|
+
if value.respond_to?(:to_mash)
|
25
23
|
typecast_hash_to_datetime(value)
|
26
24
|
else
|
27
25
|
::DateTime.parse(value.to_s)
|
@@ -7,17 +7,21 @@ module DataMapper
|
|
7
7
|
|
8
8
|
protected
|
9
9
|
|
10
|
-
def initialize(model, name, options = {}
|
10
|
+
def initialize(model, name, options = {})
|
11
11
|
super
|
12
12
|
|
13
|
-
|
14
|
-
unless
|
15
|
-
|
13
|
+
[ :scale, :precision ].each do |key|
|
14
|
+
unless options.key?(key)
|
15
|
+
warn "options[#{key.inspect}] should be set for #{self.class}, defaulting to #{send(key).inspect}"
|
16
16
|
end
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
unless @scale >= 0
|
20
|
+
raise ArgumentError, "scale must be equal to or greater than 0, but was #{@scale.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
unless @precision >= @scale
|
24
|
+
raise ArgumentError, "precision must be equal to or greater than scale, but was #{@precision.inspect} and scale was #{@scale.inspect}"
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
@@ -8,9 +8,9 @@ module DataMapper
|
|
8
8
|
protected
|
9
9
|
|
10
10
|
# @api semipublic
|
11
|
-
def initialize(model, name, options = {}
|
11
|
+
def initialize(model, name, options = {})
|
12
12
|
if options.key?(:serial) && !kind_of?(Serial)
|
13
|
-
|
13
|
+
raise "Integer #{name} with explicit :serial option is deprecated, use Serial instead (#{caller[2]})"
|
14
14
|
end
|
15
15
|
super
|
16
16
|
end
|
@@ -6,12 +6,12 @@ module DataMapper
|
|
6
6
|
|
7
7
|
#
|
8
8
|
# Provides transparent access to the Properties defined in
|
9
|
-
# {Property}.
|
9
|
+
# {Property}.
|
10
10
|
#
|
11
11
|
# @param [Symbol] name
|
12
12
|
# The name of the property to lookup.
|
13
13
|
#
|
14
|
-
# @return [Property
|
14
|
+
# @return [Property]
|
15
15
|
# The property with the given name.
|
16
16
|
#
|
17
17
|
# @raise [NameError]
|
@@ -22,20 +22,7 @@ module DataMapper
|
|
22
22
|
# @since 1.0.1
|
23
23
|
#
|
24
24
|
def const_missing(name)
|
25
|
-
|
26
|
-
return const
|
27
|
-
end
|
28
|
-
|
29
|
-
# only check within DataMapper::Types, if it was loaded.
|
30
|
-
if DataMapper.const_defined?(:Types)
|
31
|
-
if DataMapper::Types.const_defined?(name)
|
32
|
-
type = DataMapper::Types.const_get(name)
|
33
|
-
|
34
|
-
return type if type < DataMapper::Type
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
super
|
25
|
+
Property.find_class(name.to_s) || super
|
39
26
|
end
|
40
27
|
end
|
41
28
|
end
|
@@ -15,10 +15,10 @@ module DataMapper
|
|
15
15
|
|
16
16
|
protected
|
17
17
|
|
18
|
-
def initialize(model, name, options = {}
|
18
|
+
def initialize(model, name, options = {})
|
19
19
|
super
|
20
20
|
|
21
|
-
if
|
21
|
+
if @primitive == BigDecimal || @primitive == ::Float
|
22
22
|
@precision = @options.fetch(:precision, DEFAULT_PRECISION)
|
23
23
|
@scale = @options.fetch(:scale, self.class::DEFAULT_SCALE)
|
24
24
|
|
@@ -27,7 +27,7 @@ module DataMapper
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
if
|
30
|
+
if @options.key?(:min) || @options.key?(:max)
|
31
31
|
@min = @options.fetch(:min, DEFAULT_NUMERIC_MIN)
|
32
32
|
@max = @options.fetch(:max, DEFAULT_NUMERIC_MAX)
|
33
33
|
|
@@ -5,21 +5,12 @@ module DataMapper
|
|
5
5
|
|
6
6
|
# @api semipublic
|
7
7
|
def dump(value)
|
8
|
-
return
|
9
|
-
|
10
|
-
if @type
|
11
|
-
@type.dump(value, self)
|
12
|
-
else
|
13
|
-
[ Marshal.dump(value) ].pack('m')
|
14
|
-
end
|
8
|
+
return if value.nil?
|
9
|
+
[ Marshal.dump(value) ].pack('m')
|
15
10
|
end
|
16
11
|
|
17
12
|
# @api semipublic
|
18
13
|
def load(value)
|
19
|
-
if @type
|
20
|
-
return @type.load(value, self)
|
21
|
-
end
|
22
|
-
|
23
14
|
case value
|
24
15
|
when ::String
|
25
16
|
Marshal.load(value.unpack('m').first)
|
data/lib/dm-core/property_set.rb
CHANGED
@@ -1,58 +1,52 @@
|
|
1
|
+
require 'dm-core/support/subject_set'
|
2
|
+
|
1
3
|
module DataMapper
|
2
4
|
# Set of Property objects, used to associate
|
3
5
|
# queries with set of fields it performed over,
|
4
6
|
# to represent composite keys (esp. for associations)
|
5
7
|
# and so on.
|
6
|
-
class PropertySet <
|
7
|
-
|
8
|
-
|
9
|
-
deprecate :has_property?, :named?
|
10
|
-
deprecate :slice, :values_at
|
11
|
-
deprecate :add, :<<
|
8
|
+
class PropertySet < SubjectSet
|
9
|
+
include Enumerable
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
def <<(property)
|
12
|
+
clear_cache
|
13
|
+
super
|
16
14
|
end
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
# Make sure that entry is part of this PropertySet
|
17
|
+
#
|
18
|
+
# @param [#to_s] name
|
19
|
+
# @param [#name] entry
|
20
|
+
#
|
21
|
+
# @return [#name]
|
22
|
+
# the entry that is now part of this PropertySet
|
23
|
+
#
|
21
24
|
# @api semipublic
|
22
|
-
def []=(name,
|
23
|
-
self
|
25
|
+
def []=(name, entry)
|
26
|
+
warn "#{self.class}#[]= is deprecated. Use #{self.class}#<< instead: #{caller.first}"
|
27
|
+
raise "#{entry.class} is not added with the correct name" unless name && name.to_s == entry.name.to_s
|
28
|
+
self << entry
|
29
|
+
entry
|
24
30
|
end
|
25
31
|
|
26
|
-
|
27
|
-
|
28
|
-
@properties.key?(name.to_sym)
|
32
|
+
def |(other)
|
33
|
+
self.class.new(to_a | other.to_a)
|
29
34
|
end
|
30
35
|
|
31
|
-
|
32
|
-
|
33
|
-
@properties.values_at(*names)
|
36
|
+
def &(other)
|
37
|
+
self.class.new(to_a & other.to_a)
|
34
38
|
end
|
35
39
|
|
36
|
-
|
37
|
-
|
38
|
-
found = named?(property.name)
|
39
|
-
add_property(property)
|
40
|
-
|
41
|
-
if found
|
42
|
-
superclass_slice(index(property), property)
|
43
|
-
else
|
44
|
-
super
|
45
|
-
end
|
40
|
+
def -(other)
|
41
|
+
self.class.new(to_a - other.to_a)
|
46
42
|
end
|
47
43
|
|
48
|
-
|
49
|
-
|
50
|
-
named?(property.name)
|
44
|
+
def +(other)
|
45
|
+
self.class.new(to_a + other.to_a)
|
51
46
|
end
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
each_index { |index| break index if at(index).name == property.name }
|
48
|
+
def ==(other)
|
49
|
+
to_a == other.to_a
|
56
50
|
end
|
57
51
|
|
58
52
|
# TODO: make PropertySet#reject return a PropertySet instance
|
@@ -68,7 +62,7 @@ module DataMapper
|
|
68
62
|
|
69
63
|
# @api semipublic
|
70
64
|
def discriminator
|
71
|
-
@discriminator ||= detect { |property| property.kind_of?(Property::Discriminator)
|
65
|
+
@discriminator ||= detect { |property| property.kind_of?(Property::Discriminator) }
|
72
66
|
end
|
73
67
|
|
74
68
|
# @api semipublic
|
@@ -153,25 +147,11 @@ module DataMapper
|
|
153
147
|
map { |property| [ property.field, property ] }.to_hash
|
154
148
|
end
|
155
149
|
|
156
|
-
|
157
|
-
|
158
|
-
# @api semipublic
|
159
|
-
def initialize(*)
|
160
|
-
super
|
161
|
-
@properties = map { |property| [ property.name, property ] }.to_mash
|
150
|
+
def inspect
|
151
|
+
to_a.inspect
|
162
152
|
end
|
163
153
|
|
164
|
-
|
165
|
-
def initialize_copy(*)
|
166
|
-
super
|
167
|
-
@properties = @properties.dup
|
168
|
-
end
|
169
|
-
|
170
|
-
# @api private
|
171
|
-
def add_property(property)
|
172
|
-
clear_cache
|
173
|
-
@properties[property.name] = property
|
174
|
-
end
|
154
|
+
private
|
175
155
|
|
176
156
|
# @api private
|
177
157
|
def clear_cache
|
data/lib/dm-core/query.rb
CHANGED
@@ -486,10 +486,10 @@ module DataMapper
|
|
486
486
|
#
|
487
487
|
# @api semipublic
|
488
488
|
def filter_records(records)
|
489
|
-
records = records.uniq
|
490
|
-
records = match_records(records)
|
491
|
-
records = sort_records(records)
|
492
|
-
records = limit_records(records)
|
489
|
+
records = records.uniq if unique?
|
490
|
+
records = match_records(records) if conditions
|
491
|
+
records = sort_records(records) if order
|
492
|
+
records = limit_records(records) if limit || offset > 0
|
493
493
|
records
|
494
494
|
end
|
495
495
|
|
@@ -504,7 +504,6 @@ module DataMapper
|
|
504
504
|
# @api semipublic
|
505
505
|
def match_records(records)
|
506
506
|
conditions = self.conditions
|
507
|
-
return records if conditions.nil?
|
508
507
|
records.select { |record| conditions.matches?(record) }
|
509
508
|
end
|
510
509
|
|
@@ -530,7 +529,7 @@ module DataMapper
|
|
530
529
|
# Limits a set of records by the offset and/or limit
|
531
530
|
#
|
532
531
|
# @param [Enumerable] records
|
533
|
-
# A list of
|
532
|
+
# A list of records to sort
|
534
533
|
#
|
535
534
|
# @return [Enumerable]
|
536
535
|
# The offset & limited records
|
@@ -788,22 +787,26 @@ module DataMapper
|
|
788
787
|
|
789
788
|
model = self.model
|
790
789
|
|
791
|
-
|
792
|
-
|
790
|
+
valid_properties = model.properties
|
791
|
+
|
792
|
+
model.descendants.each do |descendant|
|
793
|
+
valid_properties += descendant.properties
|
794
|
+
end
|
793
795
|
|
796
|
+
fields.each do |field|
|
794
797
|
case field
|
795
798
|
when Symbol, String
|
796
|
-
unless
|
797
|
-
raise ArgumentError, "+options[:fields]+ entry #{inspect} does not map to a property in #{model}"
|
799
|
+
unless valid_properties.named?(field)
|
800
|
+
raise ArgumentError, "+options[:fields]+ entry #{field.inspect} does not map to a property in #{model}"
|
798
801
|
end
|
799
802
|
|
800
803
|
when Property
|
801
|
-
unless
|
804
|
+
unless valid_properties.include?(field)
|
802
805
|
raise ArgumentError, "+options[:field]+ entry #{field.name.inspect} does not map to a property in #{model}"
|
803
806
|
end
|
804
807
|
|
805
808
|
else
|
806
|
-
raise ArgumentError, "+options[:fields]+ entry #{inspect} of an unsupported object #{field.class}"
|
809
|
+
raise ArgumentError, "+options[:fields]+ entry #{field.inspect} of an unsupported object #{field.class}"
|
807
810
|
end
|
808
811
|
end
|
809
812
|
end
|
@@ -820,12 +823,10 @@ module DataMapper
|
|
820
823
|
end
|
821
824
|
|
822
825
|
links.each do |link|
|
823
|
-
inspect = link.inspect
|
824
|
-
|
825
826
|
case link
|
826
827
|
when Symbol, String
|
827
|
-
unless @relationships.
|
828
|
-
raise ArgumentError, "+options[:links]+ entry #{inspect} does not map to a relationship in #{model}"
|
828
|
+
unless @relationships.named?(link.to_sym)
|
829
|
+
raise ArgumentError, "+options[:links]+ entry #{link.inspect} does not map to a relationship in #{model}"
|
829
830
|
end
|
830
831
|
|
831
832
|
when Associations::Relationship
|
@@ -835,7 +836,7 @@ module DataMapper
|
|
835
836
|
#end
|
836
837
|
|
837
838
|
else
|
838
|
-
raise ArgumentError, "+options[:links]+ entry #{inspect} of an unsupported object #{link.class}"
|
839
|
+
raise ArgumentError, "+options[:links]+ entry #{link.inspect} of an unsupported object #{link.class}"
|
839
840
|
end
|
840
841
|
end
|
841
842
|
end
|
@@ -850,19 +851,29 @@ module DataMapper
|
|
850
851
|
case conditions
|
851
852
|
when Hash
|
852
853
|
conditions.each do |subject, bind_value|
|
853
|
-
inspect = subject.inspect
|
854
|
-
|
855
854
|
case subject
|
856
855
|
when Symbol, ::String
|
857
|
-
|
858
|
-
|
856
|
+
original = subject
|
857
|
+
subject = subject.to_s
|
858
|
+
|
859
|
+
if subject.include?('.')
|
860
|
+
unless @relationships.named?(subject[0, subject.index('.')])
|
861
|
+
raise ArgumentError, "condition #{original.inspect} does not map to a relationship in #{model}"
|
862
|
+
end
|
863
|
+
elsif !@properties.named?(subject) && !@relationships.named?(subject)
|
864
|
+
raise ArgumentError, "condition #{original.inspect} does not map to a property or relationship in #{model}"
|
865
|
+
end
|
866
|
+
|
867
|
+
when Property
|
868
|
+
unless @properties.include?(subject)
|
869
|
+
raise ArgumentError, "condition #{subject.name.inspect} does not map to a property in #{model}, but belongs to #{subject.model}"
|
859
870
|
end
|
860
871
|
|
861
872
|
when Operator
|
862
873
|
operator = subject.operator
|
863
874
|
|
864
|
-
unless
|
865
|
-
raise ArgumentError, "condition #{inspect} used an invalid operator #{operator}"
|
875
|
+
unless Conditions::Comparison.slugs.include?(operator) || operator == :not
|
876
|
+
raise ArgumentError, "condition #{subject.inspect} used an invalid operator #{operator}"
|
866
877
|
end
|
867
878
|
|
868
879
|
assert_valid_conditions(subject.target => bind_value)
|
@@ -870,15 +881,14 @@ module DataMapper
|
|
870
881
|
when Path
|
871
882
|
assert_valid_links(subject.relationships)
|
872
883
|
|
873
|
-
when Associations::Relationship
|
874
|
-
# TODO: validate that it belongs to the current model
|
875
|
-
# model
|
876
|
-
#
|
877
|
-
# raise ArgumentError, "condition #{subject.name.inspect} does not map to a property in #{model}"
|
884
|
+
when Associations::Relationship
|
885
|
+
# TODO: validate that it belongs to the current model
|
886
|
+
#unless subject.source_model.equal?(model)
|
887
|
+
# raise ArgumentError, "condition #{subject.name.inspect} is not a valid relationship for #{model}, it's source model was #{subject.source_model}"
|
878
888
|
#end
|
879
889
|
|
880
890
|
else
|
881
|
-
raise ArgumentError, "condition #{inspect} of an unsupported object #{subject.class}"
|
891
|
+
raise ArgumentError, "condition #{subject.inspect} of an unsupported object #{subject.class}"
|
882
892
|
end
|
883
893
|
end
|
884
894
|
|
@@ -938,30 +948,27 @@ module DataMapper
|
|
938
948
|
model = self.model
|
939
949
|
|
940
950
|
order.each do |order_entry|
|
941
|
-
inspect = order_entry.inspect
|
942
|
-
|
943
951
|
case order_entry
|
944
952
|
when Symbol, String
|
945
953
|
unless @properties.named?(order_entry)
|
946
|
-
raise ArgumentError, "+options[:order]+ entry #{inspect} does not map to a property in #{model}"
|
954
|
+
raise ArgumentError, "+options[:order]+ entry #{order_entry.inspect} does not map to a property in #{model}"
|
947
955
|
end
|
948
956
|
|
949
|
-
when Property
|
950
|
-
|
951
|
-
|
952
|
-
end
|
957
|
+
when Property, Path
|
958
|
+
# Allow any arbitrary property, since it may map to a model
|
959
|
+
# that has been included via the :links option
|
953
960
|
|
954
961
|
when Operator, Direction
|
955
962
|
operator = order_entry.operator
|
956
963
|
|
957
964
|
unless operator == :asc || operator == :desc
|
958
|
-
raise ArgumentError, "+options[:order]+ entry #{inspect} used an invalid operator #{operator}"
|
965
|
+
raise ArgumentError, "+options[:order]+ entry #{order_entry.inspect} used an invalid operator #{operator}"
|
959
966
|
end
|
960
967
|
|
961
968
|
assert_valid_order([ order_entry.target ], fields)
|
962
969
|
|
963
970
|
else
|
964
|
-
raise ArgumentError, "+options[:order]+ entry #{inspect} of an unsupported object #{order_entry.class}"
|
971
|
+
raise ArgumentError, "+options[:order]+ entry #{order_entry.inspect} of an unsupported object #{order_entry.class}"
|
965
972
|
end
|
966
973
|
end
|
967
974
|
end
|
@@ -1034,9 +1041,10 @@ module DataMapper
|
|
1034
1041
|
#
|
1035
1042
|
# @api private
|
1036
1043
|
def normalize_options(options = OPTIONS)
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1044
|
+
normalize_order if options.include? :order
|
1045
|
+
normalize_fields if options.include? :fields
|
1046
|
+
normalize_links if options.include? :links
|
1047
|
+
normalize_unique if options.include? :unique
|
1040
1048
|
end
|
1041
1049
|
|
1042
1050
|
# Normalize order elements to Query::Direction instances
|
@@ -1045,8 +1053,6 @@ module DataMapper
|
|
1045
1053
|
def normalize_order
|
1046
1054
|
return if @order.nil?
|
1047
1055
|
|
1048
|
-
# TODO: should Query::Path objects be permitted? If so, then it
|
1049
|
-
# should probably be normalized to a Direction object
|
1050
1056
|
@order = Array(@order)
|
1051
1057
|
@order = @order.map do |order|
|
1052
1058
|
case order
|
@@ -1064,6 +1070,10 @@ module DataMapper
|
|
1064
1070
|
|
1065
1071
|
when Direction
|
1066
1072
|
order.dup
|
1073
|
+
|
1074
|
+
when Path
|
1075
|
+
Direction.new(order.property)
|
1076
|
+
|
1067
1077
|
end
|
1068
1078
|
end
|
1069
1079
|
end
|
@@ -1113,12 +1123,19 @@ module DataMapper
|
|
1113
1123
|
|
1114
1124
|
# Normalize the unique attribute
|
1115
1125
|
#
|
1116
|
-
# If any links are present, and the unique attribute was not
|
1117
|
-
#
|
1126
|
+
# If any links are present, and the unique attribute was not explicitly
|
1127
|
+
# specified, then make sure the query is marked as unique. The exception
|
1128
|
+
# to this rule is links where there is known to be 0..1 records on the
|
1129
|
+
# the other side, such as belongs_to or a has 1. In this case, there
|
1130
|
+
# is no need to explicitly mark the query unique. This in turn allows
|
1131
|
+
# sane ordering on fields of the links, since no redundant GROUP BY
|
1132
|
+
# clause will be generated.
|
1118
1133
|
#
|
1119
1134
|
# @api private
|
1120
1135
|
def normalize_unique
|
1121
|
-
|
1136
|
+
unless @options.key?(:unique)
|
1137
|
+
@unique = @links.reject {|x| x.min.between?(0, 1) && x.max == 1 }.any?
|
1138
|
+
end
|
1122
1139
|
end
|
1123
1140
|
|
1124
1141
|
# Append conditions to this Query
|
@@ -1148,6 +1165,16 @@ module DataMapper
|
|
1148
1165
|
end
|
1149
1166
|
end
|
1150
1167
|
|
1168
|
+
# @api private
|
1169
|
+
def equality_operator_for_type(bind_value)
|
1170
|
+
case bind_value
|
1171
|
+
when Model, String then :eql
|
1172
|
+
when Enumerable then :in
|
1173
|
+
when Regexp then :regexp
|
1174
|
+
else :eql
|
1175
|
+
end
|
1176
|
+
end
|
1177
|
+
|
1151
1178
|
# @api private
|
1152
1179
|
def append_property_condition(subject, bind_value, operator)
|
1153
1180
|
negated = operator == :not
|
@@ -1171,15 +1198,6 @@ module DataMapper
|
|
1171
1198
|
add_condition(condition)
|
1172
1199
|
end
|
1173
1200
|
|
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
|
1180
|
-
end
|
1181
|
-
end
|
1182
|
-
|
1183
1201
|
# @api private
|
1184
1202
|
def append_symbol_condition(symbol, bind_value, model, operator)
|
1185
1203
|
append_condition(symbol.to_s, bind_value, model, operator)
|
@@ -1356,7 +1374,18 @@ module DataMapper
|
|
1356
1374
|
#
|
1357
1375
|
# @api private
|
1358
1376
|
def other_conditions(other, operation)
|
1359
|
-
query_conditions(self)
|
1377
|
+
self_conditions = query_conditions(self)
|
1378
|
+
|
1379
|
+
unless self_conditions.kind_of?(Conditions::Operation)
|
1380
|
+
operation_slug = case operation
|
1381
|
+
when :intersection, :difference then :and
|
1382
|
+
when :union then :or
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
self_conditions = Conditions::Operation.new(operation_slug, self_conditions)
|
1386
|
+
end
|
1387
|
+
|
1388
|
+
self_conditions.send(operation, query_conditions(other))
|
1360
1389
|
end
|
1361
1390
|
|
1362
1391
|
# Extract conditions from a Query
|