ardm-core 1.2.1

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 +35 -0
  5. data/.travis.yml +23 -0
  6. data/.yardopts +1 -0
  7. data/Gemfile +63 -0
  8. data/LICENSE +20 -0
  9. data/README.rdoc +237 -0
  10. data/Rakefile +4 -0
  11. data/VERSION +1 -0
  12. data/ardm-core.gemspec +25 -0
  13. data/lib/ardm-core.rb +1 -0
  14. data/lib/dm-core.rb +285 -0
  15. data/lib/dm-core/adapters.rb +222 -0
  16. data/lib/dm-core/adapters/abstract_adapter.rb +236 -0
  17. data/lib/dm-core/adapters/in_memory_adapter.rb +113 -0
  18. data/lib/dm-core/associations/many_to_many.rb +496 -0
  19. data/lib/dm-core/associations/many_to_one.rb +296 -0
  20. data/lib/dm-core/associations/one_to_many.rb +345 -0
  21. data/lib/dm-core/associations/one_to_one.rb +86 -0
  22. data/lib/dm-core/associations/relationship.rb +663 -0
  23. data/lib/dm-core/backwards.rb +13 -0
  24. data/lib/dm-core/collection.rb +1514 -0
  25. data/lib/dm-core/core_ext/kernel.rb +23 -0
  26. data/lib/dm-core/core_ext/pathname.rb +6 -0
  27. data/lib/dm-core/core_ext/symbol.rb +10 -0
  28. data/lib/dm-core/identity_map.rb +7 -0
  29. data/lib/dm-core/model.rb +869 -0
  30. data/lib/dm-core/model/hook.rb +102 -0
  31. data/lib/dm-core/model/is.rb +32 -0
  32. data/lib/dm-core/model/property.rb +253 -0
  33. data/lib/dm-core/model/relationship.rb +377 -0
  34. data/lib/dm-core/model/scope.rb +89 -0
  35. data/lib/dm-core/property.rb +839 -0
  36. data/lib/dm-core/property/binary.rb +22 -0
  37. data/lib/dm-core/property/boolean.rb +31 -0
  38. data/lib/dm-core/property/class.rb +24 -0
  39. data/lib/dm-core/property/date.rb +45 -0
  40. data/lib/dm-core/property/date_time.rb +44 -0
  41. data/lib/dm-core/property/decimal.rb +50 -0
  42. data/lib/dm-core/property/discriminator.rb +46 -0
  43. data/lib/dm-core/property/float.rb +28 -0
  44. data/lib/dm-core/property/integer.rb +32 -0
  45. data/lib/dm-core/property/lookup.rb +29 -0
  46. data/lib/dm-core/property/numeric.rb +40 -0
  47. data/lib/dm-core/property/object.rb +28 -0
  48. data/lib/dm-core/property/serial.rb +13 -0
  49. data/lib/dm-core/property/string.rb +50 -0
  50. data/lib/dm-core/property/text.rb +12 -0
  51. data/lib/dm-core/property/time.rb +46 -0
  52. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  53. data/lib/dm-core/property/typecast/time.rb +33 -0
  54. data/lib/dm-core/property_set.rb +177 -0
  55. data/lib/dm-core/query.rb +1444 -0
  56. data/lib/dm-core/query/conditions/comparison.rb +910 -0
  57. data/lib/dm-core/query/conditions/operation.rb +720 -0
  58. data/lib/dm-core/query/direction.rb +36 -0
  59. data/lib/dm-core/query/operator.rb +35 -0
  60. data/lib/dm-core/query/path.rb +114 -0
  61. data/lib/dm-core/query/sort.rb +39 -0
  62. data/lib/dm-core/relationship_set.rb +72 -0
  63. data/lib/dm-core/repository.rb +226 -0
  64. data/lib/dm-core/resource.rb +1228 -0
  65. data/lib/dm-core/resource/persistence_state.rb +75 -0
  66. data/lib/dm-core/resource/persistence_state/clean.rb +40 -0
  67. data/lib/dm-core/resource/persistence_state/deleted.rb +30 -0
  68. data/lib/dm-core/resource/persistence_state/dirty.rb +96 -0
  69. data/lib/dm-core/resource/persistence_state/immutable.rb +34 -0
  70. data/lib/dm-core/resource/persistence_state/persisted.rb +29 -0
  71. data/lib/dm-core/resource/persistence_state/transient.rb +78 -0
  72. data/lib/dm-core/spec/lib/adapter_helpers.rb +54 -0
  73. data/lib/dm-core/spec/lib/collection_helpers.rb +20 -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 +173 -0
  78. data/lib/dm-core/spec/shared/adapter_spec.rb +326 -0
  79. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  80. data/lib/dm-core/spec/shared/resource_spec.rb +1236 -0
  81. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  82. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +134 -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 +402 -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 +12 -0
  102. data/lib/dm-core/support/logger.rb +199 -0
  103. data/lib/dm-core/support/mash.rb +176 -0
  104. data/lib/dm-core/support/naming_conventions.rb +90 -0
  105. data/lib/dm-core/support/ordered_set.rb +380 -0
  106. data/lib/dm-core/support/subject.rb +33 -0
  107. data/lib/dm-core/support/subject_set.rb +250 -0
  108. data/lib/dm-core/version.rb +3 -0
  109. data/script/performance.rb +275 -0
  110. data/script/profile.rb +218 -0
  111. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  112. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +68 -0
  113. data/spec/public/associations/many_to_many_spec.rb +197 -0
  114. data/spec/public/associations/many_to_one_spec.rb +83 -0
  115. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  116. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  117. data/spec/public/associations/one_to_many_spec.rb +81 -0
  118. data/spec/public/associations/one_to_one_spec.rb +176 -0
  119. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  120. data/spec/public/collection_spec.rb +69 -0
  121. data/spec/public/finalize_spec.rb +76 -0
  122. data/spec/public/model/hook_spec.rb +246 -0
  123. data/spec/public/model/property_spec.rb +88 -0
  124. data/spec/public/model/relationship_spec.rb +1040 -0
  125. data/spec/public/model_spec.rb +458 -0
  126. data/spec/public/property/binary_spec.rb +41 -0
  127. data/spec/public/property/boolean_spec.rb +22 -0
  128. data/spec/public/property/class_spec.rb +28 -0
  129. data/spec/public/property/date_spec.rb +22 -0
  130. data/spec/public/property/date_time_spec.rb +22 -0
  131. data/spec/public/property/decimal_spec.rb +23 -0
  132. data/spec/public/property/discriminator_spec.rb +135 -0
  133. data/spec/public/property/float_spec.rb +22 -0
  134. data/spec/public/property/integer_spec.rb +22 -0
  135. data/spec/public/property/object_spec.rb +107 -0
  136. data/spec/public/property/serial_spec.rb +22 -0
  137. data/spec/public/property/string_spec.rb +22 -0
  138. data/spec/public/property/text_spec.rb +63 -0
  139. data/spec/public/property/time_spec.rb +22 -0
  140. data/spec/public/property_spec.rb +341 -0
  141. data/spec/public/resource_spec.rb +284 -0
  142. data/spec/public/sel_spec.rb +53 -0
  143. data/spec/public/setup_spec.rb +145 -0
  144. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  145. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  146. data/spec/public/shared/collection_shared_spec.rb +1669 -0
  147. data/spec/public/shared/finder_shared_spec.rb +1629 -0
  148. data/spec/rcov.opts +6 -0
  149. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  150. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
  151. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  152. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  153. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  154. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  155. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  156. data/spec/semipublic/associations_spec.rb +177 -0
  157. data/spec/semipublic/collection_spec.rb +110 -0
  158. data/spec/semipublic/model_spec.rb +96 -0
  159. data/spec/semipublic/property/binary_spec.rb +13 -0
  160. data/spec/semipublic/property/boolean_spec.rb +47 -0
  161. data/spec/semipublic/property/class_spec.rb +33 -0
  162. data/spec/semipublic/property/date_spec.rb +43 -0
  163. data/spec/semipublic/property/date_time_spec.rb +46 -0
  164. data/spec/semipublic/property/decimal_spec.rb +83 -0
  165. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  166. data/spec/semipublic/property/float_spec.rb +82 -0
  167. data/spec/semipublic/property/integer_spec.rb +82 -0
  168. data/spec/semipublic/property/lookup_spec.rb +29 -0
  169. data/spec/semipublic/property/serial_spec.rb +13 -0
  170. data/spec/semipublic/property/string_spec.rb +13 -0
  171. data/spec/semipublic/property/text_spec.rb +31 -0
  172. data/spec/semipublic/property/time_spec.rb +50 -0
  173. data/spec/semipublic/property_spec.rb +114 -0
  174. data/spec/semipublic/query/conditions/comparison_spec.rb +1501 -0
  175. data/spec/semipublic/query/conditions/operation_spec.rb +1294 -0
  176. data/spec/semipublic/query/path_spec.rb +471 -0
  177. data/spec/semipublic/query_spec.rb +3777 -0
  178. data/spec/semipublic/resource/state/clean_spec.rb +88 -0
  179. data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
  180. data/spec/semipublic/resource/state/dirty_spec.rb +156 -0
  181. data/spec/semipublic/resource/state/immutable_spec.rb +105 -0
  182. data/spec/semipublic/resource/state/transient_spec.rb +162 -0
  183. data/spec/semipublic/resource/state_spec.rb +230 -0
  184. data/spec/semipublic/resource_spec.rb +23 -0
  185. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  186. data/spec/semipublic/shared/resource_shared_spec.rb +199 -0
  187. data/spec/semipublic/shared/resource_state_shared_spec.rb +79 -0
  188. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  189. data/spec/spec.opts +5 -0
  190. data/spec/spec_helper.rb +37 -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 +28 -0
  248. data/spec/unit/hook_spec.rb +1235 -0
  249. data/spec/unit/lazy_array_spec.rb +1949 -0
  250. data/spec/unit/mash_spec.rb +312 -0
  251. data/spec/unit/module_spec.rb +71 -0
  252. data/spec/unit/object_spec.rb +38 -0
  253. data/spec/unit/try_dup_spec.rb +46 -0
  254. data/tasks/ci.rake +1 -0
  255. data/tasks/db.rake +11 -0
  256. data/tasks/spec.rake +38 -0
  257. data/tasks/yard.rake +9 -0
  258. data/tasks/yardstick.rake +19 -0
  259. metadata +491 -0
