sbf-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 (259) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +29 -0
  3. data/.document +5 -0
  4. data/.gitignore +44 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +468 -0
  7. data/.travis.yml +57 -0
  8. data/.yardopts +1 -0
  9. data/Gemfile +70 -0
  10. data/LICENSE +20 -0
  11. data/README.md +269 -0
  12. data/Rakefile +4 -0
  13. data/dm-core.gemspec +21 -0
  14. data/lib/dm-core/adapters/abstract_adapter.rb +233 -0
  15. data/lib/dm-core/adapters/in_memory_adapter.rb +110 -0
  16. data/lib/dm-core/adapters.rb +249 -0
  17. data/lib/dm-core/associations/many_to_many.rb +477 -0
  18. data/lib/dm-core/associations/many_to_one.rb +282 -0
  19. data/lib/dm-core/associations/one_to_many.rb +332 -0
  20. data/lib/dm-core/associations/one_to_one.rb +84 -0
  21. data/lib/dm-core/associations/relationship.rb +650 -0
  22. data/lib/dm-core/backwards.rb +11 -0
  23. data/lib/dm-core/collection.rb +1486 -0
  24. data/lib/dm-core/core_ext/kernel.rb +21 -0
  25. data/lib/dm-core/core_ext/pathname.rb +4 -0
  26. data/lib/dm-core/core_ext/symbol.rb +10 -0
  27. data/lib/dm-core/identity_map.rb +6 -0
  28. data/lib/dm-core/model/hook.rb +99 -0
  29. data/lib/dm-core/model/is.rb +30 -0
  30. data/lib/dm-core/model/property.rb +244 -0
  31. data/lib/dm-core/model/relationship.rb +366 -0
  32. data/lib/dm-core/model/scope.rb +87 -0
  33. data/lib/dm-core/model.rb +876 -0
  34. data/lib/dm-core/property/binary.rb +19 -0
  35. data/lib/dm-core/property/boolean.rb +35 -0
  36. data/lib/dm-core/property/class.rb +23 -0
  37. data/lib/dm-core/property/date.rb +45 -0
  38. data/lib/dm-core/property/date_time.rb +44 -0
  39. data/lib/dm-core/property/decimal.rb +47 -0
  40. data/lib/dm-core/property/discriminator.rb +40 -0
  41. data/lib/dm-core/property/float.rb +27 -0
  42. data/lib/dm-core/property/integer.rb +32 -0
  43. data/lib/dm-core/property/invalid_value_error.rb +17 -0
  44. data/lib/dm-core/property/lookup.rb +26 -0
  45. data/lib/dm-core/property/numeric.rb +35 -0
  46. data/lib/dm-core/property/object.rb +33 -0
  47. data/lib/dm-core/property/serial.rb +13 -0
  48. data/lib/dm-core/property/string.rb +47 -0
  49. data/lib/dm-core/property/text.rb +12 -0
  50. data/lib/dm-core/property/time.rb +46 -0
  51. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  52. data/lib/dm-core/property/typecast/time.rb +33 -0
  53. data/lib/dm-core/property.rb +856 -0
  54. data/lib/dm-core/property_set.rb +177 -0
  55. data/lib/dm-core/query/conditions/comparison.rb +886 -0
  56. data/lib/dm-core/query/conditions/operation.rb +710 -0
  57. data/lib/dm-core/query/direction.rb +33 -0
  58. data/lib/dm-core/query/operator.rb +34 -0
  59. data/lib/dm-core/query/path.rb +113 -0
  60. data/lib/dm-core/query/sort.rb +38 -0
  61. data/lib/dm-core/query.rb +1352 -0
  62. data/lib/dm-core/relationship_set.rb +69 -0
  63. data/lib/dm-core/repository.rb +226 -0
  64. data/lib/dm-core/resource/persistence_state/clean.rb +36 -0
  65. data/lib/dm-core/resource/persistence_state/deleted.rb +26 -0
  66. data/lib/dm-core/resource/persistence_state/dirty.rb +91 -0
  67. data/lib/dm-core/resource/persistence_state/immutable.rb +32 -0
  68. data/lib/dm-core/resource/persistence_state/persisted.rb +25 -0
  69. data/lib/dm-core/resource/persistence_state/transient.rb +87 -0
  70. data/lib/dm-core/resource/persistence_state.rb +70 -0
  71. data/lib/dm-core/resource.rb +1220 -0
  72. data/lib/dm-core/spec/lib/adapter_helpers.rb +63 -0
  73. data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
  74. data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
  75. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  76. data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
  77. data/lib/dm-core/spec/setup.rb +164 -0
  78. data/lib/dm-core/spec/shared/adapter_spec.rb +366 -0
  79. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  80. data/lib/dm-core/spec/shared/resource_spec.rb +1221 -0
  81. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  82. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +184 -0
  83. data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
  84. data/lib/dm-core/support/assertions.rb +8 -0
  85. data/lib/dm-core/support/chainable.rb +18 -0
  86. data/lib/dm-core/support/deprecate.rb +12 -0
  87. data/lib/dm-core/support/descendant_set.rb +89 -0
  88. data/lib/dm-core/support/equalizer.rb +48 -0
  89. data/lib/dm-core/support/ext/array.rb +22 -0
  90. data/lib/dm-core/support/ext/blank.rb +25 -0
  91. data/lib/dm-core/support/ext/hash.rb +67 -0
  92. data/lib/dm-core/support/ext/module.rb +47 -0
  93. data/lib/dm-core/support/ext/object.rb +57 -0
  94. data/lib/dm-core/support/ext/string.rb +24 -0
  95. data/lib/dm-core/support/ext/try_dup.rb +12 -0
  96. data/lib/dm-core/support/hook.rb +388 -0
  97. data/lib/dm-core/support/inflections.rb +60 -0
  98. data/lib/dm-core/support/inflector/inflections.rb +211 -0
  99. data/lib/dm-core/support/inflector/methods.rb +151 -0
  100. data/lib/dm-core/support/lazy_array.rb +451 -0
  101. data/lib/dm-core/support/local_object_space.rb +13 -0
  102. data/lib/dm-core/support/logger.rb +201 -0
  103. data/lib/dm-core/support/mash.rb +176 -0
  104. data/lib/dm-core/support/naming_conventions.rb +109 -0
  105. data/lib/dm-core/support/ordered_set.rb +381 -0
  106. data/lib/dm-core/support/subject.rb +33 -0
  107. data/lib/dm-core/support/subject_set.rb +251 -0
  108. data/lib/dm-core/version.rb +3 -0
  109. data/lib/dm-core.rb +274 -0
  110. data/script/performance.rb +275 -0
  111. data/script/profile.rb +218 -0
  112. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  113. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +69 -0
  114. data/spec/public/associations/many_to_many_spec.rb +197 -0
  115. data/spec/public/associations/many_to_one_spec.rb +83 -0
  116. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  117. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  118. data/spec/public/associations/one_to_many_spec.rb +81 -0
  119. data/spec/public/associations/one_to_one_spec.rb +176 -0
  120. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  121. data/spec/public/collection_spec.rb +69 -0
  122. data/spec/public/finalize_spec.rb +77 -0
  123. data/spec/public/model/hook_spec.rb +245 -0
  124. data/spec/public/model/property_spec.rb +91 -0
  125. data/spec/public/model/relationship_spec.rb +1040 -0
  126. data/spec/public/model_spec.rb +456 -0
  127. data/spec/public/property/binary_spec.rb +43 -0
  128. data/spec/public/property/boolean_spec.rb +21 -0
  129. data/spec/public/property/class_spec.rb +27 -0
  130. data/spec/public/property/date_spec.rb +21 -0
  131. data/spec/public/property/date_time_spec.rb +21 -0
  132. data/spec/public/property/decimal_spec.rb +23 -0
  133. data/spec/public/property/discriminator_spec.rb +134 -0
  134. data/spec/public/property/float_spec.rb +22 -0
  135. data/spec/public/property/integer_spec.rb +22 -0
  136. data/spec/public/property/object_spec.rb +117 -0
  137. data/spec/public/property/serial_spec.rb +22 -0
  138. data/spec/public/property/string_spec.rb +21 -0
  139. data/spec/public/property/text_spec.rb +62 -0
  140. data/spec/public/property/time_spec.rb +21 -0
  141. data/spec/public/property_spec.rb +333 -0
  142. data/spec/public/resource/state_spec.rb +72 -0
  143. data/spec/public/resource_spec.rb +289 -0
  144. data/spec/public/sel_spec.rb +53 -0
  145. data/spec/public/setup_spec.rb +145 -0
  146. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  147. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  148. data/spec/public/shared/collection_shared_spec.rb +1637 -0
  149. data/spec/public/shared/finder_shared_spec.rb +1647 -0
  150. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  151. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
  152. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  153. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  154. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  155. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  156. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  157. data/spec/semipublic/associations_spec.rb +177 -0
  158. data/spec/semipublic/collection_spec.rb +110 -0
  159. data/spec/semipublic/model_spec.rb +96 -0
  160. data/spec/semipublic/property/binary_spec.rb +13 -0
  161. data/spec/semipublic/property/boolean_spec.rb +47 -0
  162. data/spec/semipublic/property/class_spec.rb +33 -0
  163. data/spec/semipublic/property/date_spec.rb +43 -0
  164. data/spec/semipublic/property/date_time_spec.rb +46 -0
  165. data/spec/semipublic/property/decimal_spec.rb +83 -0
  166. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  167. data/spec/semipublic/property/float_spec.rb +82 -0
  168. data/spec/semipublic/property/integer_spec.rb +82 -0
  169. data/spec/semipublic/property/lookup_spec.rb +29 -0
  170. data/spec/semipublic/property/serial_spec.rb +13 -0
  171. data/spec/semipublic/property/string_spec.rb +13 -0
  172. data/spec/semipublic/property/text_spec.rb +31 -0
  173. data/spec/semipublic/property/time_spec.rb +50 -0
  174. data/spec/semipublic/property_spec.rb +114 -0
  175. data/spec/semipublic/query/conditions/comparison_spec.rb +1502 -0
  176. data/spec/semipublic/query/conditions/operation_spec.rb +1296 -0
  177. data/spec/semipublic/query/path_spec.rb +471 -0
  178. data/spec/semipublic/query_spec.rb +3665 -0
  179. data/spec/semipublic/resource/state/clean_spec.rb +89 -0
  180. data/spec/semipublic/resource/state/deleted_spec.rb +79 -0
  181. data/spec/semipublic/resource/state/dirty_spec.rb +163 -0
  182. data/spec/semipublic/resource/state/immutable_spec.rb +107 -0
  183. data/spec/semipublic/resource/state/transient_spec.rb +163 -0
  184. data/spec/semipublic/resource/state_spec.rb +230 -0
  185. data/spec/semipublic/resource_spec.rb +23 -0
  186. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  187. data/spec/semipublic/shared/resource_shared_spec.rb +198 -0
  188. data/spec/semipublic/shared/resource_state_shared_spec.rb +91 -0
  189. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  190. data/spec/spec_helper.rb +34 -0
  191. data/spec/support/core_ext/hash.rb +10 -0
  192. data/spec/support/core_ext/inheritable_attributes.rb +46 -0
  193. data/spec/support/properties/huge_integer.rb +17 -0
  194. data/spec/unit/array_spec.rb +23 -0
  195. data/spec/unit/blank_spec.rb +73 -0
  196. data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
  197. data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
  198. data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
  199. data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
  200. data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
  201. data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
  202. data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
  203. data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
  204. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
  205. data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
  206. data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
  207. data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
  208. data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
  209. data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
  210. data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
  211. data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
  212. data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
  213. data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
  214. data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
  215. data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
  216. data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
  217. data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
  218. data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
  219. data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
  220. data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
  221. data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
  222. data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
  223. data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
  224. data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
  225. data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
  226. data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
  227. data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
  228. data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
  229. data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
  230. data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
  231. data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
  232. data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
  233. data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
  234. data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
  235. data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
  236. data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
  237. data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
  238. data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
  239. data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
  240. data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
  241. data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
  242. data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
  243. data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
  244. data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
  245. data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
  246. data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
  247. data/spec/unit/hash_spec.rb +27 -0
  248. data/spec/unit/hook_spec.rb +1216 -0
  249. data/spec/unit/inflections_spec.rb +14 -0
  250. data/spec/unit/lazy_array_spec.rb +1949 -0
  251. data/spec/unit/mash_spec.rb +289 -0
  252. data/spec/unit/module_spec.rb +70 -0
  253. data/spec/unit/object_spec.rb +38 -0
  254. data/spec/unit/try_dup_spec.rb +46 -0
  255. data/tasks/ci.rake +1 -0
  256. data/tasks/spec.rake +18 -0
  257. data/tasks/yard.rake +9 -0
  258. data/tasks/yardstick.rake +19 -0
  259. metadata +323 -0
