dm-core 0.10.2 → 1.0.0.rc1

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 (183) hide show
  1. data/.gitignore +10 -1
  2. data/Gemfile +143 -0
  3. data/Rakefile +9 -5
  4. data/VERSION +1 -1
  5. data/dm-core.gemspec +160 -57
  6. data/lib/dm-core.rb +131 -56
  7. data/lib/dm-core/adapters.rb +98 -14
  8. data/lib/dm-core/adapters/abstract_adapter.rb +24 -4
  9. data/lib/dm-core/adapters/in_memory_adapter.rb +7 -2
  10. data/lib/dm-core/associations/many_to_many.rb +19 -30
  11. data/lib/dm-core/associations/many_to_one.rb +58 -42
  12. data/lib/dm-core/associations/one_to_many.rb +33 -23
  13. data/lib/dm-core/associations/one_to_one.rb +27 -11
  14. data/lib/dm-core/associations/relationship.rb +4 -4
  15. data/lib/dm-core/collection.rb +23 -16
  16. data/lib/dm-core/core_ext/array.rb +36 -0
  17. data/lib/dm-core/core_ext/hash.rb +30 -0
  18. data/lib/dm-core/core_ext/module.rb +46 -0
  19. data/lib/dm-core/core_ext/object.rb +31 -0
  20. data/lib/dm-core/core_ext/pathname.rb +20 -0
  21. data/lib/dm-core/core_ext/string.rb +22 -0
  22. data/lib/dm-core/core_ext/try_dup.rb +44 -0
  23. data/lib/dm-core/model.rb +88 -27
  24. data/lib/dm-core/model/hook.rb +75 -18
  25. data/lib/dm-core/model/property.rb +50 -9
  26. data/lib/dm-core/model/relationship.rb +31 -31
  27. data/lib/dm-core/model/scope.rb +3 -3
  28. data/lib/dm-core/property.rb +196 -516
  29. data/lib/dm-core/property/binary.rb +7 -0
  30. data/lib/dm-core/property/boolean.rb +35 -0
  31. data/lib/dm-core/property/class.rb +24 -0
  32. data/lib/dm-core/property/date.rb +47 -0
  33. data/lib/dm-core/property/date_time.rb +48 -0
  34. data/lib/dm-core/property/decimal.rb +43 -0
  35. data/lib/dm-core/property/discriminator.rb +48 -0
  36. data/lib/dm-core/property/float.rb +24 -0
  37. data/lib/dm-core/property/integer.rb +32 -0
  38. data/lib/dm-core/property/numeric.rb +43 -0
  39. data/lib/dm-core/property/object.rb +32 -0
  40. data/lib/dm-core/property/serial.rb +8 -0
  41. data/lib/dm-core/property/string.rb +49 -0
  42. data/lib/dm-core/property/text.rb +12 -0
  43. data/lib/dm-core/property/time.rb +48 -0
  44. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  45. data/lib/dm-core/property/typecast/time.rb +28 -0
  46. data/lib/dm-core/property_set.rb +10 -4
  47. data/lib/dm-core/query.rb +14 -37
  48. data/lib/dm-core/query/conditions/comparison.rb +8 -6
  49. data/lib/dm-core/query/conditions/operation.rb +33 -2
  50. data/lib/dm-core/query/operator.rb +2 -5
  51. data/lib/dm-core/query/path.rb +4 -6
  52. data/lib/dm-core/repository.rb +21 -6
  53. data/lib/dm-core/resource.rb +316 -133
  54. data/lib/dm-core/resource/state.rb +79 -0
  55. data/lib/dm-core/resource/state/clean.rb +40 -0
  56. data/lib/dm-core/resource/state/deleted.rb +30 -0
  57. data/lib/dm-core/resource/state/dirty.rb +86 -0
  58. data/lib/dm-core/resource/state/immutable.rb +34 -0
  59. data/lib/dm-core/resource/state/persisted.rb +29 -0
  60. data/lib/dm-core/resource/state/transient.rb +70 -0
  61. data/lib/dm-core/spec/lib/adapter_helpers.rb +52 -0
  62. data/lib/dm-core/spec/lib/collection_helpers.rb +20 -0
  63. data/{spec → lib/dm-core/spec}/lib/counter_adapter.rb +5 -1
  64. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  65. data/lib/dm-core/spec/lib/spec_helper.rb +68 -0
  66. data/lib/dm-core/spec/setup.rb +165 -0
  67. data/lib/dm-core/spec/{adapter_shared_spec.rb → shared/adapter_spec.rb} +21 -7
  68. data/{spec/public/shared/resource_shared_spec.rb → lib/dm-core/spec/shared/resource_spec.rb} +120 -83
  69. data/{spec/public/shared/sel_shared_spec.rb → lib/dm-core/spec/shared/sel_spec.rb} +5 -6
  70. data/lib/dm-core/support/assertions.rb +8 -0
  71. data/lib/dm-core/support/equalizer.rb +1 -0
  72. data/lib/dm-core/support/hook.rb +420 -0
  73. data/lib/dm-core/support/lazy_array.rb +453 -0
  74. data/lib/dm-core/support/local_object_space.rb +12 -0
  75. data/lib/dm-core/support/logger.rb +193 -6
  76. data/lib/dm-core/support/naming_conventions.rb +8 -8
  77. data/lib/dm-core/support/subject.rb +33 -0
  78. data/lib/dm-core/type.rb +4 -0
  79. data/lib/dm-core/types/boolean.rb +2 -0
  80. data/lib/dm-core/types/decimal.rb +9 -0
  81. data/lib/dm-core/types/discriminator.rb +2 -0
  82. data/lib/dm-core/types/object.rb +3 -0
  83. data/lib/dm-core/types/serial.rb +2 -0
  84. data/lib/dm-core/types/text.rb +2 -0
  85. data/lib/dm-core/version.rb +1 -1
  86. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +67 -0
  87. data/spec/public/model/hook_spec.rb +209 -0
  88. data/spec/public/model/property_spec.rb +35 -0
  89. data/spec/public/model/relationship_spec.rb +33 -20
  90. data/spec/public/model_spec.rb +142 -10
  91. data/spec/public/property/binary_spec.rb +14 -0
  92. data/spec/public/property/boolean_spec.rb +14 -0
  93. data/spec/public/property/class_spec.rb +20 -0
  94. data/spec/public/property/date_spec.rb +14 -0
  95. data/spec/public/property/date_time_spec.rb +14 -0
  96. data/spec/public/property/decimal_spec.rb +14 -0
  97. data/spec/public/{types → property}/discriminator_spec.rb +2 -12
  98. data/spec/public/property/float_spec.rb +14 -0
  99. data/spec/public/property/integer_spec.rb +14 -0
  100. data/spec/public/property/object_spec.rb +9 -17
  101. data/spec/public/property/serial_spec.rb +14 -0
  102. data/spec/public/property/string_spec.rb +14 -0
  103. data/spec/public/property/text_spec.rb +52 -0
  104. data/spec/public/property/time_spec.rb +14 -0
  105. data/spec/public/property_spec.rb +28 -87
  106. data/spec/public/resource_spec.rb +101 -0
  107. data/spec/public/sel_spec.rb +5 -15
  108. data/spec/public/shared/collection_shared_spec.rb +16 -30
  109. data/spec/public/shared/finder_shared_spec.rb +2 -4
  110. data/spec/public/shared/property_shared_spec.rb +176 -0
  111. data/spec/semipublic/adapters/abstract_adapter_spec.rb +1 -1
  112. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +2 -2
  113. data/spec/semipublic/associations/many_to_many_spec.rb +89 -0
  114. data/spec/semipublic/associations/many_to_one_spec.rb +24 -1
  115. data/spec/semipublic/associations/one_to_many_spec.rb +51 -0
  116. data/spec/semipublic/associations/one_to_one_spec.rb +49 -0
  117. data/spec/semipublic/associations/relationship_spec.rb +3 -3
  118. data/spec/semipublic/associations_spec.rb +1 -1
  119. data/spec/semipublic/property/binary_spec.rb +13 -0
  120. data/spec/semipublic/property/boolean_spec.rb +65 -0
  121. data/spec/semipublic/property/class_spec.rb +33 -0
  122. data/spec/semipublic/property/date_spec.rb +43 -0
  123. data/spec/semipublic/property/date_time_spec.rb +46 -0
  124. data/spec/semipublic/property/decimal_spec.rb +82 -0
  125. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  126. data/spec/semipublic/property/float_spec.rb +82 -0
  127. data/spec/semipublic/property/integer_spec.rb +82 -0
  128. data/spec/semipublic/property/serial_spec.rb +13 -0
  129. data/spec/semipublic/property/string_spec.rb +13 -0
  130. data/spec/semipublic/property/text_spec.rb +31 -0
  131. data/spec/semipublic/property/time_spec.rb +50 -0
  132. data/spec/semipublic/property_spec.rb +2 -532
  133. data/spec/semipublic/query/conditions/comparison_spec.rb +171 -169
  134. data/spec/semipublic/query/conditions/operation_spec.rb +53 -51
  135. data/spec/semipublic/query/path_spec.rb +17 -17
  136. data/spec/semipublic/query_spec.rb +47 -78
  137. data/spec/semipublic/resource/state/clean_spec.rb +88 -0
  138. data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
  139. data/spec/semipublic/resource/state/dirty_spec.rb +133 -0
  140. data/spec/semipublic/resource/state/immutable_spec.rb +99 -0
  141. data/spec/semipublic/resource/state/transient_spec.rb +128 -0
  142. data/spec/semipublic/resource/state_spec.rb +226 -0
  143. data/spec/semipublic/shared/property_shared_spec.rb +143 -0
  144. data/spec/semipublic/shared/resource_shared_spec.rb +16 -15
  145. data/spec/semipublic/shared/resource_state_shared_spec.rb +78 -0
  146. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  147. data/spec/spec_helper.rb +21 -97
  148. data/spec/support/types/huge_integer.rb +17 -0
  149. data/spec/unit/array_spec.rb +48 -0
  150. data/spec/unit/hash_spec.rb +35 -0
  151. data/spec/unit/hook_spec.rb +1234 -0
  152. data/spec/unit/lazy_array_spec.rb +1959 -0
  153. data/spec/unit/module_spec.rb +70 -0
  154. data/spec/unit/object_spec.rb +37 -0
  155. data/spec/unit/try_dup_spec.rb +45 -0
  156. data/tasks/local_gemfile.rake +18 -0
  157. data/tasks/spec.rake +0 -3
  158. metadata +197 -71
  159. data/deps.rip +0 -2
  160. data/lib/dm-core/adapters/data_objects_adapter.rb +0 -712
  161. data/lib/dm-core/adapters/mysql_adapter.rb +0 -42
  162. data/lib/dm-core/adapters/oracle_adapter.rb +0 -229
  163. data/lib/dm-core/adapters/postgres_adapter.rb +0 -22
  164. data/lib/dm-core/adapters/sqlite3_adapter.rb +0 -17
  165. data/lib/dm-core/adapters/sqlserver_adapter.rb +0 -114
  166. data/lib/dm-core/adapters/yaml_adapter.rb +0 -111
  167. data/lib/dm-core/core_ext/enumerable.rb +0 -28
  168. data/lib/dm-core/migrations.rb +0 -1427
  169. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +0 -366
  170. data/lib/dm-core/transaction.rb +0 -508
  171. data/lib/dm-core/types/paranoid_boolean.rb +0 -42
  172. data/lib/dm-core/types/paranoid_datetime.rb +0 -41
  173. data/spec/lib/adapter_helpers.rb +0 -105
  174. data/spec/lib/collection_helpers.rb +0 -18
  175. data/spec/lib/pending_helpers.rb +0 -46
  176. data/spec/public/migrations_spec.rb +0 -503
  177. data/spec/public/transaction_spec.rb +0 -153
  178. data/spec/semipublic/adapters/mysql_adapter_spec.rb +0 -17
  179. data/spec/semipublic/adapters/oracle_adapter_spec.rb +0 -194
  180. data/spec/semipublic/adapters/postgres_adapter_spec.rb +0 -17
  181. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +0 -17
  182. data/spec/semipublic/adapters/sqlserver_adapter_spec.rb +0 -17
  183. data/spec/semipublic/adapters/yaml_adapter_spec.rb +0 -12
