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.
Files changed (184) hide show
  1. data/Gemfile +28 -94
  2. data/LICENSE +1 -1
  3. data/README.rdoc +44 -11
  4. data/Rakefile +1 -7
  5. data/VERSION +1 -1
  6. data/dm-core.gemspec +398 -299
  7. data/lib/dm-core.rb +23 -13
  8. data/lib/dm-core/adapters/abstract_adapter.rb +1 -1
  9. data/lib/dm-core/associations/many_to_many.rb +1 -3
  10. data/lib/dm-core/associations/many_to_one.rb +54 -36
  11. data/lib/dm-core/associations/one_to_many.rb +1 -2
  12. data/lib/dm-core/associations/relationship.rb +11 -2
  13. data/lib/dm-core/collection.rb +3 -7
  14. data/lib/dm-core/core_ext/symbol.rb +1 -1
  15. data/lib/dm-core/identity_map.rb +0 -5
  16. data/lib/dm-core/model.rb +11 -21
  17. data/lib/dm-core/model/property.rb +43 -58
  18. data/lib/dm-core/model/relationship.rb +49 -44
  19. data/lib/dm-core/property.rb +106 -130
  20. data/lib/dm-core/property/date_time.rb +1 -3
  21. data/lib/dm-core/property/decimal.rb +11 -7
  22. data/lib/dm-core/property/integer.rb +2 -2
  23. data/lib/dm-core/property/lookup.rb +3 -16
  24. data/lib/dm-core/property/numeric.rb +3 -3
  25. data/lib/dm-core/property/object.rb +2 -11
  26. data/lib/dm-core/property/string.rb +1 -1
  27. data/lib/dm-core/property_set.rb +34 -54
  28. data/lib/dm-core/query.rb +85 -56
  29. data/lib/dm-core/query/conditions/comparison.rb +3 -6
  30. data/lib/dm-core/query/direction.rb +0 -4
  31. data/lib/dm-core/query/path.rb +22 -6
  32. data/lib/dm-core/relationship_set.rb +74 -0
  33. data/lib/dm-core/resource.rb +21 -32
  34. data/lib/dm-core/resource/state.rb +3 -4
  35. data/lib/dm-core/spec/lib/spec_helper.rb +1 -4
  36. data/lib/dm-core/spec/setup.rb +12 -5
  37. data/lib/dm-core/spec/shared/public/property_spec.rb +35 -21
  38. data/lib/dm-core/spec/shared/resource_spec.rb +1 -1
  39. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +9 -9
  40. data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
  41. data/lib/dm-core/support/deprecate.rb +1 -1
  42. data/lib/dm-core/support/descendant_set.rb +12 -5
  43. data/lib/dm-core/support/ordered_set.rb +382 -0
  44. data/lib/dm-core/support/subject_set.rb +252 -0
  45. data/lib/dm-core/version.rb +1 -1
  46. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +1 -2
  47. data/spec/public/associations/many_to_many_spec.rb +11 -9
  48. data/spec/public/associations/many_to_one_spec.rb +1 -1
  49. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +1 -1
  50. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +2 -2
  51. data/spec/public/associations/one_to_many_spec.rb +6 -5
  52. data/spec/public/associations/one_to_one_spec.rb +1 -1
  53. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +1 -1
  54. data/spec/public/collection_spec.rb +7 -6
  55. data/spec/public/finalize_spec.rb +1 -1
  56. data/spec/public/model/hook_spec.rb +4 -3
  57. data/spec/public/model/property_spec.rb +9 -3
  58. data/spec/public/model/relationship_spec.rb +2 -4
  59. data/spec/public/model_spec.rb +1 -1
  60. data/spec/public/property/binary_spec.rb +1 -1
  61. data/spec/public/property/boolean_spec.rb +1 -1
  62. data/spec/public/property/class_spec.rb +1 -1
  63. data/spec/public/property/date_spec.rb +1 -1
  64. data/spec/public/property/date_time_spec.rb +1 -1
  65. data/spec/public/property/decimal_spec.rb +7 -6
  66. data/spec/public/property/discriminator_spec.rb +1 -1
  67. data/spec/public/property/float_spec.rb +1 -1
  68. data/spec/public/property/integer_spec.rb +1 -1
  69. data/spec/public/property/object_spec.rb +2 -2
  70. data/spec/public/property/serial_spec.rb +1 -1
  71. data/spec/public/property/string_spec.rb +1 -1
  72. data/spec/public/property/text_spec.rb +6 -3
  73. data/spec/public/property/time_spec.rb +1 -1
  74. data/spec/public/property_spec.rb +13 -11
  75. data/spec/public/resource_spec.rb +43 -1
  76. data/spec/public/sel_spec.rb +1 -1
  77. data/spec/public/setup_spec.rb +1 -1
  78. data/spec/public/shared/collection_shared_spec.rb +6 -1
  79. data/spec/semipublic/adapters/abstract_adapter_spec.rb +1 -1
  80. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +1 -1
  81. data/spec/semipublic/associations/many_to_many_spec.rb +1 -1
  82. data/spec/semipublic/associations/many_to_one_spec.rb +1 -1
  83. data/spec/semipublic/associations/one_to_many_spec.rb +1 -1
  84. data/spec/semipublic/associations/one_to_one_spec.rb +1 -1
  85. data/spec/semipublic/associations/relationship_spec.rb +1 -1
  86. data/spec/semipublic/associations_spec.rb +1 -1
  87. data/spec/semipublic/collection_spec.rb +1 -1
  88. data/spec/semipublic/model_spec.rb +1 -1
  89. data/spec/semipublic/property/binary_spec.rb +1 -1
  90. data/spec/semipublic/property/boolean_spec.rb +1 -1
  91. data/spec/semipublic/property/class_spec.rb +1 -1
  92. data/spec/semipublic/property/date_spec.rb +1 -1
  93. data/spec/semipublic/property/date_time_spec.rb +1 -1
  94. data/spec/semipublic/property/decimal_spec.rb +6 -5
  95. data/spec/semipublic/property/discriminator_spec.rb +1 -1
  96. data/spec/semipublic/property/float_spec.rb +1 -1
  97. data/spec/semipublic/property/integer_spec.rb +1 -1
  98. data/spec/semipublic/property/lookup_spec.rb +8 -5
  99. data/spec/semipublic/property/serial_spec.rb +1 -1
  100. data/spec/semipublic/property/string_spec.rb +1 -1
  101. data/spec/semipublic/property/text_spec.rb +1 -1
  102. data/spec/semipublic/property/time_spec.rb +1 -1
  103. data/spec/semipublic/property_spec.rb +32 -7
  104. data/spec/semipublic/query/conditions/comparison_spec.rb +1 -264
  105. data/spec/semipublic/query/conditions/operation_spec.rb +1 -2
  106. data/spec/semipublic/query/path_spec.rb +27 -1
  107. data/spec/semipublic/query_spec.rb +87 -36
  108. data/spec/semipublic/resource/state/clean_spec.rb +1 -2
  109. data/spec/semipublic/resource/state/deleted_spec.rb +1 -2
  110. data/spec/semipublic/resource/state/dirty_spec.rb +1 -2
  111. data/spec/semipublic/resource/state/immutable_spec.rb +1 -2
  112. data/spec/semipublic/resource/state/transient_spec.rb +7 -2
  113. data/spec/semipublic/resource/state_spec.rb +1 -1
  114. data/spec/semipublic/resource_spec.rb +1 -1
  115. data/spec/unit/array_spec.rb +1 -0
  116. data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
  117. data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
  118. data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
  119. data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
  120. data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
  121. data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
  122. data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
  123. data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
  124. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
  125. data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
  126. data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
  127. data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
  128. data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
  129. data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
  130. data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
  131. data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
  132. data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
  133. data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
  134. data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
  135. data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
  136. data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
  137. data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
  138. data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
  139. data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
  140. data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
  141. data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
  142. data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
  143. data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
  144. data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
  145. data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
  146. data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
  147. data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
  148. data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
  149. data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
  150. data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
  151. data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
  152. data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
  153. data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
  154. data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
  155. data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
  156. data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
  157. data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
  158. data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
  159. data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
  160. data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
  161. data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
  162. data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
  163. data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
  164. data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
  165. data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
  166. data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
  167. data/spec/unit/hash_spec.rb +2 -1
  168. data/spec/unit/hook_spec.rb +1 -0
  169. data/spec/unit/lazy_array_spec.rb +2 -1
  170. data/spec/unit/module_spec.rb +2 -1
  171. data/spec/unit/object_spec.rb +1 -0
  172. data/spec/unit/try_dup_spec.rb +1 -0
  173. data/tasks/spec.rake +0 -3
  174. metadata +149 -52
  175. data/.gitignore +0 -37
  176. data/lib/dm-core/type.rb +0 -216
  177. data/lib/dm-core/types/boolean.rb +0 -9
  178. data/lib/dm-core/types/decimal.rb +0 -9
  179. data/lib/dm-core/types/discriminator.rb +0 -50
  180. data/lib/dm-core/types/object.rb +0 -25
  181. data/lib/dm-core/types/serial.rb +0 -11
  182. data/lib/dm-core/types/text.rb +0 -11
  183. data/tasks/local_gemfile.rake +0 -16
  184. data/tasks/metrics.rake +0 -37
