ghost_dm-core 1.3.0.beta

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 (254) hide show
  1. data/.autotest +29 -0
  2. data/.document +5 -0
  3. data/.gitignore +35 -0
  4. data/.yardopts +1 -0
  5. data/Gemfile +65 -0
  6. data/LICENSE +20 -0
  7. data/README.md +269 -0
  8. data/Rakefile +4 -0
  9. data/dm-core.gemspec +24 -0
  10. data/lib/dm-core.rb +292 -0
  11. data/lib/dm-core/adapters.rb +222 -0
  12. data/lib/dm-core/adapters/abstract_adapter.rb +237 -0
  13. data/lib/dm-core/adapters/in_memory_adapter.rb +113 -0
  14. data/lib/dm-core/associations/many_to_many.rb +499 -0
  15. data/lib/dm-core/associations/many_to_one.rb +290 -0
  16. data/lib/dm-core/associations/one_to_many.rb +348 -0
  17. data/lib/dm-core/associations/one_to_one.rb +86 -0
  18. data/lib/dm-core/associations/relationship.rb +663 -0
  19. data/lib/dm-core/backwards.rb +13 -0
  20. data/lib/dm-core/collection.rb +1515 -0
  21. data/lib/dm-core/core_ext/kernel.rb +23 -0
  22. data/lib/dm-core/core_ext/pathname.rb +6 -0
  23. data/lib/dm-core/core_ext/symbol.rb +10 -0
  24. data/lib/dm-core/identity_map.rb +7 -0
  25. data/lib/dm-core/model.rb +874 -0
  26. data/lib/dm-core/model/hook.rb +103 -0
  27. data/lib/dm-core/model/is.rb +32 -0
  28. data/lib/dm-core/model/property.rb +249 -0
  29. data/lib/dm-core/model/relationship.rb +378 -0
  30. data/lib/dm-core/model/scope.rb +89 -0
  31. data/lib/dm-core/property.rb +866 -0
  32. data/lib/dm-core/property/binary.rb +21 -0
  33. data/lib/dm-core/property/boolean.rb +20 -0
  34. data/lib/dm-core/property/class.rb +17 -0
  35. data/lib/dm-core/property/date.rb +10 -0
  36. data/lib/dm-core/property/date_time.rb +10 -0
  37. data/lib/dm-core/property/decimal.rb +36 -0
  38. data/lib/dm-core/property/discriminator.rb +44 -0
  39. data/lib/dm-core/property/float.rb +16 -0
  40. data/lib/dm-core/property/integer.rb +22 -0
  41. data/lib/dm-core/property/invalid_value_error.rb +22 -0
  42. data/lib/dm-core/property/lookup.rb +27 -0
  43. data/lib/dm-core/property/numeric.rb +38 -0
  44. data/lib/dm-core/property/object.rb +34 -0
  45. data/lib/dm-core/property/serial.rb +14 -0
  46. data/lib/dm-core/property/string.rb +38 -0
  47. data/lib/dm-core/property/text.rb +9 -0
  48. data/lib/dm-core/property/time.rb +10 -0
  49. data/lib/dm-core/property_set.rb +177 -0
  50. data/lib/dm-core/query.rb +1366 -0
  51. data/lib/dm-core/query/conditions/comparison.rb +911 -0
  52. data/lib/dm-core/query/conditions/operation.rb +721 -0
  53. data/lib/dm-core/query/direction.rb +36 -0
  54. data/lib/dm-core/query/operator.rb +35 -0
  55. data/lib/dm-core/query/path.rb +114 -0
  56. data/lib/dm-core/query/sort.rb +39 -0
  57. data/lib/dm-core/relationship_set.rb +72 -0
  58. data/lib/dm-core/repository.rb +226 -0
  59. data/lib/dm-core/resource.rb +1214 -0
  60. data/lib/dm-core/resource/persistence_state.rb +75 -0
  61. data/lib/dm-core/resource/persistence_state/clean.rb +40 -0
  62. data/lib/dm-core/resource/persistence_state/deleted.rb +30 -0
  63. data/lib/dm-core/resource/persistence_state/dirty.rb +96 -0
  64. data/lib/dm-core/resource/persistence_state/immutable.rb +34 -0
  65. data/lib/dm-core/resource/persistence_state/persisted.rb +29 -0
  66. data/lib/dm-core/resource/persistence_state/transient.rb +80 -0
  67. data/lib/dm-core/spec/lib/adapter_helpers.rb +64 -0
  68. data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
  69. data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
  70. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  71. data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
  72. data/lib/dm-core/spec/setup.rb +174 -0
  73. data/lib/dm-core/spec/shared/adapter_spec.rb +341 -0
  74. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  75. data/lib/dm-core/spec/shared/resource_spec.rb +1232 -0
  76. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  77. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +176 -0
  78. data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
  79. data/lib/dm-core/support/assertions.rb +8 -0
  80. data/lib/dm-core/support/chainable.rb +18 -0
  81. data/lib/dm-core/support/deprecate.rb +12 -0
  82. data/lib/dm-core/support/descendant_set.rb +89 -0
  83. data/lib/dm-core/support/equalizer.rb +48 -0
  84. data/lib/dm-core/support/ext/array.rb +22 -0
  85. data/lib/dm-core/support/ext/blank.rb +25 -0
  86. data/lib/dm-core/support/ext/hash.rb +67 -0
  87. data/lib/dm-core/support/ext/module.rb +47 -0
  88. data/lib/dm-core/support/ext/object.rb +57 -0
  89. data/lib/dm-core/support/ext/string.rb +24 -0
  90. data/lib/dm-core/support/ext/try_dup.rb +12 -0
  91. data/lib/dm-core/support/hook.rb +405 -0
  92. data/lib/dm-core/support/inflections.rb +60 -0
  93. data/lib/dm-core/support/inflector/inflections.rb +211 -0
  94. data/lib/dm-core/support/inflector/methods.rb +151 -0
  95. data/lib/dm-core/support/lazy_array.rb +451 -0
  96. data/lib/dm-core/support/local_object_space.rb +13 -0
  97. data/lib/dm-core/support/logger.rb +201 -0
  98. data/lib/dm-core/support/mash.rb +176 -0
  99. data/lib/dm-core/support/naming_conventions.rb +90 -0
  100. data/lib/dm-core/support/ordered_set.rb +380 -0
  101. data/lib/dm-core/support/subject.rb +33 -0
  102. data/lib/dm-core/support/subject_set.rb +250 -0
  103. data/lib/dm-core/version.rb +3 -0
  104. data/script/performance.rb +275 -0
  105. data/script/profile.rb +218 -0
  106. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  107. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +68 -0
  108. data/spec/public/associations/many_to_many_spec.rb +197 -0
  109. data/spec/public/associations/many_to_one_spec.rb +83 -0
  110. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  111. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  112. data/spec/public/associations/one_to_many_spec.rb +81 -0
  113. data/spec/public/associations/one_to_one_spec.rb +176 -0
  114. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  115. data/spec/public/collection_spec.rb +69 -0
  116. data/spec/public/finalize_spec.rb +76 -0
  117. data/spec/public/model/hook_spec.rb +246 -0
  118. data/spec/public/model/property_spec.rb +88 -0
  119. data/spec/public/model/relationship_spec.rb +1040 -0
  120. data/spec/public/model_spec.rb +462 -0
  121. data/spec/public/property/binary_spec.rb +41 -0
  122. data/spec/public/property/boolean_spec.rb +22 -0
  123. data/spec/public/property/class_spec.rb +28 -0
  124. data/spec/public/property/date_spec.rb +22 -0
  125. data/spec/public/property/date_time_spec.rb +22 -0
  126. data/spec/public/property/decimal_spec.rb +23 -0
  127. data/spec/public/property/discriminator_spec.rb +135 -0
  128. data/spec/public/property/float_spec.rb +22 -0
  129. data/spec/public/property/integer_spec.rb +22 -0
  130. data/spec/public/property/object_spec.rb +107 -0
  131. data/spec/public/property/serial_spec.rb +22 -0
  132. data/spec/public/property/string_spec.rb +22 -0
  133. data/spec/public/property/text_spec.rb +63 -0
  134. data/spec/public/property/time_spec.rb +22 -0
  135. data/spec/public/property_spec.rb +341 -0
  136. data/spec/public/resource_spec.rb +288 -0
  137. data/spec/public/sel_spec.rb +53 -0
  138. data/spec/public/setup_spec.rb +145 -0
  139. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  140. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  141. data/spec/public/shared/collection_shared_spec.rb +1667 -0
  142. data/spec/public/shared/finder_shared_spec.rb +1629 -0
  143. data/spec/rcov.opts +6 -0
  144. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  145. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
  146. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  147. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  148. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  149. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  150. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  151. data/spec/semipublic/associations_spec.rb +177 -0
  152. data/spec/semipublic/collection_spec.rb +110 -0
  153. data/spec/semipublic/model_spec.rb +96 -0
  154. data/spec/semipublic/property/binary_spec.rb +13 -0
  155. data/spec/semipublic/property/boolean_spec.rb +47 -0
  156. data/spec/semipublic/property/class_spec.rb +33 -0
  157. data/spec/semipublic/property/date_spec.rb +43 -0
  158. data/spec/semipublic/property/date_time_spec.rb +46 -0
  159. data/spec/semipublic/property/decimal_spec.rb +83 -0
  160. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  161. data/spec/semipublic/property/float_spec.rb +82 -0
  162. data/spec/semipublic/property/integer_spec.rb +82 -0
  163. data/spec/semipublic/property/lookup_spec.rb +29 -0
  164. data/spec/semipublic/property/serial_spec.rb +13 -0
  165. data/spec/semipublic/property/string_spec.rb +13 -0
  166. data/spec/semipublic/property/text_spec.rb +31 -0
  167. data/spec/semipublic/property/time_spec.rb +50 -0
  168. data/spec/semipublic/property_spec.rb +114 -0
  169. data/spec/semipublic/query/conditions/comparison_spec.rb +1501 -0
  170. data/spec/semipublic/query/conditions/operation_spec.rb +1294 -0
  171. data/spec/semipublic/query/path_spec.rb +471 -0
  172. data/spec/semipublic/query_spec.rb +3682 -0
  173. data/spec/semipublic/resource/state/clean_spec.rb +88 -0
  174. data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
  175. data/spec/semipublic/resource/state/dirty_spec.rb +162 -0
  176. data/spec/semipublic/resource/state/immutable_spec.rb +105 -0
  177. data/spec/semipublic/resource/state/transient_spec.rb +162 -0
  178. data/spec/semipublic/resource/state_spec.rb +230 -0
  179. data/spec/semipublic/resource_spec.rb +23 -0
  180. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  181. data/spec/semipublic/shared/resource_shared_spec.rb +199 -0
  182. data/spec/semipublic/shared/resource_state_shared_spec.rb +79 -0
  183. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  184. data/spec/spec.opts +5 -0
  185. data/spec/spec_helper.rb +38 -0
  186. data/spec/support/core_ext/hash.rb +10 -0
  187. data/spec/support/core_ext/inheritable_attributes.rb +46 -0
  188. data/spec/support/properties/huge_integer.rb +17 -0
  189. data/spec/unit/array_spec.rb +23 -0
  190. data/spec/unit/blank_spec.rb +73 -0
  191. data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
  192. data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
  193. data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
  194. data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
  195. data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
  196. data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
  197. data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
  198. data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
  199. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
  200. data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
  201. data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
  202. data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
  203. data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
  204. data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
  205. data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
  206. data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
  207. data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
  208. data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
  209. data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
  210. data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
  211. data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
  212. data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
  213. data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
  214. data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
  215. data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
  216. data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
  217. data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
  218. data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
  219. data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
  220. data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
  221. data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
  222. data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
  223. data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
  224. data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
  225. data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
  226. data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
  227. data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
  228. data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
  229. data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
  230. data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
  231. data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
  232. data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
  233. data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
  234. data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
  235. data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
  236. data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
  237. data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
  238. data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
  239. data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
  240. data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
  241. data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
  242. data/spec/unit/hash_spec.rb +28 -0
  243. data/spec/unit/hook_spec.rb +1235 -0
  244. data/spec/unit/inflections_spec.rb +16 -0
  245. data/spec/unit/lazy_array_spec.rb +1949 -0
  246. data/spec/unit/mash_spec.rb +312 -0
  247. data/spec/unit/module_spec.rb +71 -0
  248. data/spec/unit/object_spec.rb +38 -0
  249. data/spec/unit/try_dup_spec.rb +46 -0
  250. data/tasks/ci.rake +1 -0
  251. data/tasks/spec.rake +38 -0
  252. data/tasks/yard.rake +9 -0
  253. data/tasks/yardstick.rake +19 -0
  254. metadata +365 -0