@@ -0,0 +1,1629 @@
1
+ share_examples_for '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 'should be Enumerable' do
25
+ @articles.should be_kind_of(Enumerable)
26
+ end
27
+
28
+ [ :[], :slice ].each do |method|
29
+ it { @articles.should 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 'should return a Resource' do
45
+ @return.should be_kind_of(DataMapper::Resource)
46
+ end
47
+
48
+ it 'should return expected Resource' do
49
+ @return.should == @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 'should return a Collection' do
59
+ @return.should be_kind_of(DataMapper::Collection)
60
+ end
61
+
62
+ it 'should return the expected Resource' do
63
+ @return.should == @copy.entries.send(method, 5, 5)
64
+ end
65
+
66
+ it 'should scope the Collection' do
67
+ @resources.reload.should == @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 'should return a Collection' do
77
+ @return.should be_kind_of(DataMapper::Collection)
78
+ end
79
+
80
+ it 'should return the expected Resources' do
81
+ @return.should == @copy.entries.send(method, 5..10)
82
+ end
83
+
84
+ it 'should scope the Collection' do
85
+ @resources.reload.should == @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 'should return a Resource' do
97
+ @return.should be_kind_of(DataMapper::Resource)
98
+ end
99
+
100
+ it 'should return expected Resource' do
101
+ @return.should == @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 'should return a Collection' do
111
+ @return.should be_kind_of(DataMapper::Collection)
112
+ end
113
+
114
+ it 'should return the expected Resources' do
115
+ @return.should == @copy.entries.send(method, -5, 5)
116
+ end
117
+
118
+ it 'should scope the Collection' do
119
+ @resources.reload.should == @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 'should return a Collection' do
129
+ @return.should be_kind_of(DataMapper::Collection)
130
+ end
131
+
132
+ it 'should return the expected Resources' do
133
+ @return.to_a.should == @copy.entries.send(method, -5..-2)
134
+ end
135
+
136
+ it 'should scope the Collection' do
137
+ @resources.reload.should == @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 'should return a Collection' do
147
+ @return.should be_kind_of(DataMapper::Collection)
148
+ end
149
+
150
+ it 'should return the expected value' do
151
+ @return.to_a.should == @copy.entries.send(method, 0...0)
152
+ end
153
+
154
+ it 'should be empty' do
155
+ @return.should 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 'should return nil' do
167
+ @return.should 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 'should return a Collection' do
177
+ @return.should be_kind_of(DataMapper::Collection)
178
+ end
179
+
180
+ it 'should be empty' do
181
+ @return.should 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 'should return a Collection' do
191
+ @return.should be_kind_of(DataMapper::Collection)
192
+ end
193
+
194
+ it 'should be empty' do
195
+ @return.should be_empty
196
+ end
197
+ end
198
+ end
199
+ end
200
+
201
+ it { @articles.should 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 'should return a Collection' do
212
+ @return.should be_kind_of(DataMapper::Collection)
213
+ end
214
+
215
+ it 'should return a new instance' do
216
+ @return.should_not equal(@articles)
217
+ end
218
+
219
+ it 'should be expected Resources' do
220
+ @collection.should == @articles.entries
221
+ end
222
+
223
+ it 'should not have a Query the same as the original' do
224
+ @return.query.should_not equal(@articles.query)
225
+ end
226
+
227
+ it 'should have a Query equal to the original' do
228
+ @return.query.should eql(@articles.query)
229
+ end
230
+
231
+ it 'should scope the Collection' do
232
+ @collection.reload.should == @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 'should return a Collection' do
245
+ @return.should be_kind_of(DataMapper::Collection)
246
+ end
247
+
248
+ it 'should return a new instance' do
249
+ @return.should_not equal(@articles)
250
+ end
251
+
252
+ it 'should be expected Resources' do
253
+ @return.should == [ @new ]
254
+ end
255
+
256
+ it 'should have a different query than original Collection' do
257
+ @return.query.should_not equal(@articles.query)
258
+ end
259
+
260
+ it 'should scope the Collection' do
261
+ @return.reload.should == @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 'should return a Collection' do
278
+ @return.should be_kind_of(DataMapper::Collection)
279
+ end
280
+
281
+ it 'should return a new instance' do
282
+ @return.should_not equal(@articles)
283
+ end
284
+
285
+ it 'should be expected Resources' do
286
+ @return.should == [ @new ]
287
+ end
288
+
289
+ it 'should have a different query than original Collection' do
290
+ @return.query.should_not == @articles.query
291
+ end
292
+
293
+ it 'should scope the Collection' do
294
+ @return.reload.should == @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 'should raise an exception' do
300
+ lambda {
301
+ @articles.all(:limit => 10).all(:offset => 10)
302
+ }.should 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 'should return a Collection' do
313
+ @return.should be_kind_of(DataMapper::Collection)
314
+ end
315
+
316
+ it 'should be expected Resources' do
317
+ @return.should == [ @article ]
318
+ end
319
+
320
+ it 'should have a valid query' do
321
+ @return.query.should 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 'should return a Collection' do
331
+ @return.should be_kind_of(DataMapper::Collection)
332
+ end
333
+
334
+ it 'should be expected Resources' do
335
+ @return.should == [ @article ]
336
+ end
337
+
338
+ it 'should have a valid query' do
339
+ @return.query.should 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 'should return a Collection' do
353
+ @return.should be_kind_of(DataMapper::Collection)
354
+ end
355
+
356
+ it 'should be expected Resources' do
357
+ @return.should == [ @article ]
358
+ end
359
+
360
+ it 'should have a valid query' do
361
+ @return.query.should 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 'should return a Collection' do
372
+ @return.should be_kind_of(DataMapper::Collection)
373
+ end
374
+
375
+ it 'should be an empty Collection' do
376
+ @return.should be_empty
377
+ end
378
+
379
+ it 'should not have a valid query' do
380
+ @return.query.should_not 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 'should return a Collection' do
390
+ @return.should be_kind_of(DataMapper::Collection)
391
+ end
392
+
393
+ if respond_to?(:model?) && model?
394
+ it 'should be expected Resources' do
395
+ @return.should == [ @original, @other ]
396
+ end
397
+ else
398
+ it 'should be an empty Collection' do
399
+ @return.should be_empty
400
+ end
401
+ end
402
+
403
+ it 'should have a valid query' do
404
+ @return.query.should be_valid
405
+ end
406
+
407
+ it 'should be equivalent to negated collection query' do
408
+ pending_if 'Update RDBMS to match ruby behavior', @do_adapter && @articles.kind_of?(DataMapper::Model) do
409
+ # NOTE: the second query will not match any articles where original_id
410
+ # is nil, while the in-memory/yaml adapters will. RDBMS will explicitly
411
+ # filter out NULL matches because we are matching on a non-NULL value,
412
+ # which is not consistent with how DM/Ruby matching behaves.
413
+ @return.should == @articles.all(:original.not => @article_model.all)
414
+ end
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 'should return a Collection' do
424
+ @return.should be_kind_of(DataMapper::Collection)
425
+ end
426
+
427
+ it 'should be expected Resources' do
428
+ @return.should == [ @article ]
429
+ end
430
+
431
+ it 'should have a valid query' do
432
+ @return.query.should be_valid
433
+ end
434
+
435
+ it 'should be equivalent to collection query' do
436
+ @return.should == @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 'should return a Collection' do
452
+ @return.should be_kind_of(DataMapper::Collection)
453
+ end
454
+
455
+ it 'should be expected Resources' do
456
+ @return.should == [ @article ]
457
+ end
458
+
459
+ it 'should have a valid query' do
460
+ @return.query.should 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 'should return a Collection' do
470
+ @return.should be_kind_of(DataMapper::Collection)
471
+ end
472
+
473
+ it 'should be expected Resources' do
474
+ @return.should == [ @article ]
475
+ end
476
+
477
+ it 'should have a valid query' do
478
+ @return.query.should 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 'should return a Collection' do
492
+ @return.should be_kind_of(DataMapper::Collection)
493
+ end
494
+
495
+ it 'should be expected Resources' do
496
+ @return.should == [ @article ]
497
+ end
498
+
499
+ it 'should have a valid query' do
500
+ @return.query.should 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 'should return a Collection' do
510
+ @return.should be_kind_of(DataMapper::Collection)
511
+ end
512
+
513
+ it 'should be an empty Collection' do
514
+ @return.should be_empty
515
+ end
516
+
517
+ it 'should not have a valid query' do
518
+ @return.query.should_not 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 'should return a Collection' do
528
+ @return.should be_kind_of(DataMapper::Collection)
529
+ end
530
+
531
+ if respond_to?(:model?) && model?
532
+ it 'should be expected Resources' do
533
+ @return.should == [ @other, @new ]
534
+ end
535
+ else
536
+ it 'should be expected Resources' do
537
+ @return.should == [ @new ]
538
+ end
539
+ end
540
+
541
+ it 'should have a valid query' do
542
+ @return.query.should be_valid
543
+ end
544
+
545
+ it 'should be equivalent to negated collection query' do
546
+ @return.should == @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 'should return a Collection' do
556
+ @return.should be_kind_of(DataMapper::Collection)
557
+ end
558
+
559
+ if respond_to?(:model?) && model?
560
+ it 'should be expected Resources' do
561
+ @return.should == [ @original, @article ]
562
+ end
563
+ else
564
+ it 'should be expected Resources' do
565
+ @return.should == [ @article ]
566
+ end
567
+ end
568
+
569
+ it 'should have a valid query' do
570
+ @return.query.should be_valid
571
+ end
572
+
573
+ it 'should be equivalent to collection query' do
574
+ @return.should == @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 'should return a Collection' do
590
+ @return.should be_kind_of(DataMapper::Collection)
591
+ end
592
+
593
+ it 'should be expected Resources' do
594
+ @return.should == [ @article ]
595
+ end
596
+
597
+ it 'should have a valid query' do
598
+ @return.query.should 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 'should return a Collection' do
608
+ @return.should be_kind_of(DataMapper::Collection)
609
+ end
610
+
611
+ it 'should be expected Resources' do
612
+ @return.should == [ @article ]
613
+ end
614
+
615
+ it 'should have a valid query' do
616
+ @return.query.should 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 'should return a Collection' do
630
+ @return.should be_kind_of(DataMapper::Collection)
631
+ end
632
+
633
+ it 'should be expected Resources' do
634
+ @return.should == [ @article ]
635
+ end
636
+
637
+ it 'should have a valid query' do
638
+ @return.query.should 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 'should return a Collection' do
648
+ @return.should be_kind_of(DataMapper::Collection)
649
+ end
650
+
651
+ it 'should be an empty Collection' do
652
+ @return.should be_empty
653
+ end
654
+
655
+ it 'should not have a valid query' do
656
+ @return.query.should_not 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 'should return a Collection' do
666
+ @return.should be_kind_of(DataMapper::Collection)
667
+ end
668
+
669
+ if respond_to?(:model?) && model?
670
+ it 'should be expected Resources' do
671
+ @return.should == [ @other, @new ]
672
+ end
673
+ else
674
+ it 'should be expected Resources' do
675
+ @return.should == [ @new ]
676
+ end
677
+ end
678
+
679
+ it 'should have a valid query' do
680
+ @return.query.should be_valid
681
+ end
682
+
683
+ it 'should be equivalent to negated collection query' do
684
+ @return.should == @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 'should return a Collection' do
694
+ @return.should be_kind_of(DataMapper::Collection)
695
+ end
696
+
697
+ if respond_to?(:model?) && model?
698
+ it 'should be expected Resources' do
699
+ @return.should == [ @original, @article ]
700
+ end
701
+ else
702
+ it 'should be expected Resources' do
703
+ @return.should == [ @article ]
704
+ end
705
+ end
706
+
707
+ it 'should have a valid query' do
708
+ @return.query.should be_valid
709
+ end
710
+
711
+ it 'should be equivalent to collection query' do
712
+ @return.should == @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 'should return a Collection' do
728
+ @return.should be_kind_of(DataMapper::Collection)
729
+ end
730
+
731
+ it 'should be expected Resources' do
732
+ pending 'TODO' do
733
+ @return.should == [ @article ]
734
+ end
735
+ end
736
+
737
+ it 'should have a valid query' do
738
+ @return.query.should 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 'should return a Collection' do
748
+ @return.should be_kind_of(DataMapper::Collection)
749
+ end
750
+
751
+ it 'should be expected Resources' do
752
+ pending 'TODO' do
753
+ @return.should == [ @article ]
754
+ end
755
+ end
756
+
757
+ it 'should have a valid query' do
758
+ @return.query.should 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 'should return a Collection' do
772
+ @return.should be_kind_of(DataMapper::Collection)
773
+ end
774
+
775
+ it 'should be expected Resources' do
776
+ pending 'TODO' do
777
+ @return.should == [ @article ]
778
+ end
779
+ end
780
+
781
+ it 'should have a valid query' do
782
+ @return.query.should 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 'should return a Collection' do
792
+ @return.should be_kind_of(DataMapper::Collection)
793
+ end
794
+
795
+ it 'should be an empty Collection' do
796
+ @return.should be_empty
797
+ end
798
+
799
+ it 'should not have a valid query' do
800
+ @return.query.should_not 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 'should return a Collection' do
810
+ @return.should be_kind_of(DataMapper::Collection)
811
+ end
812
+
813
+ it 'should be empty' do
814
+ pending 'TODO' do
815
+ @return.should be_empty
816
+ end
817
+ end
818
+
819
+ it 'should have a valid query' do
820
+ @return.query.should be_valid
821
+ end
822
+
823
+ it 'should be equivalent to negated collection query' do
824
+ @return.should == @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 'should return a Collection' do
834
+ @return.should be_kind_of(DataMapper::Collection)
835
+ end
836
+
837
+ it 'should be expected Resources' do
838
+ pending 'TODO' do
839
+ @return.should == [ @article ]
840
+ end
841
+ end
842
+
843
+ it 'should have a valid query' do
844
+ @return.query.should be_valid
845
+ end
846
+
847
+ it 'should be equivalent to collection query' do
848
+ @return.should == @articles.all(:publications => @publication_model.all)
849
+ end
850
+ end
851
+ end
852
+ end
853
+
854
+ it { @articles.should 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 'should return a Resource' do
870
+ @return.should be_kind_of(DataMapper::Resource)
871
+ end
872
+
873
+ it 'should return expected Resource' do
874
+ @resource.should == @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 'should return a Resource' do
886
+ @return.should be_kind_of(DataMapper::Resource)
887
+ end
888
+
889
+ it 'should return expected Resource' do
890
+ @resource.should == @copy.entries.at(-1)
891
+ end
892
+ end
893
+ end
894
+
895
+ it { @articles.should respond_to(:each) }
896
+
897
+ describe '#each' do
898
+ subject { @articles.each(&block) }
899
+
900
+ let(:yields) { [] }
901
+ let(:block) { lambda { |resource| yields << resource } }
902
+
903
+ before do
904
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
905
+ @copy.to_a
906
+ end
907
+
908
+ it { should equal(@articles) }
909
+
910
+ it { method(:subject).should change { yields.dup }.from([]).to(@copy.to_a) }
911
+ end
912
+
913
+ it { @articles.should respond_to(:fetch) }
914
+
915
+ describe '#fetch' do
916
+ subject { @articles.fetch(*args, &block) }
917
+
918
+ let(:block) { nil }
919
+
920
+ context 'with a valid index and no default' do
921
+ let(:args) { [ 0 ] }
922
+
923
+ before do
924
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
925
+ @copy.to_a
926
+ end
927
+
928
+ should_not_be_a_kicker
929
+
930
+ it { should be_kind_of(DataMapper::Resource) }
931
+
932
+ it { should == @copy.entries.fetch(*args) }
933
+ end
934
+
935
+ context 'with an invalid index and no default' do
936
+ let(:args) { [ 42 ] }
937
+
938
+ it { method(:subject).should raise_error(IndexError) }
939
+ end
940
+
941
+ context 'with an invalid index and a default' do
942
+ let(:default) { mock('Default') }
943
+ let(:args) { [ 42, default ] }
944
+
945
+ it { should equal(default) }
946
+ end
947
+
948
+ context 'with an invalid index and a block default' do
949
+ let(:yields) { [] }
950
+ let(:default) { mock('Default') }
951
+ let(:block) { lambda { |index| yields << index; default } }
952
+ let(:args) { [ 42 ] }
953
+
954
+ it { should equal(default) }
955
+
956
+ it { method(:subject).should change { yields.dup }.from([]).to([ 42 ]) }
957
+ end
958
+ end
959
+
960
+ it { @articles.should respond_to(:first) }
961
+
962
+ describe '#first' do
963
+ before :all do
964
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
965
+
966
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
967
+ @copy.to_a
968
+ end
969
+
970
+ describe 'with no arguments' do
971
+ before :all do
972
+ @return = @resource = @articles.first
973
+ end
974
+
975
+ it 'should return a Resource' do
976
+ @return.should be_kind_of(DataMapper::Resource)
977
+ end
978
+
979
+ it 'should be first Resource in the Collection' do
980
+ @resource.should == @copy.entries.first
981
+ end
982
+ end
983
+
984
+ describe 'with empty query' do
985
+ before :all do
986
+ @return = @resource = @articles.first({})
987
+ end
988
+
989
+ it 'should return a Resource' do
990
+ @return.should be_kind_of(DataMapper::Resource)
991
+ end
992
+
993
+ it 'should be first Resource in the Collection' do
994
+ @resource.should == @copy.entries.first
995
+ end
996
+ end
997
+
998
+ describe 'with a query' do
999
+ before :all do
1000
+ @return = @resource = @articles.first(:content => 'Sample')
1001
+ end
1002
+
1003
+ it 'should return a Resource' do
1004
+ @return.should be_kind_of(DataMapper::Resource)
1005
+ end
1006
+
1007
+ it 'should should be the first Resource in the Collection matching the query' do
1008
+ @resource.should == @article
1009
+ end
1010
+ end
1011
+
1012
+ describe 'with a limit specified' do
1013
+ before :all do
1014
+ @return = @resources = @articles.first(1)
1015
+ end
1016
+
1017
+ it 'should return a Collection' do
1018
+ @return.should be_kind_of(DataMapper::Collection)
1019
+ end
1020
+
1021
+ it 'should be the first N Resources in the Collection' do
1022
+ @resources.should == @copy.entries.first(1)
1023
+ end
1024
+ end
1025
+
1026
+ describe 'on an empty collection' do
1027
+ before :all do
1028
+ @articles = @articles.all(:id => nil)
1029
+ @return = @articles.first
1030
+ end
1031
+
1032
+ it 'should still be an empty collection' do
1033
+ @articles.should be_empty
1034
+ end
1035
+
1036
+ it 'should return nil' do
1037
+ @return.should be_nil
1038
+ end
1039
+ end
1040
+
1041
+ describe 'with offset specified' do
1042
+ before :all do
1043
+ @return = @resource = @articles.first(:offset => 1)
1044
+ end
1045
+
1046
+ it 'should return a Resource' do
1047
+ @return.should be_kind_of(DataMapper::Resource)
1048
+ end
1049
+
1050
+ it 'should be the second Resource in the Collection' do
1051
+ @resource.should == @copy.entries[1]
1052
+ end
1053
+ end
1054
+
1055
+ describe 'with a limit and query specified' do
1056
+ before :all do
1057
+ @return = @resources = @articles.first(1, :content => 'Sample')
1058
+ end
1059
+
1060
+ it 'should return a Collection' do
1061
+ @return.should be_kind_of(DataMapper::Collection)
1062
+ end
1063
+
1064
+ it 'should be the first N Resources in the Collection matching the query' do
1065
+ @resources.should == [ @article ]
1066
+ end
1067
+ end
1068
+ end
1069
+
1070
+ it { @articles.should respond_to(:first_or_create) }
1071
+
1072
+ describe '#first_or_create' do
1073
+ describe 'with conditions that find an existing Resource' do
1074
+ before :all do
1075
+ @return = @resource = @articles.first_or_create(@article.attributes)
1076
+ end
1077
+
1078
+ it 'should return a Resource' do
1079
+ @return.should be_kind_of(DataMapper::Resource)
1080
+ end
1081
+
1082
+ it 'should be expected Resource' do
1083
+ @resource.should == @article
1084
+ end
1085
+
1086
+ it 'should be a saved Resource' do
1087
+ @resource.should be_saved
1088
+ end
1089
+ end
1090
+
1091
+ describe 'with conditions that do not find an existing Resource' do
1092
+ before :all do
1093
+ @conditions = { :content => 'Unknown Content' }
1094
+ @attributes = {}
1095
+
1096
+ @return = @resource = @articles.first_or_create(@conditions, @attributes)
1097
+ end
1098
+
1099
+ it 'should return a Resource' do
1100
+ @return.should be_kind_of(DataMapper::Resource)
1101
+ end
1102
+
1103
+ it 'should be expected Resource' do
1104
+ DataMapper::Ext::Hash.only(@resource.attributes, *@conditions.keys).should == @conditions
1105
+ end
1106
+
1107
+ it 'should be a saved Resource' do
1108
+ @resource.should be_saved
1109
+ end
1110
+ end
1111
+ end
1112
+
1113
+ it { @articles.should respond_to(:first_or_new) }
1114
+
1115
+ describe '#first_or_new' do
1116
+ describe 'with conditions that find an existing Resource' do
1117
+ before :all do
1118
+ @return = @resource = @articles.first_or_new(@article.attributes)
1119
+ end
1120
+
1121
+ it 'should return a Resource' do
1122
+ @return.should be_kind_of(DataMapper::Resource)
1123
+ end
1124
+
1125
+ it 'should be expected Resource' do
1126
+ @resource.should == @article
1127
+ end
1128
+
1129
+ it 'should be a saved Resource' do
1130
+ @resource.should be_saved
1131
+ end
1132
+ end
1133
+
1134
+ describe 'with conditions that do not find an existing Resource' do
1135
+ before :all do
1136
+ @conditions = { :content => 'Unknown Content' }
1137
+ @attributes = {}
1138
+
1139
+ @return = @resource = @articles.first_or_new(@conditions, @attributes)
1140
+ end
1141
+
1142
+ it 'should return a Resource' do
1143
+ @return.should be_kind_of(DataMapper::Resource)
1144
+ end
1145
+
1146
+ it 'should be expected Resource' do
1147
+ DataMapper::Ext::Hash.only(@resource.attributes, *@conditions.keys).should == @conditions
1148
+ end
1149
+
1150
+ it 'should not be a saved Resource' do
1151
+ @resource.should be_new
1152
+ end
1153
+ end
1154
+ end
1155
+
1156
+ [ :get, :get! ].each do |method|
1157
+ it { @articles.should respond_to(method) }
1158
+
1159
+ describe "##{method}" do
1160
+ describe 'with a key to a Resource within the Collection' do
1161
+ before :all do
1162
+ unless @skip
1163
+ @return = @resource = @articles.send(method, *@article.key)
1164
+ end
1165
+ end
1166
+
1167
+ it 'should return a Resource' do
1168
+ @return.should be_kind_of(DataMapper::Resource)
1169
+ end
1170
+
1171
+ it 'should be matching Resource in the Collection' do
1172
+ @resource.should == @article
1173
+ end
1174
+ end
1175
+
1176
+ describe 'with a key not typecast' do
1177
+ before :all do
1178
+ unless @skip
1179
+ @return = @resource = @articles.send(method, *@article.key.map { |value| value.to_s })
1180
+ end
1181
+ end
1182
+
1183
+ it 'should return a Resource' do
1184
+ @return.should be_kind_of(DataMapper::Resource)
1185
+ end
1186
+
1187
+ it 'should be matching Resource in the Collection' do
1188
+ @resource.should == @article
1189
+ end
1190
+ end
1191
+
1192
+ describe 'with a key to a Resource not within the Collection' do
1193
+ if method == :get
1194
+ it 'should return nil' do
1195
+ @articles.get(99).should be_nil
1196
+ end
1197
+ else
1198
+ it 'should raise an exception' do
1199
+ lambda {
1200
+ @articles.get!(99)
1201
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key \[99\]")
1202
+ end
1203
+ end
1204
+ end
1205
+
1206
+ describe 'with a key that is nil' do
1207
+ if method == :get
1208
+ it 'should return nil' do
1209
+ @articles.get(nil).should be_nil
1210
+ end
1211
+ else
1212
+ it 'should raise an exception' do
1213
+ lambda {
1214
+ @articles.get!(nil)
1215
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [nil]")
1216
+ end
1217
+ end
1218
+ end
1219
+
1220
+ describe 'with a key that is an empty String' do
1221
+ if method == :get
1222
+ it 'should return nil' do
1223
+ @articles.get('').should be_nil
1224
+ end
1225
+ else
1226
+ it 'should raise an exception' do
1227
+ lambda {
1228
+ @articles.get!('')
1229
+ }.should raise_error(DataMapper::ObjectNotFoundError, "Could not find #{@article_model} with key [\"\"]")
1230
+ end
1231
+ end
1232
+ end
1233
+
1234
+ describe 'with a key that has incorrect number of arguments' do
1235
+ subject { @articles.send(method) }
1236
+
1237
+ it 'should raise an exception' do
1238
+ method(:subject).should raise_error(ArgumentError, 'The number of arguments for the key is invalid, expected 1 but was 0')
1239
+ end
1240
+ end
1241
+ end
1242
+ end
1243
+
1244
+ it { @articles.should respond_to(:last) }
1245
+
1246
+ describe '#last' do
1247
+ before :all do
1248
+ 1.upto(5) { |number| @articles.create(:content => "Article #{number}") }
1249
+
1250
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
1251
+ @copy.to_a
1252
+ end
1253
+
1254
+ describe 'with no arguments' do
1255
+ before :all do
1256
+ @return = @resource = @articles.last
1257
+ end
1258
+
1259
+ it 'should return a Resource' do
1260
+ @return.should be_kind_of(DataMapper::Resource)
1261
+ end
1262
+
1263
+ it 'should be last Resource in the Collection' do
1264
+ @resource.should == @copy.entries.last
1265
+ end
1266
+ end
1267
+
1268
+ describe 'with a query' do
1269
+ before :all do
1270
+ @return = @resource = @articles.last(:content => 'Sample')
1271
+ end
1272
+
1273
+ it 'should return a Resource' do
1274
+ @return.should be_kind_of(DataMapper::Resource)
1275
+ end
1276
+
1277
+ it 'should should be the last Resource in the Collection matching the query' do
1278
+ @resource.should == @article
1279
+ end
1280
+
1281
+ it 'should not update the original query order' do
1282
+ collection = @articles.all(:order => [ :title ])
1283
+ original_order = collection.query.order[0].dup
1284
+ last = collection.last(:content => 'Sample')
1285
+
1286
+ last.should == @resource
1287
+
1288
+ collection.query.order[0].should == original_order
1289
+ end
1290
+ end
1291
+
1292
+ describe 'with a limit specified' do
1293
+ before :all do
1294
+ @return = @resources = @articles.last(1)
1295
+ end
1296
+
1297
+ it 'should return a Collection' do
1298
+ @return.should be_kind_of(DataMapper::Collection)
1299
+ end
1300
+
1301
+ it 'should be the last N Resources in the Collection' do
1302
+ @resources.should == @copy.entries.last(1)
1303
+ end
1304
+ end
1305
+
1306
+ describe 'with offset specified' do
1307
+ before :all do
1308
+ @return = @resource = @articles.last(:offset => 1)
1309
+ end
1310
+
1311
+ it 'should return a Resource' do
1312
+ @return.should be_kind_of(DataMapper::Resource)
1313
+ end
1314
+
1315
+ it 'should be the second Resource in the Collection' do
1316
+ @resource.should == @copy.entries[-2]
1317
+ end
1318
+ end
1319
+
1320
+ describe 'with a limit and query specified' do
1321
+ before :all do
1322
+ @return = @resources = @articles.last(1, :content => 'Sample')
1323
+ end
1324
+
1325
+ it 'should return a Collection' do
1326
+ @return.should be_kind_of(DataMapper::Collection)
1327
+ end
1328
+
1329
+ it 'should be the last N Resources in the Collection matching the query' do
1330
+ @resources.should == [ @article ]
1331
+ end
1332
+ end
1333
+ end
1334
+
1335
+ it { @articles.should respond_to(:reverse) }
1336
+
1337
+ describe '#reverse' do
1338
+ before :all do
1339
+ @query = @articles.query
1340
+
1341
+ @new = @articles.create(:title => 'Sample Article')
1342
+
1343
+ @return = @articles.reverse
1344
+ end
1345
+
1346
+ it 'should return a Collection' do
1347
+ @return.should be_kind_of(DataMapper::Collection)
1348
+ end
1349
+
1350
+ it 'should return a Collection with reversed entries' do
1351
+ @return.should == @articles.entries.reverse
1352
+ end
1353
+
1354
+ it 'should return a Query that is the reverse of the original' do
1355
+ @return.query.should == @query.reverse
1356
+ end
1357
+ end
1358
+
1359
+ it { @articles.should respond_to(:values_at) }
1360
+
1361
+ describe '#values_at' do
1362
+ subject { @articles.values_at(*args) }
1363
+
1364
+ before :all do
1365
+ @copy = @articles.kind_of?(Class) ? @articles : @articles.dup
1366
+ @copy.to_a
1367
+ end
1368
+
1369
+ context 'with positive offset' do
1370
+ let(:args) { [ 0 ] }
1371
+
1372
+ should_not_be_a_kicker
1373
+
1374
+ it { should be_kind_of(Array) }
1375
+
1376
+ it { should == @copy.entries.values_at(*args) }
1377
+ end
1378
+
1379
+ describe 'with negative offset' do
1380
+ let(:args) { [ -1 ] }
1381
+
1382
+ should_not_be_a_kicker
1383
+
1384
+ it { should be_kind_of(Array) }
1385
+
1386
+ it { should == @copy.entries.values_at(*args) }
1387
+ end
1388
+ end
1389
+
1390
+ it 'should respond to a belongs_to relationship method with #method_missing' do
1391
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1392
+ @articles.should respond_to(:original)
1393
+ end
1394
+ end
1395
+
1396
+ it 'should respond to a has n relationship method with #method_missing' do
1397
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1398
+ @articles.should respond_to(:revisions)
1399
+ end
1400
+ end
1401
+
1402
+ it 'should respond to a has 1 relationship method with #method_missing' do
1403
+ pending_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1404
+ @articles.should respond_to(:previous)
1405
+ end
1406
+ end
1407
+
1408
+ describe '#method_missing' do
1409
+ before do
1410
+ pending 'Model#method_missing should delegate to relationships' if @articles.kind_of?(Class)
1411
+ end
1412
+
1413
+ describe 'with a belongs_to relationship method' do
1414
+ before :all do
1415
+ rescue_if 'Model#method_missing should delegate to relationships', @articles.kind_of?(Class) do
1416
+ @articles.create(:content => 'Another Article', :original => @original)
1417
+
1418
+ @return = @collection = @articles.originals
1419
+ end
1420
+ end
1421
+
1422
+ should_not_be_a_kicker
1423
+
1424
+ it 'should return a Collection' do
1425
+ @return.should be_kind_of(DataMapper::Collection)
1426
+ end
1427
+
1428
+ it 'should return expected Collection' do
1429
+ @collection.should == [ @original ]
1430
+ end
1431
+
1432
+ it 'should set the association for each Resource' do
1433
+ @articles.map { |resource| resource.original }.should == [ @original, @original ]
1434
+ end
1435
+ end
1436
+
1437
+ describe 'with a has 1 relationship method' do
1438
+ before :all do
1439
+ # FIXME: create is necessary for m:m so that the intermediary
1440
+ # is created properly. This does not occur with @new.save
1441
+ @new = @articles.send(@many_to_many ? :create : :new)
1442
+
1443
+ @article.previous = @new
1444
+ @new.previous = @other
1445
+
1446
+ @article.save.should be(true)
1447
+ end
1448
+
1449
+ describe 'with no arguments' do
1450
+ before :all do
1451
+ @return = @articles.previous
1452
+ end
1453
+
1454
+ should_not_be_a_kicker
1455
+
1456
+ it 'should return a Collection' do
1457
+ @return.should be_kind_of(DataMapper::Collection)
1458
+ end
1459
+
1460
+ it 'should return expected Collection' do
1461
+ # association is sorted reverse by id
1462
+ @return.should == [ @new, @other ]
1463
+ end
1464
+
1465
+ it 'should set the association for each Resource' do
1466
+ @articles.map { |resource| resource.previous }.should == [ @new, @other ]
1467
+ end
1468
+ end
1469
+
1470
+ describe 'with arguments' do
1471
+ before :all do
1472
+ @return = @articles.previous(:fields => [ :id ])
1473
+ end
1474
+
1475
+ should_not_be_a_kicker
1476
+
1477
+ it 'should return a Collection' do
1478
+ @return.should be_kind_of(DataMapper::Collection)
1479
+ end
1480
+
1481
+ it 'should return expected Collection' do
1482
+ # association is sorted reverse by id
1483
+ @return.should == [ @new, @other ]
1484
+ end
1485
+
1486
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1487
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1488
+ @return.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1489
+ end
1490
+ end
1491
+
1492
+ it 'should set the association for each Resource' do
1493
+ @articles.map { |resource| resource.previous }.should == [ @new, @other ]
1494
+ end
1495
+ end
1496
+ end
1497
+
1498
+ describe 'with a has n relationship method' do
1499
+ before :all do
1500
+ # FIXME: create is necessary for m:m so that the intermediary
1501
+ # is created properly. This does not occur with @new.save
1502
+ @new = @articles.send(@many_to_many ? :create : :new)
1503
+
1504
+ # associate the article with children
1505
+ @article.revisions << @new
1506
+ @new.revisions << @other
1507
+
1508
+ @article.save.should be(true)
1509
+ end
1510
+
1511
+ describe 'with no arguments' do
1512
+ before :all do
1513
+ @return = @collection = @articles.revisions
1514
+ end
1515
+
1516
+ should_not_be_a_kicker
1517
+
1518
+ it 'should return a Collection' do
1519
+ @return.should be_kind_of(DataMapper::Collection)
1520
+ end
1521
+
1522
+ it 'should return expected Collection' do
1523
+ @collection.should == [ @other, @new ]
1524
+ end
1525
+
1526
+ it 'should set the association for each Resource' do
1527
+ @articles.map { |resource| resource.revisions }.should == [ [ @new ], [ @other ] ]
1528
+ end
1529
+ end
1530
+
1531
+ describe 'with arguments' do
1532
+ before :all do
1533
+ @return = @collection = @articles.revisions(:fields => [ :id ])
1534
+ end
1535
+
1536
+ should_not_be_a_kicker
1537
+
1538
+ it 'should return a Collection' do
1539
+ @return.should be_kind_of(DataMapper::Collection)
1540
+ end
1541
+
1542
+ it 'should return expected Collection' do
1543
+ @collection.should == [ @other, @new ]
1544
+ end
1545
+
1546
+ { :id => true, :title => false, :content => false }.each do |attribute, expected|
1547
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1548
+ @collection.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1549
+ end
1550
+ end
1551
+
1552
+ it 'should set the association for each Resource' do
1553
+ @articles.map { |resource| resource.revisions }.should == [ [ @new ], [ @other ] ]
1554
+ end
1555
+ end
1556
+ end
1557
+
1558
+ describe 'with a has n :through relationship method' do
1559
+ before :all do
1560
+ @new = @articles.create
1561
+
1562
+ @publication1 = @article.publications.create(:name => 'Ruby Today')
1563
+ @publication2 = @new.publications.create(:name => 'Inside DataMapper')
1564
+ end
1565
+
1566
+ describe 'with no arguments' do
1567
+ before :all do
1568
+ @return = @collection = @articles.publications
1569
+ end
1570
+
1571
+ should_not_be_a_kicker
1572
+
1573
+ it 'should return a Collection' do
1574
+ @return.should be_kind_of(DataMapper::Collection)
1575
+ end
1576
+
1577
+ it 'should return expected Collection' do
1578
+ pending_if @no_join do
1579
+ @collection.should == [ @publication1, @publication2 ]
1580
+ end
1581
+ end
1582
+
1583
+ it 'should set the association for each Resource' do
1584
+ pending_if @no_join do
1585
+ @articles.map { |resource| resource.publications }.should == [ [ @publication1 ], [ @publication2 ] ]
1586
+ end
1587
+ end
1588
+ end
1589
+
1590
+ describe 'with arguments' do
1591
+ before :all do
1592
+ @return = @collection = @articles.publications(:fields => [ :id ])
1593
+ end
1594
+
1595
+ should_not_be_a_kicker
1596
+
1597
+ it 'should return a Collection' do
1598
+ @return.should be_kind_of(DataMapper::Collection)
1599
+ end
1600
+
1601
+ it 'should return expected Collection' do
1602
+ pending_if @no_join do
1603
+ @collection.should == [ @publication1, @publication2 ]
1604
+ end
1605
+ end
1606
+
1607
+ { :id => true, :name => false }.each do |attribute, expected|
1608
+ it "should have query field #{attribute.inspect} #{'not' unless expected} loaded".squeeze(' ') do
1609
+ @collection.each { |resource| resource.attribute_loaded?(attribute).should == expected }
1610
+ end
1611
+ end
1612
+
1613
+ it 'should set the association for each Resource' do
1614
+ pending_if @no_join do
1615
+ @articles.map { |resource| resource.publications }.should == [ [ @publication1 ], [ @publication2 ] ]
1616
+ end
1617
+ end
1618
+ end
1619
+ end
1620
+
1621
+ describe 'with an unknown method' do
1622
+ it 'should raise an exception' do
1623
+ lambda {
1624
+ @articles.unknown
1625
+ }.should raise_error(NoMethodError)
1626
+ end
1627
+ end
1628
+ end
1629
+ end