@@ -81,13 +81,6 @@ require 'dm-core/support/subject'
81
81
 
82
82
  require 'dm-core/collection'
83
83
 
84
- require 'dm-core/type'
85
- require 'dm-core/types/boolean'
86
- require 'dm-core/types/discriminator'
87
- require 'dm-core/types/text'
88
- require 'dm-core/types/object'
89
- require 'dm-core/types/serial'
90
-
91
84
  require 'dm-core/property'
92
85
  require 'dm-core/property/object'
93
86
  require 'dm-core/property/string'
@@ -321,11 +314,12 @@ module DataMapper
321
314
  end
322
315
 
323
316
  private
317
+
324
318
  # @api private
325
319
  def self.finalize_model(model)
326
320
  name = model.name
327
321
  repository_name = model.repository_name
328
- relationships = model.relationships(repository_name).values
322
+ relationships = model.relationships(repository_name)
329
323
 
330
324
  if name.to_s.strip.empty?
331
325
  raise IncompleteModelError, "#{model.inspect} must have a name"
@@ -336,15 +330,31 @@ module DataMapper
336
330
  raise IncompleteModelError, "#{name} must have at least one property or many to one relationship to be valid"
337
331
  end
338
332
 
339
- # initialize join models and target keys
333
+ # Initialize all foreign key properties established by relationships
340
334
  relationships.each do |relationship|