@@ -0,0 +1,75 @@
1
+ module DataMapper
2
+ module Resource
3
+
4
+ # the state of the resource (abstract)
5
+ class PersistenceState
6
+ extend Equalizer
7
+
8
+ equalize :resource
9
+
10
+ attr_reader :resource
11
+
12
+ def initialize(resource)
13
+ @resource = resource
14
+ @model = resource.model
15
+ end
16
+
17
+ def get(subject, *args)
18
+ subject.get(resource, *args)
19
+ end
20
+
21
+ def set(subject, value)
22
+ subject.set(resource, value)
23
+ self
24
+ end
25
+
26
+ def delete
27
+ raise NotImplementedError, "#{self.class}#delete should be implemented"
28
+ end
29
+
30
+ def commit
31
+ raise NotImplementedError, "#{self.class}#commit should be implemented"
32
+ end
33
+
34
+ def rollback
35
+ raise NotImplementedError, "#{self.class}#rollback should be implemented"
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :model
41
+
42
+ def properties
43
+ @properties ||= model.properties(repository.name)
44
+ end
45
+
46
+ def relationships
47
+ @relationships ||= model.relationships(repository.name)
48
+ end
49
+
50
+ def identity_map
51
+ @identity_map ||= repository.identity_map(model)
52
+ end
53
+
54
+ def remove_from_identity_map
55
+ identity_map.delete(resource.key)
56
+ end
57
+
58
+ def add_to_identity_map
59
+ identity_map[resource.key] = resource
60
+ end
61
+
62
+ def set_child_keys
63
+ relationships.each do |relationship|
64
+ set_child_key(relationship)
65
+ end
66
+ end
67
+
68
+ def set_child_key(relationship)
69
+ return unless relationship.loaded?(resource) && relationship.respond_to?(:resource_for)
70
+ set(relationship, get(relationship))
71
+ end
72
+
73
+ end # class PersistenceState
74
+ end # module Resource
75
+ end # module DataMapper
@@ -0,0 +1,40 @@
1
+ module DataMapper
2
+ module Resource
3
+ class PersistenceState
4
+
5
+ # a persisted/unmodified resource
6
+ class Clean < Persisted
7
+ def set(subject, value)
8
+ if not_modified?(subject, value)
9
+ self
10
+ else
11
+ # assign to persistence_state so that if Dirty#set calls
12
+ # a Relationship#set, which modifies a Property, the same
13
+ # Dirty state instance will be reused.
14
+ state = resource.persistence_state = Dirty.new(resource)
15
+ state.set(subject, value)
16
+ end
17
+ end
18
+
19
+ def delete
20
+ Deleted.new(resource)
21
+ end
22
+
23
+ def commit
24
+ self
25
+ end
26
+
27
+ def rollback
28
+ self
29
+ end
30
+
31
+ private
32
+
33
+ def not_modified?(subject, value)
34
+ subject.loaded?(resource) && subject.get!(resource).eql?(value)
35
+ end
36
+
37
+ end # class Clean
38
+ end # class PersistenceState
39
+ end # module Resource
40
+ end # module DataMapper
@@ -0,0 +1,30 @@
1
+ module DataMapper
2
+ module Resource
3
+ class PersistenceState
4
+
5
+ # a persisted/deleted resource
6
+ class Deleted < Persisted
7
+ def set(subject, value)
8
+ raise ImmutableDeletedError, 'Deleted resource cannot be modified'
9
+ end
10
+
11
+ def delete
12
+ self
13
+ end
14
+
15
+ def commit
16
+ delete_resource
17
+ remove_from_identity_map
18
+ Immutable.new(resource)
19
+ end
20
+
21
+ private
22
+
23
+ def delete_resource
24
+ repository.delete(collection_for_self)
25
+ end
26
+
27
+ end # class Deleted
28
+ end # class PersistenceState
29
+ end # module Resource
30
+ end # module DataMapper
@@ -0,0 +1,96 @@
1
+ module DataMapper
2
+ module Resource
3
+ class PersistenceState
4
+
5
+ # a persisted/dirty resource
6
+ class Dirty < Persisted
7
+ def set(subject, value)
8
+ track(subject, value)
9
+ super
10
+ original_attributes.empty? ? Clean.new(resource) : self
11
+ end
12
+
13
+ def delete
14
+ reset_resource
15
+ Deleted.new(resource)
16
+ end
17
+
18
+ def commit
19
+ remove_from_identity_map
20
+ set_child_keys
21
+ assert_valid_attributes
22
+ update_resource
23
+ reset_original_attributes
24
+ reset_resource_key
25
+ Clean.new(resource)
26
+ ensure
27
+ add_to_identity_map
28
+ end
29
+
30
+ def rollback
31
+ reset_resource
32
+ Clean.new(resource)
33
+ end
34
+
35
+ def original_attributes
36
+ @original_attributes ||= {}
37
+ end
38
+
39
+ private
40
+
41
+ def track(subject, value)
42
+ if original_attributes.key?(subject)
43
+ # stop tracking if the new value is the same as the original
44
+ if original_attributes[subject].eql?(value)
45
+ original_attributes.delete(subject)
46
+ end
47
+ elsif !value.eql?(original = get(subject))
48
+ # track the original value
49
+ original_attributes[subject] = original
50
+ end
51
+ end
52
+
53
+ def update_resource
54
+ repository.update(resource.dirty_attributes, collection_for_self)
55
+ end
56
+
57
+ def reset_resource
58
+ reset_resource_properties
59
+ reset_resource_relationships
60
+ end
61
+
62
+ def reset_resource_key
63
+ resource.instance_eval { remove_instance_variable(:@_key) }
64
+ end
65
+
66
+ def reset_resource_properties
67
+ # delete every original attribute after resetting the resource
68
+ original_attributes.delete_if do |property, value|
69
+ property.set!(resource, value)
70
+ true
71
+ end
72
+ end
73
+
74
+ def reset_resource_relationships
75
+ relationships.each do |relationship|
76
+ next unless relationship.loaded?(resource)
77
+ # TODO: consider a method in Relationship that can reset the relationship
78
+ resource.instance_eval { remove_instance_variable(relationship.instance_variable_name) }
79
+ end
80
+ end
81
+
82
+ def reset_original_attributes
83
+ original_attributes.clear
84
+ end
85
+
86
+ def assert_valid_attributes
87
+ properties.each do |property|
88
+ value = property.get! resource
89
+ property.assert_valid_value(value)
90
+ end
91
+ end
92
+
93
+ end # class Dirty
94
+ end # class PersistenceState
95
+ end # module Resource
96
+ end # module DataMapper
@@ -0,0 +1,34 @@
1
+ module DataMapper
2
+ module Resource
3
+ class PersistenceState
4
+
5
+ # a not-persisted/unmodifiable resource
6
+ class Immutable < PersistenceState
7
+ def get(subject, *args)
8
+ unless subject.loaded?(resource) || subject.kind_of?(Associations::Relationship)
9
+ raise ImmutableError, 'Immutable resource cannot be lazy loaded'
10
+ end
11
+
12
+ super
13
+ end
14
+
15
+ def set(subject, value)
16
+ raise ImmutableError, 'Immutable resource cannot be modified'
17
+ end
18
+
19
+ def delete
20
+ raise ImmutableError, 'Immutable resource cannot be deleted'
21
+ end
22
+
23
+ def commit
24
+ self
25
+ end
26
+
27
+ def rollback
28
+ self
29
+ end
30
+
31
+ end # class Immutable
32
+ end # class PersistenceState
33
+ end # module Resource
34
+ end # module DataMapper
@@ -0,0 +1,29 @@
1
+ module DataMapper
2
+ module Resource
3
+ class PersistenceState
4
+
5
+ # a persisted resource (abstract)
6
+ class Persisted < PersistenceState
7
+ def get(subject, *args)
8
+ lazy_load(subject)
9
+ super
10
+ end
11
+
12
+ private
13
+
14
+ def repository
15
+ @repository ||= resource.instance_variable_get(:@_repository)
16
+ end
17
+
18
+ def collection_for_self
19
+ @collection_for_self ||= resource.collection_for_self
20
+ end
21
+
22
+ def lazy_load(subject)
23
+ subject.lazy_load(resource)
24
+ end
25
+
26
+ end # class Persisted
27
+ end # class PersistenceState
28
+ end # module Resource
29
+ end # module DataMapper
@@ -0,0 +1,80 @@
1
+ module DataMapper
2
+ module Resource
3
+ class PersistenceState
4
+
5
+ # a not-persisted/modifiable resource
6
+ class Transient < PersistenceState
7
+ def get(subject, *args)
8
+ set_default_value(subject)
9
+ super
10
+ end
11
+
12
+ def set(subject, value)
13
+ track(subject)
14
+ super
15
+ end
16
+
17
+ def delete
18
+ self
19
+ end
20
+
21
+ def commit
22
+ set_child_keys
23
+ set_default_values
24
+ assert_valid_attributes
25
+ create_resource
26
+ set_repository
27
+ add_to_identity_map
28
+ Clean.new(resource)
29
+ end
30
+
31
+ def rollback
32
+ self
33
+ end
34
+
35
+ def original_attributes
36
+ @original_attributes ||= {}
37
+ end
38
+
39
+ private
40
+
41
+ def repository
42
+ @repository ||= model.repository
43
+ end
44
+
45
+ def set_default_values
46
+ (properties | relationships).each do |subject|
47
+ set_default_value(subject)
48
+ end
49
+ end
50
+
51
+ def set_default_value(subject)
52
+ return if subject.loaded?(resource) || !subject.default?
53
+ set(subject, subject.default_for(resource))
54
+ end
55
+
56
+ def track(subject)
57
+ original_attributes[subject] = nil
58
+ end
59
+
60
+ def create_resource
61
+ repository.create([ resource ])
62
+ end
63
+
64
+ def set_repository
65
+ resource.instance_variable_set(:@_repository, repository)
66
+ end
67
+
68
+ def assert_valid_attributes
69
+ properties.each do |property|
70
+ value = get(property)
71
+ unless property.serial? && value.nil?
72
+ property.assert_valid_value(value)
73
+ end
74
+ end
75
+ end
76
+
77
+ end # class Transient
78
+ end # class PersistenceState
79
+ end # module Resource
80
+ end # module DataMapper
@@ -0,0 +1,64 @@
1
+ module DataMapper
2
+ module Spec
3
+ module Adapters
4
+
5
+ module Helpers
6
+
7
+ def supported_by(*adapters, &block)
8
+ adapters = adapters.map { |adapter| adapter.to_sym }
9
+ adapter = DataMapper::Spec.adapter_name.to_sym
10
+ if adapters.include?(:all) || adapters.include?(adapter)
11
+ describe_adapter(:default, &block)
12
+ end
13
+ end
14
+
15
+ def with_alternate_adapter(&block)
16
+ describe_adapter(:alternate, &block)
17
+ end
18
+
19
+ def describe_adapter(kind, &block)
20
+ describe("with #{kind} adapter") do
21
+
22
+ before :all do
23
+ # store these in instance vars for the shared adapter specs
24
+ @adapter = DataMapper::Spec.adapter(kind)
25
+ @repository = DataMapper.repository(@adapter.name)
26
+
27
+ @repository.scope { DataMapper.finalize }
28
+
29
+ # create all tables and constraints before each spec
30
+ DataMapper::Model.descendants.each do |model|
31
+ next unless model.respond_to?(:auto_migrate!)
32
+ begin
33
+ model.auto_migrate!(@repository.name)
34
+ rescue IncompleteModelError
35
+ # skip incomplete models
36
+ end
37
+ end
38
+ end
39
+
40
+ after :all do
41
+ # remove all tables and constraints after each spec
42
+ DataMapper::Model.descendants.each do |model|
43
+ next unless model.respond_to?(:auto_migrate_down!)
44
+ begin
45
+ model.auto_migrate_down!(@repository.name)
46
+ rescue IncompleteModelError
47
+ # skip incomplete models
48
+ end
49
+ end
50
+ # TODO consider proper automigrate functionality
51
+ if @adapter.respond_to?(:reset)
52
+ @adapter.reset
53
+ end
54
+ end
55
+
56
+ instance_eval(&block)
57
+ end
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
64
+ end