@@ -162,9 +162,9 @@ module DataMapper
162
162
  namespace.const_get(name)
163
163
  else
164
164
  model = Model.new do
165
- # all properties added to the anonymous through model are keys by default
165
+ # all properties added to the anonymous through model are keys
166
166
  def property(name, type, options = {})
167
- options[:key] = true unless options.key?(:key)
167
+ options[:key] = true
168
168
  options.delete(:index)
169
169
  super
170
170
  end
@@ -196,7 +196,7 @@ module DataMapper
196
196
  def through_relationship_name
197
197
  if anonymous_through_model?
198
198
  namespace = through_model_namespace_name.first
199
- relationship_name = Extlib::Inflection.underscore(through_model.name.sub(/\A#{namespace.name}::/, '')).tr('/', '_')
199
+ relationship_name = ActiveSupport::Inflector.underscore(through_model.name.sub(/\A#{namespace.name}::/, '')).tr('/', '_')
200
200
  relationship_name.pluralize.to_sym
201
201
  else
202
202
  options[:through]
@@ -302,20 +302,6 @@ module DataMapper
302
302
  )
303
303
  end
304
304
 
305
- # Loads association targets and sets resulting value on
306
- # given source resource
307
- #
308
- # @param [Resource] source
309
- # the source resource for the association
310
- #
311
- # @return [undefined]
312
- #
313
- # @api private
314
- def lazy_load(source)
315
- # FIXME: delegate to super once SEL is enabled
316
- set!(source, collection_for(source))
317
- end
318
-
319
305
  # Returns collection class used by this type of
320
306
  # relationship
321
307
  #
@@ -374,7 +360,10 @@ module DataMapper
374
360
  return false
375
361
  end
376
362
 
377
- each { |resource| resource.reset }
363
+ each do |resource|
364
+ resource.persisted_state = Resource::State::Immutable.new(resource)
365
+ end
366
+
378
367
  clear
379
368
 
380
369
  true
@@ -391,7 +380,7 @@ module DataMapper
391
380
  source = self.source
392
381
 
393
382
  @intermediaries ||= if through.loaded?(source)
394
- through.get!(source)
383
+ through.get_collection(source)
395
384
  else
396
385
  reset_intermediaries
397
386
  end
@@ -422,27 +411,27 @@ module DataMapper
422
411
  private
423
412
 
424
413
  # @api private
425
- def _create(safe, attributes)
414
+ def _create(attributes, execute_hooks = true)
426
415
  via = self.via
427
416
  if via.respond_to?(:resource_for)
428
417
  resource = super
429
- if create_intermediary(safe, resource)
418
+ if create_intermediary(execute_hooks, resource)
430
419
  resource
431
420
  end
432
421
  else
433
- if intermediary = create_intermediary(safe)
434
- super(safe, attributes.merge(via.inverse => intermediary))
422
+ if intermediary = create_intermediary(execute_hooks)
423
+ super(attributes.merge(via.inverse => intermediary), execute_hooks)
435
424
  end
436
425
  end
437
426
  end
438
427
 
439
428
  # @api private
440
- def _save(safe)
429
+ def _save(execute_hooks = true)
441
430
  via = self.via
442
431
 
443
432
  if @removed.any?
444
433
  # delete only intermediaries linked to the removed targets
445
- return false unless intermediaries.all(via => @removed).send(safe ? :destroy : :destroy!)
434
+ return false unless intermediaries.all(via => @removed).send(execute_hooks ? :destroy : :destroy!)
446
435
 
447
436
  # reset the intermediaries so that it reflects the current state of the datastore
448
437
  reset_intermediaries
@@ -452,9 +441,9 @@ module DataMapper
452
441
 
453
442
  if via.respond_to?(:resource_for)
454
443
  super
455
- loaded_entries.all? { |resource| create_intermediary(safe, resource) }
444
+ loaded_entries.all? { |resource| create_intermediary(execute_hooks, resource) }
456
445
  else
457
- if intermediary = create_intermediary(safe)
446
+ if loaded_entries.any? && (intermediary = create_intermediary(execute_hooks))
458
447
  inverse = via.inverse
459
448
  loaded_entries.each { |resource| inverse.set(resource, intermediary) }
460
449
  end
@@ -464,14 +453,14 @@ module DataMapper
464
453
  end
465
454
 
466
455
  # @api private
467
- def create_intermediary(safe, resource = nil)
456
+ def create_intermediary(execute_hooks, resource = nil)
468
457
  intermediary_for = self.intermediary_for
469
458
 
470
459
  intermediary_resource = intermediary_for[resource]
471
460
  return intermediary_resource if intermediary_resource
472
461
 
473
462
  intermediaries = self.intermediaries
474
- method = safe ? :save : :save!
463
+ method = execute_hooks ? :save : :save!
475
464
 
476
465
  return unless intermediaries.send(method)
477
466
 
@@ -490,7 +479,7 @@ module DataMapper
490
479
  through = self.through
491
480
  source = self.source
492
481
 
493
- through.set!(source, through.collection_for(source))
482
+ through.set_collection(source, through.collection_for(source))
494
483
  end
495
484
 
496
485
  # @api private
@@ -4,7 +4,7 @@ module DataMapper
4
4
  # Relationship class with implementation specific
5
5
  # to n side of 1 to n association
6
6
  class Relationship < Associations::Relationship
7
- OPTIONS = superclass::OPTIONS.dup << :required
7
+ OPTIONS = superclass::OPTIONS.dup << :required << :key
8
8
 
9
9
  # @api semipublic
10
10
  alias source_repository_name child_repository_name
@@ -26,6 +26,11 @@ module DataMapper
26
26
  @required
27
27
  end
28
28
 
29
+ # @api semipublic
30
+ def key?
31
+ @key
32
+ end
33
+
29
34
  # @api private
30
35
  def nullable?
31
36
  klass = self.class
@@ -50,7 +55,7 @@ module DataMapper
50
55
  properties[property_name] || begin
51
56
  # create the property within the correct repository
52
57
  DataMapper.repository(repository_name) do
53
- type = parent_property.send(parent_property.type == DataMapper::Types::Boolean ? :type : :primitive)
58
+ type = parent_property.send(parent_property.type == DataMapper::Property::Boolean ? :type : :primitive)
54
59
  model.property(property_name, type, child_key_options(parent_property))
55
60
  end
56
61
  end
@@ -106,15 +111,15 @@ module DataMapper
106
111
  # Query options
107
112
  #
108
113
  # @api semipublic
109
- def get(source, other_query = nil)
110
- assert_kind_of 'source', source, source_model
111
-
112
- lazy_load(source) unless loaded?(source)
114
+ def get(source, query = nil)
115
+ lazy_load(source)
116
+ collection = get_collection(source)
117
+ collection.first(query) if collection
118
+ end
113
119
 
120
+ def get_collection(source)
114
121
  resource = get!(source)
115
- if other_query.nil? || query_for(source, other_query).conditions.matches?(resource)
116
- resource
117
- end
122
+ resource.collection_for_self if resource
118
123
  end
119
124
 
120
125
  # Sets value of association target (ex.: author) for given source resource
@@ -128,36 +133,14 @@ module DataMapper
128
133
  #
129
134
  # @api semipublic
130
135
  def set(source, target)
131
- target_model = self.target_model
132
-
133
- assert_kind_of 'source', source, source_model
134
- assert_kind_of 'target', target, target_model, Hash, NilClass
135
-
136
- if target.kind_of?(Hash)
137
- target = target_model.new(target)
138
- end
139
-
140
- source_key.set(source, target.nil? ? [] : target_key.get(target))
136
+ target = typecast(target)
137
+ source_key.set(source, target_key.get(target))
141
138
  set!(source, target)
142
139
  end
143
140
 
144
- private
145
-
146
- # Initializes the relationship, always using max cardinality of 1.
147
- #
148
141
  # @api semipublic
149
- def initialize(name, source_model, target_model, options = {})
150
- if options.key?(:nullable)
151
- nullable_options = options.only(:nullable)
152
- required_options = { :required => !options.delete(:nullable) }
153
- warn "#{nullable_options.inspect} is deprecated, use #{required_options.inspect} instead (#{caller[2]})"
154
- options.update(required_options)
155
- end
156
-
157
- @required = options.fetch(:required, true)
158
- target_model ||= Extlib::Inflection.camelize(name)
159
- options = { :min => @required ? 1 : 0, :max => 1 }.update(options)
160
- super
142
+ def default_for(source)
143
+ typecast(super)
161
144
  end
162
145
 
163
146
  # Loads association target and sets resulting value on
@@ -170,7 +153,7 @@ module DataMapper
170
153
  #
171
154
  # @api private
172
155
  def lazy_load(source)
173
- return unless valid_source?(source)
156
+ return if loaded?(source) || !valid_source?(source)
174
157
 
175
158
  # SEL: load all related resources in the source collection
176
159
  collection = source.collection
@@ -183,6 +166,26 @@ module DataMapper
183
166
  end
184
167
  end
185
168
 
169
+ private
170
+
171
+ # Initializes the relationship, always using max cardinality of 1.
172
+ #
173
+ # @api semipublic
174
+ def initialize(name, source_model, target_model, options = {})
175
+ if options.key?(:nullable)
176
+ nullable_options = options.only(:nullable)
177
+ required_options = { :required => !options.delete(:nullable) }
178
+ warn "#{nullable_options.inspect} is deprecated, use #{required_options.inspect} instead (#{caller[2]})"
179
+ options.update(required_options)
180
+ end
181
+
182
+ @required = options.fetch(:required, true)
183
+ @key = options.fetch(:key, false)
184
+ target_model ||= ActiveSupport::Inflector.camelize(name)
185
+ options = { :min => @required ? 1 : 0, :max => 1 }.update(options)
186
+ super
187
+ end
188
+
186
189
  # Sets the association targets in the resource
187
190
  #
188
191
  # @param [Resource] source
@@ -199,6 +202,15 @@ module DataMapper
199
202
  set(source, targets.first)
200
203
  end
201
204
 
205
+ # @api private
206
+ def typecast(target)
207
+ if target.kind_of?(Hash)
208
+ target_model.new(target)
209
+ else
210
+ target
211
+ end
212
+ end
213
+
202
214
  # Returns the inverse relationship class
203
215
  #
204
216
  # @api private
@@ -210,18 +222,22 @@ module DataMapper
210
222
  #
211
223
  # @api private
212
224
  def inverse_name
213
- super || Extlib::Inflection.underscore(Extlib::Inflection.demodulize(source_model.name)).pluralize.to_sym
225
+ super || ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(source_model.name)).pluralize.to_sym
214
226
  end
215
227
 
216
228
  # @api private
217
229
  def child_key_options(parent_property)
218
- options = parent_property.options.only(:length, :precision, :scale).update(:index => name, :required => required?)
230
+ options = parent_property.options.only(:length, :precision, :scale).update(
231
+ :index => name,
232
+ :required => required?,
233
+ :key => key?
234
+ )
219
235
 
220
- min = parent_property.min
221
- max = parent_property.max
236
+ if parent_property.primitive == Integer
237
+ min = parent_property.min
238
+ max = parent_property.max
222
239
 
223
- if parent_property.primitive == Integer && min && max
224
- options.update(:min => min, :max => max)
240
+ options.update(:min => min, :max => max) if min && max
225
241
  end
226
242
 
227
243
  options
@@ -43,8 +43,8 @@ module DataMapper
43
43
  collection.relationship = self
44
44
  collection.source = source
45
45
 
46
- # make the collection empty if the source is not saved
47
- collection.replace([]) unless source.saved?
46
+ # make the collection empty if the source is new
47
+ collection.replace([]) if source.new?
48
48
 
49
49
  collection
50
50
  end
@@ -53,13 +53,15 @@ module DataMapper
53
53
  # (ex.: author)
54
54
  #
55
55
  # @api semipublic
56
- def get(source, other_query = nil)
57
- assert_kind_of 'source', source, source_model
58
-
59
- lazy_load(source) unless loaded?(source)
56
+ def get(source, query = nil)
57
+ lazy_load(source)
58
+ collection = get_collection(source)
59
+ query ? collection.all(query) : collection
60
+ end
60
61
 
61
- collection = get!(source)
62
- other_query.nil? ? collection : collection.all(other_query)
62
+ # @api private
63
+ def get_collection(source)
64
+ get!(source)
63
65
  end
64
66
 
65
67
  # Sets value of association targets (ex.: paragraphs) for given source resource
@@ -67,21 +69,13 @@ module DataMapper
67
69
  #
68
70
  # @api semipublic
69
71
  def set(source, targets)
70
- assert_kind_of 'source', source, source_model
71
- assert_kind_of 'targets', targets, Array
72
-
73
- lazy_load(source) unless loaded?(source)
74
-
72
+ lazy_load(source)
75
73
  get!(source).replace(targets)
76
74
  end
77
75
 
78
- private
79
-
80
- # @api semipublic
81
- def initialize(name, target_model, source_model, options = {})
82
- target_model ||= Extlib::Inflection.camelize(name.to_s.singular)
83
- options = { :min => 0, :max => source_model.n }.update(options)
84
- super
76
+ # @api private
77
+ def set_collection(source, target)
78
+ set!(source, target)
85
79
  end
86
80
 
87
81
  # Loads association targets and sets resulting value on
@@ -94,6 +88,8 @@ module DataMapper
94
88
  #
95
89
  # @api private
96
90
  def lazy_load(source)
91
+ return if loaded?(source)
92
+
97
93
  # SEL: load all related resources in the source collection
98
94
  collection = source.collection
99
95
  if source.saved? && collection.size > 1
@@ -105,6 +101,20 @@ module DataMapper
105
101
  end
106
102
  end
107
103
 
104
+ # @api semipublic
105
+ def default_for(source)
106
+ collection_for(source).replace(Array(super))
107
+ end
108
+
109
+ private
110
+
111
+ # @api semipublic
112
+ def initialize(name, target_model, source_model, options = {})
113
+ target_model ||= ActiveSupport::Inflector.camelize(name.to_s.singularize)
114
+ options = { :min => 0, :max => source_model.n }.update(options)
115
+ super
116
+ end
117
+
108
118
  # Sets the association targets in the resource
109
119
  #
110
120
  # @param [Resource] source
@@ -140,7 +150,7 @@ module DataMapper
140
150
  #
141
151
  # @api private
142
152
  def inverse_name
143
- super || Extlib::Inflection.underscore(Extlib::Inflection.demodulize(source_model.name)).to_sym
153
+ super || ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(source_model.name)).to_sym
144
154
  end
145
155
 
146
156
  # @api private
@@ -257,11 +267,11 @@ module DataMapper
257
267
  end
258
268
 
259
269
  # @api private
260
- def _save(safe)
270
+ def _save(execute_hooks = true)
261
271
  assert_source_saved 'The source must be saved before saving the collection'
262
272
 
263
273
  # update removed resources to not reference the source
264
- @removed.all? { |resource| resource.destroyed? || resource.__send__(safe ? :save : :save!) } && super
274
+ @removed.all? { |resource| resource.destroyed? || resource.__send__(execute_hooks ? :save : :save!) } && super
265
275
  end
266
276
 
267
277
  # @api private
@@ -3,8 +3,11 @@ module DataMapper
3
3
  module OneToOne #:nodoc:
4
4
  class Relationship < Associations::Relationship
5
5
  %w[ public protected private ].map do |visibility|
6
- superclass.send("#{visibility}_instance_methods", false).each do |method|
7
- undef_method method unless method.to_s == 'initialize'
6
+ methods = superclass.send("#{visibility}_instance_methods", false) |
7
+ DataMapper::Subject.send("#{visibility}_instance_methods", false)
8
+
9
+ methods.each do |method|
10
+ undef_method method.to_sym unless method.to_s == 'initialize'
8
11
  end
9
12
  end
10
13
 
@@ -12,12 +15,16 @@ module DataMapper
12
15
  # for given source
13
16
  #
14
17
  # @api semipublic
15
- def get(source, other_query = nil)
16
- assert_kind_of 'source', source, source_model
17
-
18
- return unless loaded?(source) || valid_source?(source)
18
+ def get(source, query = nil)
19
+ relationship.get(source, query).first
20
+ end
19
21
 
20
- relationship.get(source, other_query).first
22
+ # Get the resource directly
23
+ #
24
+ # @api semipublic
25
+ def get!(source)
26
+ collection = relationship.get!(source)
27
+ collection.first if collection
21
28
  end
22
29
 
23
30
  # Sets and returns association target
@@ -25,12 +32,21 @@ module DataMapper
25
32
  #
26
33
  # @api semipublic
27
34
  def set(source, target)
28
- assert_kind_of 'source', source, source_model
29
- assert_kind_of 'target', target, target_model, Hash, NilClass
30
-
31
35
  relationship.set(source, [ target ].compact).first
32
36
  end
33
37
 
38
+ # Sets the resource directly
39
+ #
40
+ # @api semipublic
41
+ def set!(source, target)
42
+ set(source, target)
43
+ end
44
+
45
+ # @api semipublic
46
+ def default_for(source)
47
+ relationship.default_for(source).first
48
+ end
49
+
34
50
  # @api public
35
51
  def kind_of?(klass)
36
52
  super || relationship.kind_of?(klass)
@@ -56,7 +72,7 @@ module DataMapper
56
72
  # @api semipublic
57
73
  def initialize(name, target_model, source_model, options = {})
58
74
  klass = options.key?(:through) ? ManyToMany::Relationship : OneToMany::Relationship
59
- target_model ||= Extlib::Inflection.camelize(name).freeze
75
+ target_model ||= ActiveSupport::Inflector.camelize(name).freeze
60
76
  @relationship = klass.new(name, target_model, source_model, options)
61
77
  end
62
78