341
- relationship.child_key
342
- relationship.through if relationship.respond_to?(:through)
343
- relationship.via if relationship.respond_to?(:via)
335
+ if relationship.kind_of?(Associations::ManyToOne::Relationship)
336
+ # Initialize the foreign key property this "many to one"
337
+ # relationship uses to persist itself
338
+ relationship.child_key
339
+ elsif relationship.kind_of?(Associations::ManyToMany::Relationship)
340
+ # Initialize the chain for "many to many" relationships
341
+ relationship.through
342
+ relationship.via
343
+ else
344
+ # If this is a "one to one" or "one to many" relationship, initialize
345
+ # the inverse "many to one" relationships explicitly before initializing
346
+ # other relationships. This makes sure that foreign key properties always
347
+ # appear in the order they were declared.
348
+ relationship.child_model.relationships.each do |remote_relationship|
349
+ if remote_relationship.kind_of?(Associations::ManyToOne::Relationship)
350
+ remote_relationship.child_key
351
+ end
352
+ end
353
+ end
344
354
  end
345
355
 
346
356
  if model.key(repository_name).empty?
347
357
  raise IncompleteModelError, "#{name} must have a key to be valid"
348
358
  end
349
359
  end
350
- end
360
+ end # module DataMapper
@@ -178,7 +178,7 @@ module DataMapper
178
178
  #
179
179
  # @param [Resource] resource
180
180
  # the resource to set the serial property in
181
- # @param [Integer] id
181
+ # @param [Integer] next_id
182
182
  # the identifier to set in the resource
183
183
  #
184
184
  # @return [undefined]
@@ -161,7 +161,7 @@ module DataMapper
161
161
  if namespace.const_defined?(name)
162
162
  namespace.const_get(name)
163
163
  else
164
- model = Model.new do
164
+ Model.new(name, namespace) do
165
165
  # all properties added to the anonymous through model are keys
166
166
  def property(name, type, options = {})
167
167
  options[:key] = true
@@ -169,8 +169,6 @@ module DataMapper
169
169
  super
170
170
  end
171
171
  end
172
-
173
- namespace.const_set(name, model)
174
172
  end
175
173
  end