@@ -0,0 +1,251 @@
1
+ module DataMapper
2
+
3
+ # An insertion ordered set of named objects
4
+ #
5
+ # {SubjectSet} uses {DataMapper::OrderedSet}
6
+ # under the hood to keep track of a set of
7
+ # entries. In DataMapper code, a subject
8
+ # can be either a {DataMapper::Property}, or
9
+ # a {DataMapper::Associations::Relationship}.
10
+ #
11
+ # All entries added to instances of this
12
+ # class must respond to the {#name} method
13
+ #
14
+ # The motivation behind this is that we
15
+ # use this class as a base to keep track
16
+ # properties and relationships.
17
+ # The following constraints apply for these
18
+ # types of objects: {Property} names must be
19
+ # unique within any model.
20
+ # {Associations::Relationship} names must be
21
+ # unique within any model
22
+ #
23
+ # When adding an entry with a name that
24
+ # already exists, the already existing
25
+ # entry will be replaced with the new
26
+ # entry with the same name. This is because
27
+ # we want to be able to update properties,
28
+ # and relationship during the course of
29
+ # initializing our application.
30
+ #
31
+ # This also happens to be consistent with
32
+ # the way ruby handles redefining methods,
33
+ # where the last definitions "wins".
34
+ #
35
+ # Furthermore, the builtin ruby {Set#<<} method
36
+ # also updates the old object if a new object
37
+ # gets added.
38
+ #
39
+ # @api private
40
+ class SubjectSet
41
+
42
+ # An {OrderedSet::Cache::API} implementation that establishes
43
+ # set semantics based on the name of its entries. The cache
44
+ # uses the entries' names as cache key and refuses to add
45
+ # entries that don't respond_to?(:name).
46
+ #
47
+ # @see OrderedSet::Cache::API
48
+ #
49
+ # @api private
50
+ class NameCache
51
+
52
+ include OrderedSet::Cache::API
53
+
54
+ # Tests if the given entry qualifies to be added to the cache
55
+ #
56
+ # @param [#name] entry
57
+ # the entry to be checked
58
+ #
59
+ # @return [Boolean]
60
+ # true if the entry respond_to?(:name)
61
+ #
62
+ # @api private
63
+ def valid?(entry)
64
+ entry.respond_to?(:name)
65
+ end
66
+
67
+ # Given an entry, return the key to be used in the cache
68
+ #
69
+ # @param [#name] entry
70
+ # the entry to get the key for
71
+ #
72
+ # @return [#to_s, nil]
73
+ # the entry's name or nil if the entry isn't #valid?
74
+ #
75
+ # @api private
76
+ def key_for(entry)
77
+ valid?(entry) ? entry.name : nil
78
+ end
79
+
80
+ end # class NameCache
81
+
82
+ include Enumerable
83
+
84
+ # The elements in the SubjectSet
85
+ #
86
+ # @return [OrderedSet]
87
+ #
88
+ # @api private
89
+ attr_reader :entries
90
+
91
+ # Initialize a SubjectSet
92
+ #
93
+ # @param [Enumerable<#name>] entries
94
+ # the entries to initialize this set with
95
+ #
96
+ # @api private
97
+ def initialize(entries = [])
98
+ @entries = OrderedSet.new(entries, NameCache)
99
+ end
100
+
101
+ # Initialize a copy of a SubjectSet
102
+ #
103
+ # @api private
104
+ def initialize_copy(*)
105
+ @entries = @entries.dup
106
+ end
107
+
108
+ # Make sure that entry is part of this SubjectSet
109
+ #
110
+ # If an entry with the same name already exists, it
111
+ # will be updated. If no such named entry exists, it
112
+ # will be added.
113
+ #
114
+ # @param [#name] entry
115
+ # the entry to be added
116
+ #
117
+ # @return [SubjectSet] self
118
+ #
119
+ # @api private
120
+ def <<(entry)
121
+ entries << entry
122
+ self
123
+ end
124
+
125
+ # Delete an entry from this SubjectSet
126
+ #
127
+ # @param [#name] entry
128
+ # the entry to delete
129
+ #
130
+ # @return [#name, nil]
131
+ # the deleted entry or nil
132
+ #
133
+ # @api private
134
+ def delete(entry)
135
+ entries.delete(entry)
136
+ end
137
+
138
+ # Removes all entries and returns self
139
+ #
140
+ # @return [SubjectSet] self
141
+ #
142
+ # @api private
143
+ def clear
144
+ entries.clear
145
+ self
146
+ end
147
+
148
+ # Test if the given entry is included in this SubjectSet
149
+ #
150
+ # @param [#name] entry
151
+ # the entry to test for
152
+ #
153
+ # @return [Boolean]
154
+ # true if the entry is included in this SubjectSet
155
+ #
156
+ # @api private
157
+ def include?(entry)
158
+ entries.include?(entry)
159
+ end
160
+
161
+ # Tests wether the SubjectSet contains a entry named name
162
+ #
163
+ # @param [#to_s] name
164
+ # the entry name to test for
165
+ #
166
+ # @return [Boolean]
167
+ # true if the SubjectSet contains a entry named name
168
+ #
169
+ # @api private
170
+ def named?(name)
171
+ !self[name].nil?
172
+ end
173
+
174
+ # Check if there are any entries
175
+ #
176
+ # @return [Boolean]
177
+ # true if the set contains at least one entry
178
+ #
179
+ # @api private
180
+ def empty?
181
+ entries.empty?
182
+ end
183
+
184
+ # Lookup an entry in the SubjectSet based on a given name
185
+ #
186
+ # @param [#to_s] name
187
+ # the name of the entry
188
+ #
189
+ # @return [Object, nil]
190
+ # the entry having the given name, or nil if not found
191
+ #
192
+ # @api private
193
+ def [](name)
194
+ name = name.to_s
195
+ entries.detect { |entry| entry.name.to_s == name }
196
+ end
197
+
198
+ # Iterate over each entry in the set
199
+ #
200
+ # @yield [entry]
201
+ # each entry in the set
202
+ #
203
+ # @yieldparam [#name] entry
204
+ # an entry in the set
205
+ #
206
+ # @return [SubjectSet] self
207
+ #
208
+ # @api private
209
+ def each
210
+ return to_enum unless block_given?
211
+ entries.each { |entry| yield(entry) }
212
+ self
213
+ end
214
+
215
+ # All entries (or nil values) that have any of the given names
216
+ #
217
+ # @param [Enumerable<#to_s>] names
218
+ # the names of the desired entries
219
+ #
220
+ # @return [Array<#name, nil>]
221
+ # an array containing entries whose names match any of the given
222
+ # names, or nil values for those names with no matching entries
223
+ # in the set
224
+ #
225
+ # @api private
226
+ def values_at(*names)
227
+ names.map { |name| self[name] }
228
+ end
229
+
230
+ # Get the number of elements inside this SubjectSet
231
+ #
232
+ # @return [Integer]
233
+ # the number of elements
234
+ #
235
+ # @api private
236
+ def size
237
+ entries.size
238
+ end
239
+
240
+ # Convert the SubjectSet into an Array
241
+ #
242
+ # @return [Array]
243
+ # an array containing all the SubjectSet's entries
244
+ #
245
+ # @api private
246
+ def to_ary
247
+ to_a
248
+ end
249
+
250
+ end # class SubjectSet
251
+ end # module DataMapper
@@ -0,0 +1,3 @@
1
+ module DataMapper
2
+ VERSION = '1.3.0.beta'.freeze
3
+ end
data/lib/dm-core.rb ADDED
@@ -0,0 +1,274 @@
1
+ require 'addressable/uri'
2
+ require 'bigdecimal'
3
+ require 'bigdecimal/util'
4
+ require 'date'
5
+ require 'pathname'
6
+ require 'time'
7
+ require 'yaml'
8
+
9
+ module DataMapper
10
+ module Undefined; end
11
+ end
12
+
13
+ require 'dm-core/support/ext/blank'
14
+ require 'dm-core/support/ext/hash'
15
+ require 'dm-core/support/ext/object'
16
+ require 'dm-core/support/ext/string'
17
+
18
+ require 'dm-core/core_ext/pathname'
19
+ require 'dm-core/support/ext/module'
20
+ require 'dm-core/support/ext/array'
21
+ require 'dm-core/support/ext/try_dup'
22
+
23
+ require 'dm-core/support/mash'
24
+ require 'dm-core/support/inflector/inflections'
25
+ require 'dm-core/support/inflector/methods'
26
+ require 'dm-core/support/inflections'
27
+ require 'dm-core/support/chainable'
28
+ require 'dm-core/support/deprecate'
29
+ require 'dm-core/support/descendant_set'
30
+ require 'dm-core/support/equalizer'
31
+ require 'dm-core/support/assertions'
32
+ require 'dm-core/support/lazy_array'
33
+ require 'dm-core/support/local_object_space'
34
+ require 'dm-core/support/hook'
35
+ require 'dm-core/support/subject'
36
+ require 'dm-core/support/ordered_set'
37
+ require 'dm-core/support/subject_set'
38
+
39
+ require 'dm-core/query'
40
+ require 'dm-core/query/conditions/operation'
41
+ require 'dm-core/query/conditions/comparison'
42
+ require 'dm-core/query/operator'
43
+ require 'dm-core/query/direction'
44
+ require 'dm-core/query/path'
45
+ require 'dm-core/query/sort'
46
+
47
+ require 'dm-core/resource'
48
+ require 'dm-core/resource/persistence_state'
49
+ require 'dm-core/resource/persistence_state/transient'
50
+ require 'dm-core/resource/persistence_state/immutable'
51
+ require 'dm-core/resource/persistence_state/persisted'
52
+ require 'dm-core/resource/persistence_state/clean'
53
+ require 'dm-core/resource/persistence_state/deleted'
54
+ require 'dm-core/resource/persistence_state/dirty'
55
+
56
+ require 'dm-core/property/invalid_value_error'
57
+ require 'dm-core/property'
58
+ require 'dm-core/property/typecast/numeric'
59
+ require 'dm-core/property/typecast/time'
60
+ require 'dm-core/property/object'
61
+ require 'dm-core/property/string'
62
+ require 'dm-core/property/binary'
63
+ require 'dm-core/property/text'
64
+ require 'dm-core/property/numeric'
65
+ require 'dm-core/property/float'
66
+ require 'dm-core/property/decimal'
67
+ require 'dm-core/property/boolean'
68
+ require 'dm-core/property/integer'
69
+ require 'dm-core/property/serial'
70
+ require 'dm-core/property/date'
71
+ require 'dm-core/property/date_time'
72
+ require 'dm-core/property/time'
73
+ require 'dm-core/property/class'
74
+ require 'dm-core/property/discriminator'
75
+ require 'dm-core/property/lookup'
76
+ require 'dm-core/property_set'
77
+
78
+ require 'dm-core/model'
79
+ require 'dm-core/model/hook'
80
+ require 'dm-core/model/is'
81
+ require 'dm-core/model/scope'
82
+ require 'dm-core/model/relationship'
83
+ require 'dm-core/model/property'
84
+
85
+ require 'dm-core/collection'
86
+ require 'dm-core/relationship_set'
87
+ require 'dm-core/associations/relationship'
88
+ require 'dm-core/associations/one_to_many'
89
+ require 'dm-core/associations/one_to_one'
90
+ require 'dm-core/associations/many_to_one'
91
+ require 'dm-core/associations/many_to_many'
92
+
93
+ require 'dm-core/identity_map'
94
+ require 'dm-core/repository'
95
+ require 'dm-core/adapters'
96
+ require 'dm-core/adapters/abstract_adapter'
97
+
98
+ require 'dm-core/support/logger'
99
+ require 'dm-core/support/naming_conventions'
100
+ require 'dm-core/version'
101
+
102
+ require 'dm-core/core_ext/kernel' # TODO: do not load automatically
103
+ require 'dm-core/core_ext/symbol' # TODO: do not load automatically
104
+
105
+ require 'dm-core/backwards' # TODO: do not load automatically
106
+
107
+ # A logger should always be present. Lets be consistent with DO
108
+ DataMapper::Logger.new(StringIO.new, :fatal)
109
+
110
+ Infinity = 1.0 / 0 unless defined?(Infinity)
111
+
112
+ # == Setup and Configuration
113
+ # DataMapper uses URIs or a connection hash to connect to your data-store.
114
+ # URI connections takes the form of:
115
+ # DataMapper.setup(:default, 'protocol://username:password@127.0.0.1:port/path/to/repo')
116
+ #
117
+ # Breaking this down, the first argument is the name you wish to give this
118
+ # connection. If you do not specify one, it will be assigned :default. If you
119
+ # would like to connect to more than one data-store, simply issue this command
120
+ # again, but with a different name specified.
121
+ #
122
+ # In order to issue ORM commands without specifying the repository context, you
123
+ # must define the :default database. Otherwise, you'll need to wrap your ORM
124
+ # calls in <tt>repository(:name) { }</tt>.
125
+ #
126
+ # Second, the URI breaks down into the access protocol, the username, the
127
+ # server, the password, and whatever path information is needed to properly
128
+ # address the data-store on the server.
129
+ #
130
+ # Here's some examples
131
+ # DataMapper.setup(:default, 'sqlite3://path/to/your/project/db/development.db')
132
+ # DataMapper.setup(:default, 'mysql://127.0.0.1/dm_core_test')
133
+ # # no auth-info
134
+ # DataMapper.setup(:default, 'postgres://root:supahsekret@127.0.0.1/dm_core_test')
135
+ # # with auth-info
136
+ #
137
+ #
138
+ # Alternatively, you can supply a hash as the second parameter, which would
139
+ # take the form:
140
+ #
141
+ # DataMapper.setup(:default, {
142
+ # :adapter => 'adapter_name_here',
143
+ # :database => 'path/to/repo',
144
+ # :username => 'username',
145
+ # :password => 'password',
146
+ # :host => 'hostname'
147
+ # })
148
+ #
149
+ # === Logging
150
+ # To turn on error logging to STDOUT, issue:
151
+ #
152
+ # DataMapper::Logger.new($stdout, :debug)
153
+ #
154
+ # You can pass a file location ("/path/to/log/file.log") in place of $stdout.
155
+ # see DataMapper::Logger for more information.
156
+ #
157
+ module DataMapper
158
+ extend DataMapper::Assertions
159
+
160
+ class RepositoryNotSetupError < StandardError; end
161
+
162
+ class IncompleteModelError < StandardError; end
163
+
164
+ class PluginNotFoundError < StandardError; end
165
+
166
+ class UnknownRelationshipError < StandardError; end
167
+
168
+ class ObjectNotFoundError < RuntimeError; end
169
+
170
+ class PersistenceError < RuntimeError; end
171
+
172
+ class UpdateConflictError < PersistenceError; end
173
+
174
+ class SaveFailureError < PersistenceError
175
+ attr_reader :resource
176
+
177
+ def initialize(message, resource)
178
+ super(message)
179
+ @resource = resource
180
+ end
181
+ end
182
+
183
+ class ImmutableError < RuntimeError; end
184
+
185
+ class ImmutableDeletedError < ImmutableError; end
186
+
187
+ # Raised on attempt to operate on collection of child objects
188
+ # when parent object is not yet saved.
189
+ # For instance, if your article object is not saved,
190
+ # but you try to fetch or scope down comments (1:n case), or
191
+ # publications (n:m case), operation cannot be completed
192
+ # because parent object's keys are not yet persisted,
193
+ # and thus there is no FK value to use in the query.
194
+ class UnsavedParentError < PersistenceError; end
195
+
196
+ # @api private
197
+ def self.root
198
+ @root ||= Pathname(__FILE__).dirname.parent.expand_path.freeze
199
+ end
200
+
201
+ # Setups up a connection to a data-store
202
+ #
203
+ # @param [Symbol] name
204
+ # a name for the context, defaults to :default
205
+ # @param [Hash(Symbol => String), Addressable::URI, String] uri_or_options
206
+ # connection information
207
+ #
208
+ # @return [DataMapper::Adapters::AbstractAdapter]
209
+ # the resulting setup adapter
210
+ #
211
+ # @raise [ArgumentError] "+name+ must be a Symbol, but was..."
212
+ # indicates that an invalid argument was passed for name[Symbol]
213
+ # @raise [ArgumentError] "+uri_or_options+ must be a Hash, URI or String, but was..."
214
+ # indicates that connection information could not be gleaned from
215
+ # the given uri_or_options[Hash, Addressable::URI, String]
216
+ #
217
+ # @api public
218
+ def self.setup(*args)
219
+ adapter = args.first
220
+
221
+ adapter = Adapters.new(*args) unless adapter.is_a?(Adapters::AbstractAdapter)
222
+
223
+ Repository.adapters[adapter.name] = adapter
224
+ end
225
+
226
+ # Block Syntax
227
+ # Pushes the named repository onto the context-stack,
228
+ # yields a new session, and pops the context-stack.
229
+ #
230
+ # Non-Block Syntax
231
+ # Returns the current session, or if there is none,
232
+ # a new Session.
233
+ #
234
+ # @param [Symbol] args the name of a repository to act within or return, :default is default
235
+ #
236
+ # @yield [Proc] (optional) block to execute within the context of the named repository
237
+ #
238
+ # @api public
239
+ def self.repository(name = nil)
240
+ context = Repository.context
241
+
242
+ current_repository = if name
243
+ name = name.to_sym
244
+ context.detect { |repository| repository.name == name }
245
+ else
246
+ name = Repository.default_name
247
+ context.last
248
+ end
249
+
250
+ current_repository ||= Repository.new(name)
251
+
252
+ if block_given?
253
+ current_repository.scope { |*block_args| yield(*block_args) }
254
+ else
255
+ current_repository
256
+ end
257
+ end
258
+
259
+ # Perform necessary steps to finalize DataMapper for the current repository
260
+ #
261
+ # This method should be called after loading all models and plugins.
262
+ #
263
+ # It ensures foreign key properties and anonymous join models are created.
264
+ # These are otherwise lazily declared, which can lead to unexpected errors.
265
+ # It also performs basic validity checking of the DataMapper models.
266
+ #
267
+ # @return [self]
268
+ #
269
+ # @api public
270
+ def self.finalize
271
+ Model.descendants.each(&:finalize)
272
+ self
273
+ end
274
+ end