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,36 @@
1
+ # TODO: rename this DM::Symbol::Direction
2
+
3
+ # TODO: add a method to convert it into a DM::Query::Sort object, eg:
4
+ # operator.sort_for(model)
5
+
6
+ # TODO: rename #target to #property_name
7
+
8
+ # TODO: make sure Query converts this into a DM::Query::Sort object
9
+ # immediately and passes that down to the Adapter
10
+
11
+ # TODO: remove #get method
12
+
13
+ module DataMapper
14
+ class Query
15
+ class Direction < Operator
16
+
17
+ # @api private
18
+ def reverse!
19
+ @operator = @operator == :asc ? :desc : :asc
20
+ self
21
+ end
22
+
23
+ # @api private
24
+ def get(resource)
25
+ Sort.new(target.get(resource), @operator == :asc)
26
+ end
27
+
28
+ private
29
+
30
+ # @api private
31
+ def initialize(target, operator = :asc)
32
+ super
33
+ end
34
+ end # class Direction
35
+ end # class Query
36
+ end # module DataMapper
@@ -0,0 +1,35 @@
1
+ # TODO: rename this DM::Symbol::Operator
2
+
3
+ # TODO: add a method to convert it into a DM::Query::AbstractComparison object, eg:
4
+ # operator.comparison_for(repository, model)
5
+
6
+ # TODO: rename #target to #property_name
7
+
8
+ module DataMapper
9
+ class Query
10
+ class Operator
11
+ include DataMapper::Assertions
12
+ extend Equalizer
13
+
14
+ equalize :target, :operator
15
+
16
+ # @api private
17
+ attr_reader :target
18
+
19
+ # @api private
20
+ attr_reader :operator
21
+
22
+ # @api private
23
+ def inspect
24
+ "#<#{self.class.name} @target=#{target.inspect} @operator=#{operator.inspect}>"
25
+ end
26
+
27
+ private
28
+
29
+ # @api private
30
+ def initialize(target, operator)
31
+ @target, @operator = target, operator.to_sym
32
+ end
33
+ end # class Operator
34
+ end # class Query
35
+ end # module DataMapper
@@ -0,0 +1,114 @@
1
+ # TODO: instead of an Array of Path objects, create a Relationship
2
+ # on the fly using :through on the previous relationship, creating a
3
+ # chain. Query::Path could then be a thin wrapper that specifies extra
4
+ # conditions on the Relationships, like the target property o match
5
+ # on.
6
+
7
+ module DataMapper
8
+ class Query
9
+ class Path
10
+ # TODO: replace this with BasicObject
11
+ instance_methods.each do |method|
12
+ next if method =~ /\A__/ ||
13
+ %w[ send class dup object_id kind_of? instance_of? respond_to? respond_to_missing? equal? freeze frozen? should should_not instance_variables instance_variable_set instance_variable_get instance_variable_defined? remove_instance_variable extend hash inspect to_s copy_object initialize_dup ].include?(method.to_s)
14
+ undef_method method
15
+ end
16
+
17
+ include DataMapper::Assertions
18
+ extend Equalizer
19
+
20
+ equalize :relationships, :property
21
+
22
+ # @api semipublic
23
+ attr_reader :repository_name
24
+
25
+ # @api semipublic
26
+ attr_reader :relationships
27
+
28
+ # @api semipublic
29
+ attr_reader :model
30
+
31
+ # @api semipublic
32
+ attr_reader :property
33
+
34
+ (Conditions::Comparison.slugs | [ :not ]).each do |slug|
35
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
36
+ def #{slug} # def eql
37
+ #{"raise \"explicit use of '#{slug}' operator is deprecated (#{caller.first})\"" if slug == :eql || slug == :in} # raise "explicit use of 'eql' operator is deprecated (#{caller.first})"
38
+ Operator.new(self, #{slug.inspect}) # Operator.new(self, :eql)
39
+ end # end
40
+ RUBY
41
+ end
42
+
43
+ # @api public
44
+ def kind_of?(klass)
45
+ super || (defined?(@property) ? @property.kind_of?(klass) : false)
46
+ end
47
+
48
+ # @api public
49
+ def instance_of?(klass)
50
+ super || (defined?(@property) ? @property.instance_of?(klass) : false)
51
+ end
52
+
53
+ # Used for creating :order options. This technique may be deprecated,
54
+ # so marking as semipublic until the issue is resolved.
55
+ #
56
+ # @api semipublic
57
+ def asc
58
+ Operator.new(property, :asc)
59
+ end
60
+
61
+ # Used for creating :order options. This technique may be deprecated,
62
+ # so marking as semipublic until the issue is resolved.
63
+ #
64
+ # @api semipublic
65
+ def desc
66
+ Operator.new(property, :desc)
67
+ end
68
+
69
+ # @api semipublic
70
+ def respond_to?(method, include_private = false)
71
+ super ||
72
+ (defined?(@property) && @property.respond_to?(method, include_private)) ||
73
+ @model.relationships(@repository_name).named?(method) ||
74
+ @model.properties(@repository_name).named?(method)
75
+ end
76
+
77
+ private
78
+
79
+ # @api semipublic
80
+ def initialize(relationships, property_name = nil)
81
+ @relationships = relationships.to_ary.dup
82
+
83
+ last_relationship = @relationships.last
84
+ @repository_name = last_relationship.relative_target_repository_name
85
+ @model = last_relationship.target_model
86
+
87
+ if property_name
88
+ property_name = property_name.to_sym
89
+ @property = @model.properties(@repository_name)[property_name] ||
90
+ raise(ArgumentError, "Unknown property '#{property_name}' in #{@model}")
91
+ end
92
+ end
93
+
94
+ # @api semipublic
95
+ def method_missing(method, *args)
96
+ if @property
97
+ return @property.send(method, *args)
98
+ end
99
+
100
+ path_class = self.class
101
+
102
+ if relationship = @model.relationships(@repository_name)[method]
103
+ return path_class.new(@relationships.dup << relationship)
104
+ end
105
+
106
+ if @model.properties(@repository_name).named?(method)
107
+ return path_class.new(@relationships, method)
108
+ end
109
+
110
+ raise NoMethodError, "undefined property or relationship '#{method}' on #{@model}"
111
+ end
112
+ end # class Path
113
+ end # class Query
114
+ end # module DataMapper
@@ -0,0 +1,39 @@
1
+ # TODO: add #reverse and #reverse! methods
2
+
3
+ module DataMapper
4
+ class Query
5
+ class Sort
6
+ # @api semipublic
7
+ attr_reader :value
8
+
9
+ # @api semipublic
10
+ def direction
11
+ @ascending ? :ascending : :descending
12
+ end
13
+
14
+ # @api private
15
+ def <=>(other)
16
+ other_value = other.value
17
+ value_nil = @value.nil?
18
+ other_nil = other_value.nil?
19
+
20
+ cmp = case
21
+ when value_nil then other_nil ? 0 : 1
22
+ when other_nil then -1
23
+ else
24
+ @value <=> other_value
25
+ end
26
+
27
+ @ascending ? cmp : cmp * -1
28
+ end
29
+
30
+ private
31
+
32
+ # @api private
33
+ def initialize(value, ascending = true)
34
+ @value = value
35
+ @ascending = ascending
36
+ end
37
+ end # class Sort
38
+ end # class Query
39
+ end # module DataMapper
@@ -0,0 +1,72 @@
1
+ module DataMapper
2
+
3
+ # A {SubjectSet} that keeps track of relationships defined in a {Model}
4
+ #
5
+ class RelationshipSet < SubjectSet
6
+
7
+ # A list of all relationships in this set
8
+ #
9
+ # @deprecated use DataMapper::RelationshipSet#each or DataMapper::RelationshipSet#to_a instead
10
+ #
11
+ # @return [Array]
12
+ # a list of all relationships in the set
13
+ #
14
+ # @api semipublic
15
+ def values
16
+ warn "#{self.class}#values is deprecated. Use #{self.class}#each or #{self.class}#to_a instead: #{caller.first}"
17
+ to_a
18
+ end
19
+
20
+ # A list of all relationships in this set
21
+ #
22
+ # @deprecated use DataMapper::RelationshipSet#each instead
23
+ #
24
+ # @yield [DataMapper::Associations::Relationship]
25
+ # all relationships in the set
26
+ #
27
+ # @yieldparam [DataMapper::Associations::Relationship] relationship
28
+ # a relationship in the set
29
+ #
30
+ # @return [RelationshipSet] self
31
+ #
32
+ # @api semipublic
33
+ def each_value
34
+ warn "#{self.class}#each_value is deprecated. Use #{self.class}#each instead: #{caller.first}"
35
+ each { |relationship| yield(relationship) }
36
+ self
37
+ end
38
+
39
+ # Check wether this RelationshipSet includes an entry with the given name
40
+ #
41
+ # @deprecated use DataMapper::RelationshipSet#named? instead
42
+ #
43
+ # @param [#to_s] name
44
+ # the name of the entry to look for
45
+ #
46
+ # @return [Boolean]
47
+ # true if the set contains a relationship with the given name
48
+ #
49
+ # @api semipublic
50
+ def key?(name)
51
+ warn "#{self.class}#key? is deprecated. Use #{self.class}#named? instead: #{caller.first}"
52
+ named?(name)
53
+ end
54
+
55
+ # Check wether this RelationshipSet includes an entry with the given name
56
+ #
57
+ # @deprecated use DataMapper::RelationshipSet#named? instead
58
+ #
59
+ # @param [#to_s] name
60
+ # the name of the entry to look for
61
+ #
62
+ # @return [Boolean]
63
+ # true if the set contains a relationship with the given name
64
+ #
65
+ # @api semipublic
66
+ def has_key?(name)
67
+ warn "#{self.class}#has_key? is deprecated. Use #{self.class}#named? instead: #{caller.first}"
68
+ named?(name)
69
+ end
70
+
71
+ end # class RelationshipSet
72
+ end # module DataMapper
@@ -0,0 +1,226 @@
1
+ module DataMapper
2
+ class Repository
3
+ include DataMapper::Assertions
4
+ extend Equalizer
5
+
6
+ equalize :name
7
+
8
+ # Get the list of adapters registered for all Repositories,
9
+ # keyed by repository name.
10
+ #
11
+ # TODO: create example
12
+ #
13
+ # @return [Hash(Symbol => Adapters::AbstractAdapter)]
14
+ # the adapters registered for all Repositories
15
+ #
16
+ # @api private
17
+ def self.adapters
18
+ @adapters ||= {}
19
+ end
20
+
21
+ # Get the stack of current repository contexts
22
+ #
23
+ # TODO: create example
24
+ #
25
+ # @return [Array]
26
+ # List of Repository contexts for the current Thread
27
+ #
28
+ # @api private
29
+ def self.context
30
+ Thread.current[:dm_repository_contexts] ||= []
31
+ end
32
+
33
+ # Get the default name of this Repository
34
+ #
35
+ # TODO: create example
36
+ #
37
+ # @return [Symbol]
38
+ # the default name of this repository
39
+ #
40
+ # @api private
41
+ def self.default_name
42
+ :default
43
+ end
44
+
45
+ # @api semipublic
46
+ attr_reader :name
47
+
48
+ # @api semipublic
49
+ alias_method :to_sym, :name
50
+
51
+ # Get the adapter for this repository
52
+ #
53
+ # Lazy loads adapter setup from registered adapters
54
+ #
55
+ # TODO: create example
56
+ #
57
+ # @return [Adapters::AbstractAdapter]
58
+ # the adapter for this repository
59
+ #
60
+ # @raise [RepositoryNotSetupError]
61
+ # if there is no adapter registered for a repository named @name
62
+ #
63
+ # @api semipublic
64
+ def adapter
65
+ # Make adapter instantiation lazy so we can defer repository setup until it's actually
66
+ # needed. Do not remove this code.
67
+ @adapter ||=
68
+ begin
69
+ adapters = self.class.adapters
70
+
71
+ unless adapters.key?(@name)
72
+ raise RepositoryNotSetupError, "Adapter not set: #{@name}. Did you forget to setup?"
73
+ end
74
+
75
+ adapters[@name]
76
+ end
77
+ end
78
+
79
+ # Get the identity for a particular model within this repository.
80
+ #
81
+ # If one doesn't yet exist, create a new default in-memory IdentityMap
82
+ # for the requested model.
83
+ #
84
+ # TODO: create example
85
+ #
86
+ # @param [Model] model
87
+ # Model whose identity map should be returned
88
+ #
89
+ # @return [IdentityMap]
90
+ # The IdentityMap for model in this Repository
91
+ #
92
+ # @api private
93
+ def identity_map(model)
94
+ @identity_maps[model.base_model] ||= IdentityMap.new
95
+ end
96
+
97
+ # Executes a block in the scope of this Repository
98
+ #
99
+ # TODO: create example
100
+ #
101
+ # @yieldparam [Repository] repository
102
+ # yields self within the block
103
+ #
104
+ # @yield
105
+ # execute block in the scope of this Repository
106
+ #
107
+ # @api private
108
+ def scope
109
+ context = Repository.context
110
+
111
+ context << self
112
+
113
+ begin
114
+ yield self
115
+ ensure
116
+ context.pop
117
+ end
118
+ end
119
+
120
+ # Create a Query or subclass instance for this repository.
121
+ #
122
+ # @param [Model] model
123
+ # the Model to retrieve results from
124
+ # @param [Hash] options
125
+ # the conditions and scope
126
+ #
127
+ # @return [Query]
128
+ #
129
+ # @api semipublic
130
+ def new_query(model, options = {})
131
+ adapter.new_query(self, model, options)
132
+ end
133
+
134
+ # Create one or more resource instances in this repository.
135
+ #
136
+ # TODO: create example
137
+ #
138
+ # @param [Enumerable(Resource)] resources
139
+ # The list of resources (model instances) to create
140
+ #
141
+ # @return [Integer]
142
+ # The number of records that were actually saved into the data-store
143
+ #
144
+ # @api semipublic
145
+ def create(resources)
146
+ adapter.create(resources)
147
+ end
148
+
149
+ # Retrieve a collection of results of a query
150
+ #
151
+ # TODO: create example
152
+ #
153
+ # @param [Query] query
154
+ # composition of the query to perform
155
+ #
156
+ # @return [Array]
157
+ # result set of the query
158
+ #
159
+ # @api semipublic
160
+ def read(query)
161
+ return [] unless query.valid?
162
+ query.model.load(adapter.read(query), query)
163
+ end
164
+
165
+ # Update the attributes of one or more resource instances
166
+ #
167
+ # TODO: create example
168
+ #
169
+ # @param [Hash(Property => Object)] attributes
170
+ # hash of attribute values to set, keyed by Property
171
+ # @param [Collection] collection
172
+ # collection of records to be updated
173
+ #
174
+ # @return [Integer]
175
+ # the number of records updated
176
+ #
177
+ # @api semipublic
178
+ def update(attributes, collection)
179
+ return 0 unless collection.query.valid? && attributes.any?
180
+ adapter.update(attributes, collection)
181
+ end
182
+
183
+ # Delete one or more resource instances
184
+ #
185
+ # TODO: create example
186
+ #
187
+ # @param [Collection] collection
188
+ # collection of records to be deleted
189
+ #
190
+ # @return [Integer]
191
+ # the number of records deleted
192
+ #
193
+ # @api semipublic
194
+ def delete(collection)
195
+ return 0 unless collection.query.valid?
196
+ adapter.delete(collection)
197
+ end
198
+
199
+ # Return a human readable representation of the repository
200
+ #
201
+ # TODO: create example
202
+ #
203
+ # @return [String]
204
+ # human readable representation of the repository
205
+ #
206
+ # @api private
207
+ def inspect
208
+ "#<#{self.class.name} @name=#{@name}>"
209
+ end
210
+
211
+ private
212
+
213
+ # Initializes a new Repository
214
+ #
215
+ # TODO: create example
216
+ #
217
+ # @param [Symbol] name
218
+ # The name of the Repository
219
+ #
220
+ # @api semipublic
221
+ def initialize(name)
222
+ @name = name.to_sym
223
+ @identity_maps = {}
224
+ end
225
+ end # class Repository
226
+ end # module DataMapper