176
174
 
@@ -31,36 +31,34 @@ module DataMapper
31
31
  @key
32
32
  end
33
33
 
34
- # @api private
34
+ # @deprecated
35
35
  def nullable?
36
- klass = self.class
37
- warn "#{klass}#nullable? is deprecated, use #{klass}#required? instead (#{caller[0]})"
38
- !required?
36
+ raise "#{self.class}#nullable? is deprecated, use #{self.class}#required? instead (#{caller.first})"
39
37
  end
40
38
 
41
- # Returns a set of keys that identify child model
39
+ # Returns a set of keys that identify source model
42
40
  #
43
- # @return [DataMapper::PropertySet] a set of properties that identify child model
41
+ # @return [DataMapper::PropertySet] a set of properties that identify source model
44
42
  # @api private
45
43
  def child_key
46
44
  return @child_key if defined?(@child_key)
47
45
 
48
- model = child_model
49
- repository_name = child_repository_name || parent_repository_name
46
+ model = source_model
47
+ repository_name = source_repository_name || target_repository_name
50
48
  properties = model.properties(repository_name)
51
49
 
52
- child_key = parent_key.zip(@child_properties || []).map do |parent_property, property_name|
53
- property_name ||= "#{name}_#{parent_property.name}".to_sym
50
+ source_key = target_key.zip(@child_properties || []).map do |target_property, property_name|
51
+ property_name ||= "#{name}_#{target_property.name}".to_sym
54
52
 
55
53
  properties[property_name] || begin
56
54
  # create the property within the correct repository
57
55
  DataMapper.repository(repository_name) do
58
- model.property(property_name, parent_property.to_child_key, child_key_options(parent_property))
56
+ model.property(property_name, target_property.to_child_key, source_key_options(target_property))
59
57
  end
60
58
  end
61
59
  end
62
60
 
63
- @child_key = properties.class.new(child_key).freeze
61
+ @child_key = properties.class.new(source_key).freeze
64
62
  end
65
63
 
66
64
  # @api semipublic
@@ -95,17 +93,25 @@ module DataMapper
95
93
  def resource_for(source, other_query = nil)
96
94
  query = query_for(source, other_query)
97
95
 
98
- # TODO: lookup the resource in the Identity Map, and make sure
99
- # it matches the query criteria, otherwise perform the query
100
-
101
- target_model.first(query)
96
+ # If the target key is equal to the model key, we can use the
97
+ # Model#get so the IdentityMap is used
98
+ if target_key == target_model.key
99
+ target = target_model.get(*source_key.get!(source))
100
+ if query.conditions.matches?(target)
101
+ target
102
+ else
103
+ nil
104
+ end
105
+ else
106
+ target_model.first(query)
107
+ end
102
108
  end
103
109
 
104
110
  # Loads and returns association target (ex.: author) for given source resource
105
111
  # (ex.: article)
106
112
  #
107
113
  # @param source [DataMapper::Resource]
108
- # Child object (ex.: instance of article)
114
+ # source object (ex.: instance of article)
109
115
  # @param other_query [DataMapper::Query]
110
116
  # Query options
111
117
  #
@@ -117,18 +123,18 @@ module DataMapper
117
123
  end
118
124
 
119
125
  def get_collection(source)
120
- resource = get!(source)
121
- resource.collection_for_self if resource
126
+ target = get!(source)
127
+ target.collection_for_self if target
122
128
  end
123
129
 
124
130
  # Sets value of association target (ex.: author) for given source resource
125
131
  # (ex.: article)
126
132
  #
127
133
  # @param source [DataMapper::Resource]
128
- # Child object (ex.: instance of article)
134
+ # source object (ex.: instance of article)
129
135
  #
130
- # @param source [DataMapper::Resource]
131
- # Parent object (ex.: instance of author)
136
+ # @param target [DataMapper::Resource]
137
+ # target object (ex.: instance of author)
132
138
  #
133
139
  # @api semipublic
134
140
  def set(source, target)
@@ -152,16 +158,21 @@ module DataMapper
152
158
  #
153
159
  # @api private
154
160
  def lazy_load(source)
155
- return if loaded?(source) || !valid_source?(source)
161
+ source_key_different = source_key_different?(source)
162
+
163
+ if (loaded?(source) && !source_key_different) || !valid_source?(source)
164
+ return
165
+ end
156
166
 
