sbf-dm-core 1.3.0.beta

Sign up to get free protection for your applications and to get access to all the features.
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,1647 @@
1
+ shared_examples 'Finder Interface' do
2
+ before :all do
3
+ %w[ @article_model @article @other @articles ].each do |ivar|
4
+ raise "+#{ivar}+ should be defined in before block" unless instance_variable_defined?(ivar)
5
+ raise "+#{ivar}+ should not be nil in before block" unless instance_variable_get(ivar)
6
+ end
7
+ end
8
+
9
+ before :all do
10
+ @no_join = defined?(DataMapper::Adapters::InMemoryAdapter) && @adapter.kind_of?(DataMapper::Adapters::InMemoryAdapter) ||
11
+ defined?(DataMapper::Adapters::YamlAdapter) && @adapter.kind_of?(DataMapper::Adapters::YamlAdapter)
12
+
13
+ @do_adapter = defined?(DataMapper::Adapters::DataObjectsAdapter) && @adapter.kind_of?(DataMapper::Adapters::DataObjectsAdapter)
14
+
15
+ @many_to_many = @articles.kind_of?(DataMapper::Associations::ManyToMany::Collection)
16
+
17
+ @skip = @no_join && @many_to_many
18
+ end
19
+
20
+ before do
21
+ pending if @skip
22
+ end
23
+
24
+ it 'is Enumerable' do
25
+ expect(@articles).to be_kind_of(Enumerable)
26
+ end
27
+
28
+ [ :[], :slice ].each do |method|
29
+ it { expect(@articles).to respond_to(method) }
30
+
31
+ describe "##{method}" do
32
+ before :all do
33
+ 1.upto(10) { |number| @articles.create(:content => "Article #{number}") }
34
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
35
+ end
36
+
37
+ describe 'with a positive offset' do
38
+ before :all do
39
+ unless @skip
40
+ @return = @resource = @articles.send(method, 0)
41
+ end
42
+ end
43
+
44
+ it 'returns a Resource' do
45
+ expect(@return).to be_kind_of(DataMapper::Resource)
46
+ end
47
+
48
+ it 'returns expected Resource' do
49
+ expect(@return).to eq @copy.entries.send(method, 0)
50
+ end
51
+ end
52
+
53
+ describe 'with a positive offset and length' do
54
+ before :all do
55
+ @return = @resources = @articles.send(method, 5, 5)
56
+ end
57
+
58
+ it 'returns a Collection' do
59
+ expect(@return).to be_kind_of(DataMapper::Collection)
60
+ end
61
+
62
+ it 'returns the expected Resource' do
63
+ expect(@return).to eq @copy.entries.send(method, 5, 5)
64
+ end
65
+
66
+ it 'scopes the Collection' do
67
+ expect(@resources.reload).to eq @copy.entries.send(method, 5, 5)
68
+ end
69
+ end
70
+
71
+ describe 'with a positive range' do
72
+ before :all do
73
+ @return = @resources = @articles.send(method, 5..10)
74
+ end
75
+
76
+ it 'returns a Collection' do
77
+ expect(@return).to be_kind_of(DataMapper::Collection)
78
+ end
79
+
80
+ it 'returns the expected Resources' do
81
+ expect(@return).to eq @copy.entries.send(method, 5..10)
82
+ end
83
+
84
+ it 'scopes the Collection' do
85
+ expect(@resources.reload).to eq @copy.entries.send(method, 5..10)
86
+ end
87
+ end
88
+
89
+ describe 'with a negative offset' do
90
+ before :all do
91
+ unless @skip
92
+ @return = @resource = @articles.send(method, -1)
93
+ end
94
+ end
95
+
96
+ it 'returns a Resource' do
97
+ expect(@return).to be_kind_of(DataMapper::Resource)
98
+ end
99
+
100
+ it 'returns expected Resource' do
101
+ expect(@return).to eq @copy.entries.send(method, -1)
102
+ end
103
+ end
104
+
105
+ describe 'with a negative offset and length' do
106
+ before :all do
107
+ @return = @resources = @articles.send(method, -5, 5)
108
+ end
109
+
110
+ it 'returns a Collection' do
111
+ expect(@return).to be_kind_of(DataMapper::Collection)
112
+ end
113
+
114
+ it 'returns the expected Resources' do
115
+ expect(@return).to eq @copy.entries.send(method, -5, 5)
116
+ end
117
+
118
+ it 'scopes the Collection' do
119
+ expect(@resources.reload).to eq @copy.entries.send(method, -5, 5)
120
+ end
121
+ end
122
+
123
+ describe 'with a negative range' do
124
+ before :all do
125
+ @return = @resources = @articles.send(method, -5..-2)
126
+ end
127
+
128
+ it 'returns a Collection' do
129
+ expect(@return).to be_kind_of(DataMapper::Collection)
130
+ end
131
+
132
+ it 'returns the expected Resources' do
133
+ expect(@return.to_a).to eq @copy.entries.send(method, -5..-2)
134
+ end
135
+
136
+ it 'scopes the Collection' do
137
+ expect(@resources.reload).to eq @copy.entries.send(method, -5..-2)
138
+ end
139
+ end
140
+
141
+ describe 'with an empty exclusive range' do
142
+ before :all do
143
+ @return = @resources = @articles.send(method, 0...0)
144
+ end
145
+
146
+ it 'returns a Collection' do
147
+ expect(@return).to be_kind_of(DataMapper::Collection)
148
+ end
149
+
150
+ it 'returns the expected value' do
151
+ expect(@return.to_a).to eq @copy.entries.send(method, 0...0)
152
+ end
153
+
154
+ it 'is empty' do
155
+ expect(@return).to be_empty
156
+ end
157
+ end
158
+
159
+ describe 'with an offset not within the Collection' do
160
+ before :all do
161
+ unless @skip
162
+ @return = @articles.send(method, 99)
163
+ end
164
+ end
165
+
166
+ it 'returns nil' do
167
+ expect(@return).to be_nil
168
+ end
169
+ end
170
+
171
+ describe 'with an offset and length not within the Collection' do
172
+ before :all do
173
+ @return = @articles.send(method, 99, 1)
174
+ end
175
+
176
+ it 'returns a Collection' do
177
+ expect(@return).to be_kind_of(DataMapper::Collection)
178
+ end
179
+
180
+ it 'is empty' do
181
+ expect(@return).to be_empty
182
+ end
183
+ end
184
+
185
+ describe 'with a range not within the Collection' do
186
+ before :all do
187
+ @return = @articles.send(method, 99..100)
188
+ end
189
+
190
+ it 'returns a Collection' do
191
+ expect(@return).to be_kind_of(DataMapper::Collection)
192
+ end
193
+
194
+ it 'is empty' do
195
+ expect(@return).to be_empty
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ it { expect(@articles).to respond_to(:all) }
202
+
203
+ describe '#all' do
204
+ describe 'with no arguments' do
205
+ before :all do
206
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
207
+
208
+ @return = @collection = @articles.all
209
+ end
210
+
211
+ it 'returns a Collection' do
212
+ expect(@return).to be_kind_of(DataMapper::Collection)
213
+ end
214
+
215
+ it 'returns a new instance' do
216
+ expect(@return).not_to equal(@articles)
217
+ end
218
+
219
+ it 'is expected Resources' do
220
+ expect(@collection).to eq @articles.entries
221
+ end
222
+
223
+ it 'does not have a Query the same as the original' do
224
+ expect(@return.query).not_to equal(@articles.query)
225
+ end
226
+
227
+ it 'has a Query equal to the original' do
228
+ expect(@return.query).to eql(@articles.query)
229
+ end
230
+
231
+ it 'scopes the Collection' do
232
+ expect(@collection.reload).to eq @copy.entries
233
+ end
234
+ end
235
+
236
+ describe 'with a query' do
237
+ before :all do
238
+ @new = @articles.create(:content => 'New Article')
239
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
240
+
241
+ @return = @articles.all(:content => [ 'New Article' ])
242
+ end
243
+
244
+ it 'returns a Collection' do
245
+ expect(@return).to be_kind_of(DataMapper::Collection)
246
+ end
247
+
248
+ it 'returns a new instance' do
249
+ expect(@return).not_to equal(@articles)
250
+ end
251
+
252
+ it 'is expected Resources' do
253
+ expect(@return).to eq [ @new ]
254
+ end
255
+
256
+ it 'has a different query than original Collection' do
257
+ expect(@return.query).not_to equal(@articles.query)
258
+ end
259
+
260
+ it 'scopes the Collection' do
261
+ expect(@return.reload).to eq @copy.entries.select { |resource| resource.content == 'New Article' }
262
+ end
263
+ end
264
+
265
+ describe 'with a query using raw conditions' do
266
+ before do
267
+ pending unless defined?(DataMapper::Adapters::DataObjectsAdapter) && @adapter.kind_of?(DataMapper::Adapters::DataObjectsAdapter)
268
+ end
269
+
270
+ before :all do
271
+ @new = @articles.create(:subtitle => 'New Article')
272
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
273
+
274
+ @return = @articles.all(:conditions => [ 'subtitle = ?', 'New Article' ])
275
+ end
276
+
277
+ it 'returns a Collection' do
278
+ expect(@return).to be_kind_of(DataMapper::Collection)
279
+ end
280
+
281
+ it 'returns a new instance' do
282
+ expect(@return).not_to equal(@articles)
283
+ end
284
+
285
+ it 'is expected Resources' do
286
+ expect(@return).to eq [ @new ]
287
+ end
288
+
289
+ it 'has a different query than original Collection' do
290
+ expect(@return.query).not_to eq @articles.query
291
+ end
292
+
293
+ it 'scopes the Collection' do
294
+ expect(@return.reload).to eq @copy.entries.select { |resource| resource.subtitle == 'New Article' }.first(1)
295
+ end
296
+ end
297
+
298
+ describe 'with a query that is out of range' do
299
+ it 'raises an exception' do
300
+ expect {
301
+ @articles.all(:limit => 10).all(:offset => 10)
302
+ }.to raise_error(RangeError, 'offset 10 and limit 0 are outside allowed range')
303
+ end
304
+ end
305
+
306
+ describe 'with a query using a m:1 relationship' do
307
+ describe 'with a Hash' do
308
+ before :all do
309
+ @return = @articles.all(:original => @original.attributes)
310
+ end
311
+
312
+ it 'returns a Collection' do
313
+ expect(@return).to be_kind_of(DataMapper::Collection)
314
+ end
315
+
316
+ it 'is expected Resources' do
317
+ expect(@return).to eq [ @article ]
318
+ end
319
+
320
+ it 'has a valid query' do
321
+ expect(@return.query).to be_valid
322
+ end
323
+ end
324
+
325
+ describe 'with a resource' do
326
+ before :all do
327
+ @return = @articles.all(:original => @original)
328
+ end
329
+
330
+ it 'returns a Collection' do
331
+ expect(@return).to be_kind_of(DataMapper::Collection)
332
+ end
333
+
334
+ it 'are expected Resources' do
335
+ expect(@return).to eq [ @article ]
336
+ end
337
+
338
+ it 'has a valid query' do
339
+ expect(@return.query).to be_valid
340
+ end
341
+ end
342
+
343
+ describe 'with a collection' do
344
+ before :all do
345
+ @collection = @article_model.all(
346
+ Hash[ @article_model.key.zip(@original.key) ]
347
+ )
348
+
349
+ @return = @articles.all(:original => @collection)
350
+ end
351
+
352
+ it 'returns a Collection' do
353
+ expect(@return).to be_kind_of(DataMapper::Collection)
354
+ end
355
+
356
+ it 'is expected Resources' do
357
+ expect(@return).to eq [ @article ]
358
+ end
359
+
360
+ it 'has a valid query' do
361
+ expect(@return.query).to be_valid
362
+ end
363
+
364
+ end
365
+
366
+ describe 'with an empty Array' do
367
+ before :all do
368
+ @return = @articles.all(:original => [])
369
+ end
370
+
371
+ it 'returns a Collection' do
372
+ expect(@return).to be_kind_of(DataMapper::Collection)
373
+ end
374
+
375
+ it 'is an empty Collection' do
376
+ expect(@return).to be_empty
377
+ end
378
+
379
+ it 'does not have a valid query' do
380
+ expect(@return.query).not_to be_valid
381
+ end
382
+ end
383
+
384
+ describe 'with a nil value' do
385
+ before :all do
386
+ @return = @articles.all(:original => nil)
387
+ end
388
+
389
+ it 'returns a Collection' do
390
+ expect(@return).to be_kind_of(DataMapper::Collection)
391
+ end
392
+
393
+ if respond_to?(:model?) && model?
394
+ it 'is expected Resources' do
395
+ expect(@return).to eq [ @original, @other ]
396
+ end
397
+ else
398
+ it 'is an empty Collection' do
399
+ expect(@return).to be_empty
400
+ end
401
+ end
402
+
403
+ it 'has a valid query' do
404
+ expect(@return.query).to be_valid
405
+ end
406
+
407
+ it 'is equivalent to negated collection query' do
408
+ pending 'Update RDBMS to match ruby behavior' if @do_adapter && @articles.kind_of?(DataMapper::Model)
409
+
410
+ # NOTE: the second query will not match any articles where original_id
411
+ # is nil, while the in-memory/yaml adapters will. RDBMS will explicitly
412
+ # filter out NULL matches because we are matching on a non-NULL value,
413
+ # which is not consistent with how DM/Ruby matching behaves.
414
+ expect(@return).to eq @articles.all(:original.not => @article_model.all)
415
+ end
416
+ end
417
+
418
+ describe 'with a negated nil value' do
419
+ before :all do
420
+ @return = @articles.all(:original.not => nil)
421
+ end
422
+
423
+ it 'returns a Collection' do
424
+ expect(@return).to be_kind_of(DataMapper::Collection)
425
+ end
426
+
427
+ it 'are expected Resources' do
428
+ expect(@return).to eq [ @article ]
429
+ end
430
+
431
+ it 'has a valid query' do
432
+ expect(@return.query).to be_valid
433
+ end
434
+
435
+ it 'is equivalent to collection query' do
436
+ expect(@return).to eq @articles.all(:original => @article_model.all)
437
+ end
438
+ end
439
+ end
440
+
441
+ describe 'with a query using a 1:1 relationship' do
442
+ before :all do
443
+ @new = @articles.create(:content => 'New Article', :original => @article)
444
+ end
445
+
446
+ describe 'with a Hash' do
447
+ before :all do
448
+ @return = @articles.all(:previous => @new.attributes)
449
+ end
450
+
451
+ it 'returns a Collection' do
452
+ expect(@return).to be_kind_of(DataMapper::Collection)
453
+ end
454
+
455
+ it 'are expected Resources' do
456
+ expect(@return).to eq [ @article ]
457
+ end
458
+
459
+ it 'has a valid query' do
460
+ expect(@return.query).to be_valid
461
+ end
462
+ end
463
+
464
+ describe 'with a resource' do
465
+ before :all do
466
+ @return = @articles.all(:previous => @new)
467
+ end
468
+
469
+ it 'returns a Collection' do
470
+ expect(@return).to be_kind_of(DataMapper::Collection)
471
+ end
472
+
473
+ it 'are expected Resources' do
474
+ expect(@return).to eq [ @article ]
475
+ end
476
+
477
+ it 'has a valid query' do
478
+ expect(@return.query).to be_valid
479
+ end
480
+ end
481
+
482
+ describe 'with a collection' do
483
+ before :all do
484
+ @collection = @article_model.all(
485
+ Hash[ @article_model.key.zip(@new.key) ]
486
+ )
487
+
488
+ @return = @articles.all(:previous => @collection)
489
+ end
490
+
491
+ it 'returns a Collection' do
492
+ expect(@return).to be_kind_of(DataMapper::Collection)
493
+ end
494
+
495
+ it 'are expected Resources' do
496
+ expect(@return).to eq [ @article ]
497
+ end
498
+
499
+ it 'has a valid query' do
500
+ expect(@return.query).to be_valid
501
+ end
502
+ end
503
+
504
+ describe 'with an empty Array' do
505
+ before :all do
506
+ @return = @articles.all(:previous => [])
507
+ end
508
+
509
+ it 'returns a Collection' do
510
+ expect(@return).to be_kind_of(DataMapper::Collection)
511
+ end
512
+
513
+ it 'is an empty Collection' do
514
+ expect(@return).to be_empty
515
+ end
516
+
517
+ it 'does not have a valid query' do
518
+ expect(@return.query).not_to be_valid
519
+ end
520
+ end
521
+
522
+ describe 'with a nil value' do
523
+ before :all do
524
+ @return = @articles.all(:previous => nil)
525
+ end
526
+
527
+ it 'returns a Collection' do
528
+ expect(@return).to be_kind_of(DataMapper::Collection)
529
+ end
530
+
531
+ if respond_to?(:model?) && model?
532
+ it 'are expected Resources' do
533
+ expect(@return).to eq [ @other, @new ]
534
+ end
535
+ else
536
+ it 'are expected Resources' do
537
+ expect(@return).to eq [ @new ]
538
+ end
539
+ end
540
+
541
+ it 'has a valid query' do
542
+ expect(@return.query).to be_valid
543
+ end
544
+
545
+ it 'is equivalent to negated collection query' do
546
+ expect(@return).to eq @articles.all(:previous.not => @article_model.all(:original.not => nil))
547
+ end
548
+ end
549
+
550
+ describe 'with a negated nil value' do
551
+ before :all do
552
+ @return = @articles.all(:previous.not => nil)
553
+ end
554
+
555
+ it 'returns a Collection' do
556
+ expect(@return).to be_kind_of(DataMapper::Collection)
557
+ end
558
+
559
+ if respond_to?(:model?) && model?
560
+ it 'are expected Resources' do
561
+ expect(@return).to eq [ @original, @article ]
562
+ end
563
+ else
564
+ it 'are expected Resources' do
565
+ expect(@return).to eq [ @article ]
566
+ end
567
+ end
568
+
569
+ it 'has a valid query' do
570
+ expect(@return.query).to be_valid
571
+ end
572
+
573
+ it 'is equivalent to collection query' do
574
+ expect(@return).to eq @articles.all(:previous => @article_model.all)
575
+ end
576
+ end
577
+ end
578
+
579
+ describe 'with a query using a 1:m relationship' do
580
+ before :all do
581
+ @new = @articles.create(:content => 'New Article', :original => @article)
582
+ end
583
+
584
+ describe 'with a Hash' do
585
+ before :all do
586
+ @return = @articles.all(:revisions => @new.attributes)
587
+ end
588
+
589
+ it 'returns a Collection' do
590
+ expect(@return).to be_kind_of(DataMapper::Collection)
591
+ end
592
+
593
+ it 'are expected Resources' do
594
+ expect(@return).to eq [ @article ]
595
+ end
596
+
597
+ it 'has a valid query' do
598
+ expect(@return.query).to be_valid
599
+ end
600
+ end
601
+
602
+ describe 'with a resource' do
603
+ before :all do
604
+ @return = @articles.all(:revisions => @new)
605
+ end
606
+
607
+ it 'returns a Collection' do
608
+ expect(@return).to be_kind_of(DataMapper::Collection)
609
+ end
610
+
611
+ it 'are expected Resources' do
612
+ expect(@return).to eq [ @article ]
613
+ end
614
+
615
+ it 'has a valid query' do
616
+ expect(@return.query).to be_valid
617
+ end
618
+ end
619
+
620
+ describe 'with a collection' do
621
+ before :all do
622
+ @collection = @article_model.all(
623
+ Hash[ @article_model.key.zip(@new.key) ]
624
+ )
625
+
626
+ @return = @articles.all(:revisions => @collection)
627
+ end
628
+
629
+ it 'returns a Collection' do
630
+ expect(@return).to be_kind_of(DataMapper::Collection)
631
+ end
632
+
633
+ it 'are expected Resources' do
634
+ expect(@return).to eq [ @article ]
635
+ end
636
+
637
+ it 'has a valid query' do
638
+ expect(@return.query).to be_valid
639
+ end
640
+ end
641
+
642
+ describe 'with an empty Array' do
643
+ before :all do
644
+ @return = @articles.all(:revisions => [])
645
+ end
646
+
647
+ it 'returns a Collection' do
648
+ expect(@return).to be_kind_of(DataMapper::Collection)
649
+ end
650
+
651
+ it 'is an empty Collection' do
652
+ expect(@return).to be_empty
653
+ end
654
+
655
+ it 'does not have a valid query' do
656
+ expect(@return.query).not_to be_valid
657
+ end
658
+ end
659
+
660
+ describe 'with a nil value' do
661
+ before :all do
662
+ @return = @articles.all(:revisions => nil)
663
+ end
664
+
665
+ it 'returns a Collection' do
666
+ expect(@return).to be_kind_of(DataMapper::Collection)
667
+ end
668
+
669
+ if respond_to?(:model?) && model?
670
+ it 'are expected Resources' do
671
+ expect(@return).to eq [ @other, @new ]
672
+ end
673
+ else
674
+ it 'are expected Resources' do
675
+ expect(@return).to eq [ @new ]
676
+ end
677
+ end
678
+
679
+ it 'has a valid query' do
680
+ expect(@return.query).to be_valid
681
+ end
682
+
683
+ it 'is equivalent to negated collection query' do
684
+ expect(@return).to eq @articles.all(:revisions.not => @article_model.all(:original.not => nil))
685
+ end
686
+ end
687
+
688
+ describe 'with a negated nil value' do
689
+ before :all do
690
+ @return = @articles.all(:revisions.not => nil)
691
+ end
692
+
693
+ it 'returns a Collection' do
694
+ expect(@return).to be_kind_of(DataMapper::Collection)
695
+ end
696
+
697
+ if respond_to?(:model?) && model?
698
+ it 'are expected Resources' do
699
+ expect(@return).to eq [ @original, @article ]
700
+ end
701
+ else
702
+ it 'are expected Resources' do
703
+ expect(@return).to eq [ @article ]
704
+ end
705
+ end
706
+
707
+ it 'has a valid query' do
708
+ expect(@return.query).to be_valid
709
+ end
710
+
711
+ it 'is equivalent to collection query' do
712
+ expect(@return).to eq @articles.all(:revisions => @article_model.all)
713
+ end
714
+ end
715
+ end
716
+
717
+ describe 'with a query using a m:m relationship' do
718
+ before :all do
719
+ @publication = @article.publications.create(:name => 'DataMapper Now')
720
+ end
721
+
722
+ describe 'with a Hash' do
723
+ before :all do
724
+ @return = @articles.all(:publications => @publication.attributes)
725
+ end
726
+
727
+ it 'returns a Collection' do
728
+ expect(@return).to be_kind_of(DataMapper::Collection)
729
+ end
730
+
731
+ it 'are expected Resources' do
732
+ pending 'TODO'
733
+
734
+ expect(@return).to eq [ @article ]
735
+ end
736
+
737
+ it 'has a valid query' do
738
+ expect(@return.query).to be_valid
739
+ end
740
+ end
741
+
742
+ describe 'with a resource' do
743
+ before :all do
744
+ @return = @articles.all(:publications => @publication)
745
+ end
746
+
747
+ it 'returns a Collection' do
748
+ expect(@return).to be_kind_of(DataMapper::Collection)
749
+ end
750
+
751
+ it 'are expected Resources' do
752
+ pending 'TODO'
753
+
754
+ expect(@return).to eq [ @article ]
755
+ end
756
+
757
+ it 'has a valid query' do
758
+ expect(@return.query).to be_valid
759
+ end
760
+ end
761
+
762
+ describe 'with a collection' do
763
+ before :all do
764
+ @collection = @publication_model.all(
765
+ Hash[ @publication_model.key.zip(@publication.key) ]
766
+ )
767
+
768
+ @return = @articles.all(:publications => @collection)
769
+ end
770
+
771
+ it 'returns a Collection' do
772
+ expect(@return).to be_kind_of(DataMapper::Collection)
773
+ end
774
+
775
+ it 'are expected Resources' do
776
+ pending 'TODO'
777
+
778
+ expect(@return).to eq [ @article ]
779
+ end
780
+
781
+ it 'has a valid query' do
782
+ expect(@return.query).to be_valid
783
+ end
784
+ end
785
+
786
+ describe 'with an empty Array' do
787
+ before :all do
788
+ @return = @articles.all(:publications => [])
789
+ end
790
+
791
+ it 'returns a Collection' do
792
+ expect(@return).to be_kind_of(DataMapper::Collection)
793
+ end
794
+
795
+ it 'is an empty Collection' do
796
+ expect(@return).to be_empty
797
+ end
798
+
799
+ it 'does not have a valid query' do
800
+ expect(@return.query).not_to be_valid
801
+ end
802
+ end
803
+
804
+ describe 'with a nil value' do
805
+ before :all do
806
+ @return = @articles.all(:publications => nil)
807
+ end
808
+
809
+ it 'returns a Collection' do
810
+ expect(@return).to be_kind_of(DataMapper::Collection)
811
+ end
812
+
813
+ it 'is empty' do
814
+ pending 'TODO'
815
+
816
+ expect(@return).to be_empty
817
+ end
818
+
819
+ it 'has a valid query' do
820
+ expect(@return.query).to be_valid
821
+ end
822
+
823
+ it 'is equivalent to negated collection query' do
824
+ expect(@return).to eq @articles.all(:publications.not => @publication_model.all)
825
+ end
826
+ end
827
+
828
+ describe 'with a negated nil value' do
829
+ before :all do
830
+ @return = @articles.all(:publications.not => nil)
831
+ end
832
+
833
+ it 'returns a Collection' do
834
+ expect(@return).to be_kind_of(DataMapper::Collection)
835
+ end
836
+
837
+ it 'are expected Resources' do
838
+ pending 'TODO'
839
+
840
+ expect(@return).to eq [ @article ]
841
+ end
842
+
843
+ it 'has a valid query' do
844
+ expect(@return.query).to be_valid
845
+ end
846
+
847
+ it 'is equivalent to collection query' do
848
+ expect(@return).to eq @articles.all(:publications => @publication_model.all)
849
+ end
850
+ end
851
+ end
852
+ end
853
+
854
+ it { expect(@articles).to respond_to(:at) }
855
+
856
+ describe '#at' do
857
+ before :all do
858
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
859
+ @copy.to_a
860
+ end
861
+
862
+ describe 'with positive offset' do
863
+ before :all do
864
+ @return = @resource = @articles.at(0)
865
+ end
866
+
867
+ should_not_be_a_kicker
868
+
869
+ it 'returns a Resource' do
870
+ expect(@return).to be_kind_of(DataMapper::Resource)
871
+ end
872
+
873
+ it 'returns expected Resource' do
874
+ expect(@resource).to eq @copy.entries.at(0)
875
+ end
876
+ end
877
+
878
+ describe 'with negative offset' do
879
+ before :all do
880
+ @return = @resource = @articles.at(-1)
881
+ end
882
+
883
+ should_not_be_a_kicker
884
+
885
+ it 'returns a Resource' do
886
+ expect(@return).to be_kind_of(DataMapper::Resource)
887
+ end
888
+
889
+ it 'returns expected Resource' do
890
+ expect(@resource).to eq @copy.entries.at(-1)
891
+ end
892
+ end
893
+ end
894
+
895
+ it { expect(@articles).to respond_to(:each) }
896
+
897
+ describe '#each' do
898
+ context 'with a block' do
899
+ subject { @articles.each(&block) }
900
+
901
+ let(:yields) { [] }
902
+ let(:block) { lambda { |resource| yields << resource } }
903
+
904
+ before do
905
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
906
+ @copy.to_a
907
+ end
908
+
909
+ it { is_expected.to equal(@articles) }
910
+
911
+ it { expect { method(:subject) }.to change { yields.dup }.from([]).to(@copy.to_a) }
912
+ end
913
+
914
+ context 'without a block' do
915
+ subject { @articles.each }
916
+
917
+ let(:yields) { [] }
918
+ let(:block) { lambda { |resource| yields << resource } }
919
+
920
+ before do
921
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
922
+ @copy.to_a
923
+ end
924
+
925
+ it { is_expected.to be_instance_of(to_enum.class) }
926
+
927
+ it { expect { subject.each(&block) }.to change { yields.dup }.from([]).to(@copy.to_a) }
928
+ end
929
+ end
930
+
931
+ it { expect(@articles).to respond_to(:fetch) }
932
+
933
+ describe '#fetch' do
934
+ subject { @articles.fetch(*args, &block) }
935
+
936
+ let(:block) { nil }
937
+
938
+ context 'with a valid index and no default' do
939
+ let(:args) { [ 0 ] }
940
+
941
+ before do
942
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
943
+ @copy.to_a
944
+ end
945
+
946
+ should_not_be_a_kicker
947
+
948
+ it { is_expected.to be_kind_of(DataMapper::Resource) }
949
+
950
+ it { is_expected.to eq @copy.entries.fetch(*args) }
951
+ end
952
+
953
+ context 'with an invalid index and no default' do
954
+ let(:args) { [ 42 ] }
955
+
956
+ it { expect { method(:subject) }.to raise_error(IndexError) }
957
+ end
958
+
959
+ context 'with an invalid index and a default' do
960
+ let(:default) { mock('Default') }
961
+ let(:args) { [ 42, default ] }
962
+
963
+ it { is_expected.to equal(default) }
964
+ end
965
+
966
+ context 'with an invalid index and a block default' do
967
+ let(:yields) { [] }
968
+ let(:default) { mock('Default') }
969
+ let(:block) { lambda { |index| yields << index; default } }
970
+ let(:args) { [ 42 ] }
971
+
972
+ it { is_expected.to equal(default) }
973
+
974
+ it { expect { method(:subject) }.to change { yields.dup }.from([]).to([ 42 ]) }
975
+ end
976
+ end
977
+
978
+ it { expect(@articles).to respond_to(:first) }
979
+
980
+ describe '#first' do
981
+ before :all do
982
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
983
+
984
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
985
+ @copy.to_a
986
+ end
987
+
988
+ describe 'with no arguments' do
989
+ before :all do
990
+ @return = @resource = @articles.first
991
+ end
992
+
993
+ it 'returns a Resource' do
994
+ expect(@return).to be_kind_of(DataMapper::Resource)
995
+ end
996
+
997
+ it 'is first Resource in the Collection' do
998
+ expect(@resource).to eq @copy.entries.first
999
+ end
1000
+ end
1001
+
1002
+ describe 'with empty query' do
1003
+ before :all do
1004
+ @return = @resource = @articles.first({})
1005
+ end
1006
+
1007
+ it 'returns a Resource' do
1008
+ expect(@return).to be_kind_of(DataMapper::Resource)
1009
+ end
1010
+
1011
+ it 'is first Resource in the Collection' do
1012
+ expect(@resource).to eq @copy.entries.first
1013
+ end
1014
+ end
1015
+
1016
+ describe 'with a query' do
1017
+ before :all do
1018
+ @return = @resource = @articles.first(:content => 'Sample')
1019
+ end
1020
+
1021
+ it 'returns a Resource' do
1022
+ expect(@return).to be_kind_of(DataMapper::Resource)
1023
+ end
1024
+
1025
+ it 'is first Resource in the Collection matching the query' do
1026
+ expect(@resource).to eq @article
1027
+ end
1028
+ end
1029
+
1030
+ describe 'with a limit specified' do
1031
+ before :all do
1032
+ @return = @resources = @articles.first(1)
1033
+ end
1034
+
1035
+ it 'returns a Collection' do
1036
+ expect(@return).to be_kind_of(DataMapper::Collection)
1037
+ end
1038
+
1039
+ it 'is the first N Resources in the Collection' do
1040
+ expect(@resources).to eq @copy.entries.first(1)
1041
+ end
1042
+ end
1043
+
1044
+ describe 'on an empty collection' do
1045
+ before :all do
1046
+ @articles = @articles.all(:id => nil)
1047
+ @return = @articles.first
1048
+ end
1049
+
1050
+ it 'is still an empty collection' do
1051
+ expect(@articles).to be_empty
1052
+ end
1053
+
1054
+ it 'returns nil' do
1055
+ expect(@return).to be_nil
1056
+ end
1057
+ end
1058
+
1059
+ describe 'with offset specified' do
1060
+ before :all do
1061
+ @return = @resource = @articles.first(:offset => 1)
1062
+ end
1063
+
1064
+ it 'returns a Resource' do
1065
+ expect(@return).to be_kind_of(DataMapper::Resource)
1066
+ end
1067
+
1068
+ it 'is the second Resource in the Collection' do
1069
+ expect(@resource).to eq @copy.entries[1]
1070
+ end
1071
+ end
1072
+
1073
+ describe 'with a limit and query specified' do
1074
+ before :all do
1075
+ @return = @resources = @articles.first(1, :content => 'Sample')
1076
+ end
1077
+
1078
+ it 'returns a Collection' do
1079
+ expect(@return).to be_kind_of(DataMapper::Collection)
1080
+ end
1081
+
1082
+ it 'is the first N Resources in the Collection matching the query' do
1083
+ expect(@resources).to eq [ @article ]
1084
+ end
1085
+ end
1086
+ end
1087
+
1088
+ it { expect(@articles).to respond_to(:first_or_create) }
1089
+
1090
+ describe '#first_or_create' do
1091
+ describe 'with conditions that find an existing Resource' do
1092
+ before :all do
1093
+ @return = @resource = @articles.first_or_create(@article.attributes)
1094
+ end
1095
+
1096
+ it 'returns a Resource' do
1097
+ expect(@return).to be_kind_of(DataMapper::Resource)
1098
+ end
1099
+
1100
+ it 'is expected Resource' do
1101
+ expect(@resource).to eq @article
1102
+ end
1103
+
1104
+ it 'is a saved Resource' do
1105
+ expect(@resource).to be_saved
1106
+ end
1107
+ end
1108
+
1109
+ describe 'with conditions that do not find an existing Resource' do
1110
+ before :all do
1111
+ @conditions = { :content => 'Unknown Content' }
1112
+ @attributes = {}
1113
+
1114
+ @return = @resource = @articles.first_or_create(@conditions, @attributes)
1115
+ end
1116
+
1117
+ it 'returns a Resource' do
1118
+ expect(@return).to be_kind_of(DataMapper::Resource)
1119
+ end
1120
+
1121
+ it 'is expected Resource' do
1122
+ expect(DataMapper::Ext::Hash.only(@resource.attributes, *@conditions.keys)).to eq @conditions
1123
+ end
1124
+
1125
+ it 'is a saved Resource' do
1126
+ expect(@resource).to be_saved
1127
+ end
1128
+ end
1129
+ end
1130
+
1131
+ it { expect(@articles).to respond_to(:first_or_new) }
1132
+
1133
+ describe '#first_or_new' do
1134
+ describe 'with conditions that find an existing Resource' do
1135
+ before :all do
1136
+ @return = @resource = @articles.first_or_new(@article.attributes)
1137
+ end
1138
+
1139
+ it 'returns a Resource' do
1140
+ expect(@return).to be_kind_of(DataMapper::Resource)
1141
+ end
1142
+
1143
+ it 'is expected Resource' do
1144
+ expect(@resource).to eq @article
1145
+ end
1146
+
1147
+ it 'is a saved Resource' do
1148
+ expect(@resource).to be_saved
1149
+ end
1150
+ end
1151
+
1152
+ describe 'with conditions that do not find an existing Resource' do
1153
+ before :all do
1154
+ @conditions = { :content => 'Unknown Content' }
1155
+ @attributes = {}
1156
+
1157
+ @return = @resource = @articles.first_or_new(@conditions, @attributes)
1158
+ end
1159
+
1160
+ it 'returns a Resource' do
1161
+ expect(@return).to be_kind_of(DataMapper::Resource)
1162
+ end
1163
+
1164
+ it 'is expected Resource' do
1165
+ expect(DataMapper::Ext::Hash.only(@resource.attributes, *@conditions.keys)).to eq @conditions
1166
+ end
1167
+
1168
+ it 'is a saved Resource' do
1169
+ expect(@resource).to be_new
1170
+ end
1171
+ end
1172
+ end
1173
+
1174
+ [ :get, :get! ].each do |method|
1175
+ it { expect(@articles).to respond_to(method) }
1176
+
1177
+ describe "##{method}" do
1178
+ describe 'with a key to a Resource within the Collection' do
1179
+ before :all do
1180
+ unless @skip
1181
+ @return = @resource = @articles.send(method, *@article.key)
1182
+ end
1183
+ end
1184
+
1185
+ it 'returns a Resource' do
1186
+ expect(@return).to be_kind_of(DataMapper::Resource)
1187
+ end
1188
+
1189
+ it 'is matching Resource in the Collection' do
1190
+ expect(@resource).to eq @article
1191
+ end
1192
+ end
1193
+
1194
+ describe 'with a key not typecast' do
1195
+ before :all do
1196
+ unless @skip
1197
+ @return = @resource = @articles.send(method, *@article.key.map { |value| value.to_s })
1198
+ end
1199
+ end
1200
+
1201
+ it 'returns a Resource' do
1202
+ expect(@return).to be_kind_of(DataMapper::Resource)
1203
+ end
1204
+
1205
+ it 'is matching Resource in the Collection' do
1206
+ expect(@resource).to eq @article
1207
+ end
1208
+ end
1209
+
1210
+ describe 'with a key to a Resource not within the Collection' do
1211
+ if method == :get
1212
+ it 'returns nil' do
1213
+ expect(@articles.get(99)).to be_nil
1214
+ end
1215
+ else
1216
+ it 'raises an exception' do
1217
+ expect {
1218
+ @articles.get!(99)
1219
+ }.to raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key \[99\]")
1220
+ end
1221
+ end
1222
+ end
1223
+
1224
+ describe 'with a key that is nil' do
1225
+ if method == :get
1226
+ it 'returns nil' do
1227
+ expect(@articles.get(nil)).to be_nil
1228
+ end
1229
+ else
1230
+ it 'raises an exception' do
1231
+ expect {
1232
+ @articles.get!(nil)
1233
+ }.to raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [nil]")
1234
+ end
1235
+ end
1236
+ end
1237
+
1238
+ describe 'with a key that is an empty String' do
1239
+ if method == :get
1240
+ it 'returns nil' do
1241
+ expect(@articles.get('')).to be_nil
1242
+ end
1243
+ else
1244
+ it 'raises an exception' do
1245
+ expect {
1246
+ @articles.get!('')
1247
+ }.to raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [\"\"]")
1248
+ end
1249
+ end
1250
+ end
1251
+
1252
+ describe 'with a key that has incorrect number of arguments' do
1253
+ subject { @articles.send(method) }
1254
+
1255
+ it 'raises an exception' do
1256
+ expect { method(:subject) }.to raise_error(ArgumentError, 'The number of arguments for the key is invalid, expected 1 but was 0')
1257
+ end
1258
+ end
1259
+ end
1260
+ end
1261
+
1262
+ it { expect(@articles).to respond_to(:last) }
1263
+
1264
+ describe '#last' do
1265
+ before :all do
1266
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
1267
+
1268
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
1269
+ @copy.to_a
1270
+ end
1271
+
1272
+ describe 'with no arguments' do
1273
+ before :all do
1274
+ @return = @resource = @articles.last
1275
+ end
1276
+
1277
+ it 'returns a Resource' do
1278
+ expect(@return).to be_kind_of(DataMapper::Resource)
1279
+ end
1280
+
1281
+ it 'is last Resource in the Collection' do
1282
+ expect(@resource).to eq @copy.entries.last
1283
+ end
1284
+ end
1285
+
1286
+ describe 'with a query' do
1287
+ before :all do
1288
+ @return = @resource = @articles.last(:content => 'Sample')
1289
+ end
1290
+
1291
+ it 'returns a Resource' do
1292
+ expect(@return).to be_kind_of(DataMapper::Resource)
1293
+ end
1294
+
1295
+ it 'is the last Resource in the Collection matching the query' do
1296
+ expect(@resource).to eq @article
1297
+ end
1298
+
1299
+ it 'does not update the original query order' do
1300
+ collection = @articles.all(:order => [ :title ])
1301
+ original_order = collection.query.order[0].dup
1302
+ last = collection.last(:content => 'Sample')
1303
+
1304
+ expect(last).to eq @resource
1305
+
1306
+ expect(collection.query.order[0]).to eq original_order
1307
+ end
1308
+ end
1309
+
1310
+ describe 'with a limit specified' do
1311
+ before :all do
1312
+ @return = @resources = @articles.last(1)
1313
+ end
1314
+
1315
+ it 'returns a Collection' do
1316
+ expect(@return).to be_kind_of(DataMapper::Collection)
1317
+ end
1318
+
1319
+ it 'is the last N Resources in the Collection' do
1320
+ expect(@resources).to eq @copy.entries.last(1)
1321
+ end
1322
+ end
1323
+
1324
+ describe 'with offset specified' do
1325
+ before :all do
1326
+ @return = @resource = @articles.last(:offset => 1)
1327
+ end
1328
+
1329
+ it 'returns a Resource' do
1330
+ expect(@return).to be_kind_of(DataMapper::Resource)
1331
+ end
1332
+
1333
+ it 'is the second Resource in the Collection' do
1334
+ expect(@resource).to eq @copy.entries[-2]
1335
+ end
1336
+ end
1337
+
1338
+ describe 'with a limit and query specified' do
1339
+ before :all do
1340
+ @return = @resources = @articles.last(1, :content => 'Sample')
1341
+ end
1342
+
1343
+ it 'returns a Collection' do
1344
+ expect(@return).to be_kind_of(DataMapper::Collection)
1345
+ end
1346
+
1347
+ it 'is the last N Resources in the Collection matching the query' do
1348
+ expect(@resources).to eq [ @article ]
1349
+ end
1350
+ end
1351
+ end
1352
+
1353
+ it { expect(@articles).to respond_to(:reverse) }
1354
+
1355
+ describe '#reverse' do
1356
+ before :all do
1357
+ @query = @articles.query
1358
+
1359
+ @new = @articles.create(:title => 'Sample Article')
1360
+
1361
+ @return = @articles.reverse
1362
+ end
1363
+
1364
+ it 'returns a Collection' do
1365
+ expect(@return).to be_kind_of(DataMapper::Collection)
1366
+ end
1367
+
1368
+ it 'returns a Collection with reversed entries' do
1369
+ expect(@return).to eq @articles.entries.reverse
1370
+ end
1371
+
1372
+ it 'returns a Query that is the reverse of the original' do
1373
+ expect(@return.query).to eq @query.reverse
1374
+ end
1375
+ end
1376
+
1377
+ it { expect(@articles).to respond_to(:values_at) }
1378
+
1379
+ describe '#values_at' do
1380
+ subject { @articles.values_at(*args) }
1381
+
1382
+ before :all do
1383
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
1384
+ @copy.to_a
1385
+ end
1386
+
1387
+ context 'with positive offset' do
1388
+ let(:args) { [ 0 ] }
1389
+
1390
+ should_not_be_a_kicker
1391
+
1392
+ it { is_expected.to be_kind_of(Array) }
1393
+
1394
+ it { is_expected.to eq @copy.entries.values_at(*args) }
1395
+ end
1396
+
1397
+ describe 'with negative offset' do
1398
+ let(:args) { [ -1 ] }
1399
+
1400
+ should_not_be_a_kicker
1401
+
1402
+ it { is_expected.to be_kind_of(Array) }
1403
+
1404
+ it { is_expected.to eq @copy.entries.values_at(*args) }
1405
+ end
1406
+ end
1407
+
1408
+ it 'responds to a belongs_to relationship method with #method_missing' do
1409
+ pending 'Model#method_missing should delegate to relationships' if @articles.kind_of?(Class)
1410
+
1411
+ expect(@articles).to respond_to(:original)
1412
+ end
1413
+
1414
+ it 'responds to a has n relationship method with #method_missing' do
1415
+ pending 'Model#method_missing should delegate to relationships' if @articles.kind_of?(Class)
1416
+
1417
+ expect(@articles).to respond_to(:revisions)
1418
+ end
1419
+
1420
+ it 'responds to a has 1 relationship method with #method_missing' do
1421
+ pending 'Model#method_missing should delegate to relationships' if @articles.kind_of?(Class)
1422
+
1423
+ expect(@articles).to respond_to(:previous)
1424
+ end
1425
+
1426
+ describe '#method_missing' do
1427
+ before do
1428
+ pending 'Model#method_missing delegates to relationships' if @articles.kind_of?(Class)
1429
+ end
1430
+
1431
+ describe 'with a belongs_to relationship method' do
1432
+ before :all do
1433
+ rescue_if 'Model#method_missing delegates to relationships', @articles.kind_of?(Class) do
1434
+ @articles.create(:content => 'Another Article', :original => @original)
1435
+
1436
+ @return = @collection = @articles.originals
1437
+ end
1438
+ end
1439
+
1440
+ should_not_be_a_kicker
1441
+
1442
+ it 'returns a Collection' do
1443
+ expect(@return).to be_kind_of(DataMapper::Collection)
1444
+ end
1445
+
1446
+ it 'returns expected Collection' do
1447
+ expect(@collection).to eq [ @original ]
1448
+ end
1449
+
1450
+ it 'sets the association for each Resource' do
1451
+ expect(@articles.map { |resource| resource.original }).to eq [ @original, @original ]
1452
+ end
1453
+ end
1454
+
1455
+ describe 'with a has 1 relationship method' do
1456
+ before :all do
1457
+ # FIXME: create is necessary for m:m so that the intermediary
1458
+ # is created properly. This does not occur with @new.save
1459
+ @new = @articles.send(@many_to_many ? :create : :new)
1460
+
1461
+ @article.previous = @new
1462
+ @new.previous = @other
1463
+
1464
+ expect(@article.save).to be(true)
1465
+ end
1466
+
1467
+ describe 'with no arguments' do
1468
+ before :all do
1469
+ @return = @articles.previous
1470
+ end
1471
+
1472
+ should_not_be_a_kicker
1473
+
1474
+ it 'returns a Collection' do
1475
+ expect(@return).to be_kind_of(DataMapper::Collection)
1476
+ end
1477
+
1478
+ it 'returns expected Collection' do
1479
+ # association is sorted reverse by id
1480
+ expect(@return).to eq [ @new, @other ]
1481
+ end
1482
+
1483
+ it 'sets the association for each Resource' do
1484
+ expect(@articles.map { |resource| resource.previous }).to eq [ @new, @other ]
1485
+ end
1486
+ end
1487
+
1488
+ describe 'with arguments' do
1489
+ before :all do
1490
+ @return = @articles.previous(:fields => [ :id ])
1491
+ end
1492
+
1493
+ should_not_be_a_kicker
1494
+
1495
+ it 'returns a Collection' do
1496
+ expect(@return).to be_kind_of(DataMapper::Collection)
1497
+ end
1498
+
1499
+ it 'returns expected Collection' do
1500
+ # association is sorted reverse by id
1501
+ expect(@return).to eq [ @new, @other ]
1502
+ end
1503
+
1504
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1505
+ it "has query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1506
+ @return.each { |resource| expect(resource.attribute_loaded?(attribute)).to eq expected }
1507
+ end
1508
+ end
1509
+
1510
+ it 'sets the association for each Resource' do
1511
+ expect(@articles.map { |resource| resource.previous }).to eq [ @new, @other ]
1512
+ end
1513
+ end
1514
+ end
1515
+
1516
+ describe 'with a has n relationship method' do
1517
+ before :all do
1518
+ # FIXME: create is necessary for m:m so that the intermediary
1519
+ # is created properly. This does not occur with @new.save
1520
+ @new = @articles.send(@many_to_many ? :create : :new)
1521
+
1522
+ # associate the article with children
1523
+ @article.revisions << @new
1524
+ @new.revisions << @other
1525
+
1526
+ expect(@article.save).to be(true)
1527
+ end
1528
+
1529
+ describe 'with no arguments' do
1530
+ before :all do
1531
+ @return = @collection = @articles.revisions
1532
+ end
1533
+
1534
+ should_not_be_a_kicker
1535
+
1536
+ it 'returns a Collection' do
1537
+ expect(@return).to be_kind_of(DataMapper::Collection)
1538
+ end
1539
+
1540
+ it 'returns expected Collection' do
1541
+ expect(@collection).to eq [ @other, @new ]
1542
+ end
1543
+
1544
+ it 'sets the association for each Resource' do
1545
+ expect(@articles.map { |resource| resource.revisions }).to eq [ [ @new ], [ @other ] ]
1546
+ end
1547
+ end
1548
+
1549
+ describe 'with arguments' do
1550
+ before :all do
1551
+ @return = @collection = @articles.revisions(:fields => [ :id ])
1552
+ end
1553
+
1554
+ should_not_be_a_kicker
1555
+
1556
+ it 'returns a Collection' do
1557
+ expect(@return).to be_kind_of(DataMapper::Collection)
1558
+ end
1559
+
1560
+ it 'returns expected Collection' do
1561
+ expect(@collection).to eq [ @other, @new ]
1562
+ end
1563
+
1564
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1565
+ it "has query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1566
+ @collection.each { |resource| expect(resource.attribute_loaded?(attribute)).to eq expected }
1567
+ end
1568
+ end
1569
+
1570
+ it 'sets the association for each Resource' do
1571
+ expect(@articles.map { |resource| resource.revisions }).to eq [ [ @new ], [ @other ] ]
1572
+ end
1573
+ end
1574
+ end
1575
+
1576
+ describe 'with a has n :through relationship method' do
1577
+ before :all do
1578
+ @new = @articles.create
1579
+
1580
+ @publication1 = @article.publications.create(:name => 'Ruby Today')
1581
+ @publication2 = @new.publications.create(:name => 'Inside DataMapper')
1582
+ end
1583
+
1584
+ describe 'with no arguments' do
1585
+ before :all do
1586
+ @return = @collection = @articles.publications
1587
+ end
1588
+
1589
+ should_not_be_a_kicker
1590
+
1591
+ it 'returns a Collection' do
1592
+ expect(@return).to be_kind_of(DataMapper::Collection)
1593
+ end
1594
+
1595
+ it 'returns expected Collection' do
1596
+ pending if @no_join
1597
+
1598
+ expect(@collection).to eq [ @publication1, @publication2 ]
1599
+ end
1600
+
1601
+ it 'sets the association for each Resource' do
1602
+ pending if @no_join
1603
+
1604
+ expect(@articles.map { |resource| resource.publications }).to eq [ [ @publication1 ], [ @publication2 ] ]
1605
+ end
1606
+ end
1607
+
1608
+ describe 'with arguments' do
1609
+ before :all do
1610
+ @return = @collection = @articles.publications(:fields => [ :id ])
1611
+ end
1612
+
1613
+ should_not_be_a_kicker
1614
+
1615
+ it 'returns a Collection' do
1616
+ expect(@return).to be_kind_of(DataMapper::Collection)
1617
+ end
1618
+
1619
+ it 'returns expected Collection' do
1620
+ pending if @no_join
1621
+
1622
+ expect(@collection).to eq [ @publication1, @publication2 ]
1623
+ end
1624
+
1625
+ { :id => true, :name => false }.each do |attribute, expected|
1626
+ it "has query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1627
+ @collection.each { |resource| expect(resource.attribute_loaded?(attribute)).to eq expected }
1628
+ end
1629
+ end
1630
+
1631
+ it 'sets the association for each Resource' do
1632
+ pending if @no_join
1633
+
1634
+ expect(@articles.map { |resource| resource.publications }).to eq [ [ @publication1 ], [ @publication2 ] ]
1635
+ end
1636
+ end
1637
+ end
1638
+
1639
+ describe 'with an unknown method' do
1640
+ it 'raises an exception' do
1641
+ expect {
1642
+ @articles.unknown
1643
+ }.to raise_error(NoMethodError)
1644
+ end
1645
+ end
1646
+ end
1647
+ end