157
167
  # SEL: load all related resources in the source collection
158
- collection = source.collection
159
- if source.saved? && collection.size > 1
168
+ if source.saved? && (collection = source.collection).size > 1
160
169
  eager_load(collection)
161
170
  end
162
171
 
163
- unless loaded?(source)
172
+ if !loaded?(source) || (source_key_dirty?(source) && source.saved?)
164
173
  set!(source, resource_for(source))
174
+ elsif loaded?(source) && source_key_different
175
+ source_key.set(source, target_key.get!(get!(source)))
165
176
  end
166
177
  end
167
178
 
@@ -172,10 +183,7 @@ module DataMapper
172
183
  # @api semipublic
173
184
  def initialize(name, source_model, target_model, options = {})
174
185
  if options.key?(:nullable)
175
- nullable_options = options.only(:nullable)
176
- required_options = { :required => !options.delete(:nullable) }
177
- warn "#{nullable_options.inspect} is deprecated, use #{required_options.inspect} instead (#{caller[2]})"
178
- options.update(required_options)
186
+ raise ":nullable is deprecated, use :required instead (#{caller[2]})"
179
187
  end
180
188
 
181
189
  @required = options.fetch(:required, true)
@@ -225,16 +233,16 @@ module DataMapper
225
233
  end
226
234
 
227
235
  # @api private
228
- def child_key_options(parent_property)
229
- options = parent_property.options.only(:length, :precision, :scale).update(
236
+ def source_key_options(target_property)
237
+ options = target_property.options.only(:length, :precision, :scale).update(
230
238
  :index => name,
231
239
  :required => required?,
232
240
  :key => key?
233
241
  )
234
242
 
235
- if parent_property.primitive == Integer
236
- min = parent_property.min
237
- max = parent_property.max
243
+ if target_property.primitive == Integer
244
+ min = target_property.min
245
+ max = target_property.max
238
246
 
239
247
  options.update(:min => min, :max => max) if min && max
240
248
  end
@@ -244,7 +252,17 @@ module DataMapper
244
252
 
245
253
  # @api private
246
254
  def child_properties
247
- child_key.map { |property| property.name }
255
+ source_key.map { |property| property.name }
256
+ end
257
+
258
+ # @api private
259
+ def source_key_different?(source)
260
+ source_key.get!(source) != target_key.get!(get!(source))
261
+ end
262
+
263
+ # @api private
264
+ def source_key_dirty?(source)
265
+ source.dirty_attributes.keys.any? { |property| source_key.include?(property) }
248
266
  end
249
267
  end # class Relationship
250
268
  end # module ManyToOne
@@ -91,8 +91,7 @@ module DataMapper
91
91
  return if loaded?(source)
92
92
 
93
93
  # SEL: load all related resources in the source collection
94
- collection = source.collection
95
- if source.saved? && collection.size > 1
94
+ if source.saved? && (collection = source.collection).size > 1
96
95
  eager_load(collection)
97
96
  end
98
97
 
@@ -388,7 +388,7 @@ module DataMapper
388
388
  return @inverse
389
389
  end
390
390
 
391
- relationships = target_model.relationships(relative_target_repository_name).values
391
+ relationships = target_model.relationships(relative_target_repository_name)
392
392
 
393
393
  @inverse = relationships.detect { |relationship| inverse?(relationship) } ||
394
394
  invert
@@ -414,7 +414,16 @@ module DataMapper
414
414
 
415
415
  # @api private
416
416
  def hash
417
- source_model.hash ^ name.hash
417
+ name.hash ^
418
+ child_repository_name.hash ^
419
+ parent_repository_name.hash ^
420
+ child_model.hash ^
421
+ parent_model.hash ^
422
+ child_properties.hash ^
423
+ parent_properties.hash ^
424
+ min.hash ^
425
+ max.hash ^
426
+ query.hash
418
427
  end
419
428
 
420
429
  private
@@ -17,10 +17,6 @@ module DataMapper
17
17
  # A Collection is typically returned by the Model#all
18
18
  # method.
19
19
  class Collection < LazyArray
20
- extend Deprecate
21
-
22
- deprecate :add, :<<
23
- deprecate :build, :new
24
20
 
25
21
  # Returns the Query the Collection is scoped with
26
22
  #
@@ -170,7 +166,7 @@ module DataMapper
170
166
  @identity_map[key]
171
167
  else
172
168
  # current query is all inclusive, lookup using normal approach
173
- first(model.key_conditions(repository, key))
169
+ first(model.key_conditions(repository, key).update(:order => nil))
174
170
  end
175
171
  end
176
172
 
@@ -941,7 +937,7 @@ module DataMapper
941
937
  #
942
938
  # @api public
943
939
  def respond_to?(method, include_private = false)
944
- super || model.respond_to?(method) || relationships.key?(method)
940
+ super || model.respond_to?(method) || relationships.named?(method)
945
941
  end
946
942
 
947
943
  # Checks if all the resources have no changes to save
@@ -1265,7 +1261,7 @@ module DataMapper
1265
1261
  subject = condition.subject
1266
1262
  next unless model_properties.include?(subject) || (condition.relationship? && subject.source_model == model)
1267
1263
 
1268
- default_attributes[subject] = condition.value
1264
+ default_attributes[subject] = condition.loaded_value
1269
1265
  end
1270
1266
  end
1271
1267
 
@@ -2,7 +2,7 @@ class Symbol
2
2
  (DataMapper::Query::Conditions::Comparison.slugs | [ :not, :asc, :desc ]).each do |sym|
3
3
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
4
4
  def #{sym}
5
- #{"warn \"explicit use of '#{sym}' operator is deprecated (#{caller[0]})\"" if sym == :eql || sym == :in}
5
+ #{"raise \"explicit use of '#{sym}' operator is deprecated (#{caller.first})\"" if sym == :eql || sym == :in}
6
6
  DataMapper::Query::Operator.new(self, #{sym.inspect})
7
7
  end
8
8
  RUBY
@@ -3,10 +3,5 @@ module DataMapper
3
3
  # Tracks objects to help ensure that each object gets loaded only once.
4
4
  # See: http://www.martinfowler.com/eaaCatalog/identityMap.html
5
5
  class IdentityMap < Hash
6
- extend Deprecate
7
-
8
- deprecate :get, :[]
9
- deprecate :set, :[]=
10
-
11
6
  end # class IdentityMap
12
7
  end # module DataMapper
@@ -9,37 +9,28 @@ module DataMapper
9
9
 
10
10
  include Enumerable
11
11
 
12
- # Creates a new Model class with default_storage_name +storage_name+
12
+ # Creates a new Model class with its constant already set
13
13
  #
14
14
  # If a block is passed, it will be eval'd in the context of the new Model
15
15
  #
16
+ # @param [#to_s] name
17
+ # the name of the new model
18
+ # @param [Object] namespace
19
+ # the namespace that will hold the new model
16
20
  # @param [Proc] block
17
21
  # a block that will be eval'd in the context of the new Model class
18
22
  #
19
23
  # @return [Model]
20
24
  # the newly created Model class
21
25
  #
22
- # @api semipublic
23
- def self.new(storage_name = nil, &block)
24
- model = Class.new
26
+ # @api private
27
+ def self.new(name = nil, namespace = Object, &block)
28
+ model = name ? namespace.const_set(name, Class.new) : Class.new
25
29
 
26
30
  model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
27
31
  include DataMapper::Resource
28
-
29
- def self.name
30
- to_s
31
- end
32
32
  RUBY
33
33
 
34
- if storage_name
35
- warn "Passing in +storage_name+ to #{name}.new is deprecated (#{caller[0]})"
36
- model.class_eval <<-RUBY, __FILE__, __LINE__ + 1
37
- def self.default_storage_name
38
- #{DataMapper::Inflector.classify(storage_name).inspect}.freeze
39
- end
40
- RUBY
41
- end
42
-
43
34
  model.instance_eval(&block) if block
44
35
  model
45
36
  end
@@ -275,7 +266,7 @@ module DataMapper
275
266
  repository = self.repository
276
267
  key = self.key(repository.name).typecast(key)
277
268
 
278
- repository.identity_map(self)[key] || first(key_conditions(repository, key))
269
+ repository.identity_map(self)[key] || first(key_conditions(repository, key).update(:order => nil))
279
270
  end
280
271
 
281
272
  # Grab a single record just like #get, but raise an ObjectNotFoundError
@@ -716,8 +707,7 @@ module DataMapper
716
707
  # @api private
717
708
  def const_missing(name)
718
709
  if name == :DM
719
- warn "#{name} prefix deprecated and no longer necessary (#{caller[0]})"
720
- self
710
+ raise "#{name} prefix deprecated and no longer necessary (#{caller.first})"
721
711
  elsif name == :Resource
722
712
  Resource
723
713
  else
@@ -789,7 +779,7 @@ module DataMapper
789
779
 
790
780
  # initialize join models and target keys
791
781
  @relationships.values.each do |relationships|
792
- relationships.values.each do |relationship|
782
+ relationships.each do |relationship|
793
783
  relationship.child_key
794
784
  relationship.through if relationship.respond_to?(:through)
795
785
  relationship.via if relationship.respond_to?(:via)
@@ -1,6 +1,3 @@
1
- # TODO: move paranoid property concerns to a ParanoidModel that is mixed
2
- # into Model when a Paranoid property is used
3
-
4
1
  # TODO: update Model#respond_to? to return true if method_method missing
5
2
  # would handle the message
6
3
 
@@ -14,18 +11,16 @@ module DataMapper
14
11
  def self.extended(model)
15
12
  model.instance_variable_set(:@properties, {})
16
13
  model.instance_variable_set(:@field_naming_conventions, {})
17
- model.instance_variable_set(:@paranoid_properties, {})
18
14
  end
19
15
 
20
16
  chainable do
21
17
  def inherited(model)
22
18
  model.instance_variable_set(:@properties, {})
23
19
  model.instance_variable_set(:@field_naming_conventions, @field_naming_conventions.dup)
24
- model.instance_variable_set(:@paranoid_properties, @paranoid_properties.dup)
25
20
 
26
21
  @properties.each do |repository_name, properties|
27
22
  model_properties = model.properties(repository_name)
28
- properties.each { |property| model_properties[property.name] ||= property }
23
+ properties.each { |property| model_properties << property }
29
24
  end
30
25
 
31
26
  super
@@ -36,8 +31,8 @@ module DataMapper
36
31
  #
37
32
  # @param [Symbol] name
38
33
  # the name for which to call this property
39
- # @param [Type] type
40
- # the type to define this property ass
34
+ # @param [Class] type
35
+ # the ruby type to define this property as
41
36
  # @param [Hash(Symbol => String)] options
42
37
  # a hash of available options
43
38
  #
@@ -48,25 +43,19 @@ module DataMapper
48
43
  #
49
44
  # @api public
50
45
  def property(name, type, options = {})
51
- caller_method = caller[2]
52
-
53
46
  if TrueClass == type
54
- warn "#{type} is deprecated, use Boolean instead at #{caller_method}"
55
- type = DataMapper::Property::Boolean
47
+ raise "#{type} is deprecated, use Boolean instead at #{caller[2]}"
56
48
  elsif BigDecimal == type
57
- warn "#{type} is deprecated, use Decimal instead at #{caller_method}"
58
- type = DataMapper::Property::Decimal
49
+ raise "#{type} is deprecated, use Decimal instead at #{caller[2]}"
59
50
  end
60
51
 
61
52
  # if the type can be found within Property then
62
53
  # use that class rather than the primitive
63
- klass = DataMapper::Property.determine_class(type)
64
-
65
- unless klass
54
+ unless klass = DataMapper::Property.determine_class(type)
66
55
  raise ArgumentError, "+type+ was #{type.inspect}, which is not a supported type"
67
56
  end
68
57
 
69
- property = klass.new(self, name, options, type < DataMapper::Type ? type : nil)
58
+ property = klass.new(self, name, options)
70
59
 
71
60
  repository_name = self.repository_name
72
61
  properties = properties(repository_name)
@@ -76,11 +65,11 @@ module DataMapper
76
65
  # Add property to the other mappings as well if this is for the default
77
66
  # repository.
78
67
  if repository_name == default_repository_name
79
- @properties.except(repository_name).each do |repository_name, properties|
68
+ @properties.except(default_repository_name).each do |other_repository_name, properties|
80
69
  next if properties.named?(name)
81
70
 
82
71
  # make sure the property is created within the correct repository scope
83
- DataMapper.repository(repository_name) do
72
+ DataMapper.repository(other_repository_name) do
84
73
  properties << klass.new(self, name, options, type)
85
74
  end
86
75
  end
@@ -95,7 +84,7 @@ module DataMapper
95
84
  context = :default if context == true
96
85
 
97
86
  Array(context).each do |context|
98
- properties.lazy_context(context) << self
87
+ properties.lazy_context(context) << property
99
88
  end
100
89
  end
101
90
 
@@ -103,7 +92,7 @@ module DataMapper
103
92
  # added after the child classes' properties have been copied from
104
93
  # the parent
105
94
  descendants.each do |descendant|
106
- descendant.properties(repository_name)[name] ||= property
95
+ descendant.properties(repository_name) << property
107
96
  end
108
97
 
109
98
  create_reader_for(property)
@@ -120,7 +109,7 @@ module DataMapper
120
109
  # The name of the repository to use. Uses the default Repository
121
110
  # if none is specified.
122
111
  #
123
- # @return [Array]
112
+ # @return [PropertySet]
124
113
  # A list of Properties defined on this Model in the given Repository
125
114
  #
126
115
  # @api public
@@ -177,23 +166,13 @@ module DataMapper
177
166
 
178
167
  descendants.each do |model|
179
168
  model.properties(repository_name).each do |property|
180
- properties[property.name] ||= property
169
+ properties << property
181
170
  end
182
171
  end
183
172
 
184
173
  properties
185
174
  end
186
175
 
187
- # @api private
188
- def paranoid_properties
189
- @paranoid_properties
190
- end
191
-
192
- # @api private
193
- def set_paranoid_property(name, &block)
194
- paranoid_properties[name] = block
195
- end
196
-
197
176
  # @api private
198
177
  def key_conditions(repository, key)
199
178
  self.key(repository.name).zip(key.nil? ? [] : key).to_hash
@@ -201,6 +180,20 @@ module DataMapper
201
180
 
202
181
  private
203
182
 
183
+ # Defines the anonymous module that is used to add properties.
184
+ # Using a single module here prevents having a very large number
185
+ # of anonymous modules, where each property has their own module.
186
+ # @api private
187
+ def property_module
188
+ @property_module ||= begin
189
+ mod = Module.new
190
+ class_eval do
191
+ include mod
192
+ end
193
+ mod
194
+ end
195
+ end
196
+
204
197
  # defines the reader method for the property
205
198
  #
206
199
  # @api private
@@ -208,27 +201,22 @@ module DataMapper
208
201
  name = property.name.to_s
209
202
  reader_visibility = property.reader_visibility
210
203
  instance_variable_name = property.instance_variable_name
211
-
212
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
213
- chainable do
214
- #{reader_visibility}
215
- def #{name}
216
- return #{instance_variable_name} if defined?(#{instance_variable_name})
217
- property = properties[#{name.inspect}]
218
- #{instance_variable_name} = property ? persisted_state.get(property) : nil
219
- end
204
+ property_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
205
+ #{reader_visibility}
206
+ def #{name}
207
+ return #{instance_variable_name} if defined?(#{instance_variable_name})
208
+ property = properties[#{name.inspect}]
209
+ #{instance_variable_name} = property ? persisted_state.get(property) : nil
220
210
  end
221
211
  RUBY
222
212
 
223
213
  boolean_reader_name = "#{name}?"
224
214
 
225
215
  if property.kind_of?(DataMapper::Property::Boolean)
226
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
227
- chainable do
228
- #{reader_visibility}
229
- def #{boolean_reader_name}
230
- #{name}
231
- end
216
+ property_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
217
+ #{reader_visibility}
218
+ def #{boolean_reader_name}
219
+ #{name}
232
220
  end
233
221
  RUBY
234
222
  end
@@ -242,15 +230,12 @@ module DataMapper
242
230
  writer_visibility = property.writer_visibility
243
231
 
244
232
  writer_name = "#{name}="
245
-
246
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
247
- chainable do
248
- #{writer_visibility}
249
- def #{writer_name}(value)
250
- property = properties[#{name.inspect}]
251
- self.persisted_state = persisted_state.set(property, value)
252
- persisted_state.get(property)
253
- end
233
+ property_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1
234
+ #{writer_visibility}
235
+ def #{writer_name}(value)
236
+ property = properties[#{name.inspect}]
237
+ self.persisted_state = persisted_state.set(property, value)
238
+ persisted_state.get(property)
254
239
  end
255
240
  RUBY
256
241
  end