sbf-dm-core 1.3.0.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. checksums.yaml +7 -0
  2. data/.autotest +29 -0
  3. data/.document +5 -0
  4. data/.gitignore +44 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +468 -0
  7. data/.travis.yml +57 -0
  8. data/.yardopts +1 -0
  9. data/Gemfile +70 -0
  10. data/LICENSE +20 -0
  11. data/README.md +269 -0
  12. data/Rakefile +4 -0
  13. data/dm-core.gemspec +21 -0
  14. data/lib/dm-core/adapters/abstract_adapter.rb +233 -0
  15. data/lib/dm-core/adapters/in_memory_adapter.rb +110 -0
  16. data/lib/dm-core/adapters.rb +249 -0
  17. data/lib/dm-core/associations/many_to_many.rb +477 -0
  18. data/lib/dm-core/associations/many_to_one.rb +282 -0
  19. data/lib/dm-core/associations/one_to_many.rb +332 -0
  20. data/lib/dm-core/associations/one_to_one.rb +84 -0
  21. data/lib/dm-core/associations/relationship.rb +650 -0
  22. data/lib/dm-core/backwards.rb +11 -0
  23. data/lib/dm-core/collection.rb +1486 -0
  24. data/lib/dm-core/core_ext/kernel.rb +21 -0
  25. data/lib/dm-core/core_ext/pathname.rb +4 -0
  26. data/lib/dm-core/core_ext/symbol.rb +10 -0
  27. data/lib/dm-core/identity_map.rb +6 -0
  28. data/lib/dm-core/model/hook.rb +99 -0
  29. data/lib/dm-core/model/is.rb +30 -0
  30. data/lib/dm-core/model/property.rb +244 -0
  31. data/lib/dm-core/model/relationship.rb +366 -0
  32. data/lib/dm-core/model/scope.rb +87 -0
  33. data/lib/dm-core/model.rb +876 -0
  34. data/lib/dm-core/property/binary.rb +19 -0
  35. data/lib/dm-core/property/boolean.rb +35 -0
  36. data/lib/dm-core/property/class.rb +23 -0
  37. data/lib/dm-core/property/date.rb +45 -0
  38. data/lib/dm-core/property/date_time.rb +44 -0
  39. data/lib/dm-core/property/decimal.rb +47 -0
  40. data/lib/dm-core/property/discriminator.rb +40 -0
  41. data/lib/dm-core/property/float.rb +27 -0
  42. data/lib/dm-core/property/integer.rb +32 -0
  43. data/lib/dm-core/property/invalid_value_error.rb +17 -0
  44. data/lib/dm-core/property/lookup.rb +26 -0
  45. data/lib/dm-core/property/numeric.rb +35 -0
  46. data/lib/dm-core/property/object.rb +33 -0
  47. data/lib/dm-core/property/serial.rb +13 -0
  48. data/lib/dm-core/property/string.rb +47 -0
  49. data/lib/dm-core/property/text.rb +12 -0
  50. data/lib/dm-core/property/time.rb +46 -0
  51. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  52. data/lib/dm-core/property/typecast/time.rb +33 -0
  53. data/lib/dm-core/property.rb +856 -0
  54. data/lib/dm-core/property_set.rb +177 -0
  55. data/lib/dm-core/query/conditions/comparison.rb +886 -0
  56. data/lib/dm-core/query/conditions/operation.rb +710 -0
  57. data/lib/dm-core/query/direction.rb +33 -0
  58. data/lib/dm-core/query/operator.rb +34 -0
  59. data/lib/dm-core/query/path.rb +113 -0
  60. data/lib/dm-core/query/sort.rb +38 -0
  61. data/lib/dm-core/query.rb +1352 -0
  62. data/lib/dm-core/relationship_set.rb +69 -0
  63. data/lib/dm-core/repository.rb +226 -0
  64. data/lib/dm-core/resource/persistence_state/clean.rb +36 -0
  65. data/lib/dm-core/resource/persistence_state/deleted.rb +26 -0
  66. data/lib/dm-core/resource/persistence_state/dirty.rb +91 -0
  67. data/lib/dm-core/resource/persistence_state/immutable.rb +32 -0
  68. data/lib/dm-core/resource/persistence_state/persisted.rb +25 -0
  69. data/lib/dm-core/resource/persistence_state/transient.rb +87 -0
  70. data/lib/dm-core/resource/persistence_state.rb +70 -0
  71. data/lib/dm-core/resource.rb +1220 -0
  72. data/lib/dm-core/spec/lib/adapter_helpers.rb +63 -0
  73. data/lib/dm-core/spec/lib/collection_helpers.rb +21 -0
  74. data/lib/dm-core/spec/lib/counter_adapter.rb +38 -0
  75. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  76. data/lib/dm-core/spec/lib/spec_helper.rb +74 -0
  77. data/lib/dm-core/spec/setup.rb +164 -0
  78. data/lib/dm-core/spec/shared/adapter_spec.rb +366 -0
  79. data/lib/dm-core/spec/shared/public/property_spec.rb +229 -0
  80. data/lib/dm-core/spec/shared/resource_spec.rb +1221 -0
  81. data/lib/dm-core/spec/shared/sel_spec.rb +111 -0
  82. data/lib/dm-core/spec/shared/semipublic/property_spec.rb +184 -0
  83. data/lib/dm-core/spec/shared/semipublic/query/conditions/abstract_comparison_spec.rb +261 -0
  84. data/lib/dm-core/support/assertions.rb +8 -0
  85. data/lib/dm-core/support/chainable.rb +18 -0
  86. data/lib/dm-core/support/deprecate.rb +12 -0
  87. data/lib/dm-core/support/descendant_set.rb +89 -0
  88. data/lib/dm-core/support/equalizer.rb +48 -0
  89. data/lib/dm-core/support/ext/array.rb +22 -0
  90. data/lib/dm-core/support/ext/blank.rb +25 -0
  91. data/lib/dm-core/support/ext/hash.rb +67 -0
  92. data/lib/dm-core/support/ext/module.rb +47 -0
  93. data/lib/dm-core/support/ext/object.rb +57 -0
  94. data/lib/dm-core/support/ext/string.rb +24 -0
  95. data/lib/dm-core/support/ext/try_dup.rb +12 -0
  96. data/lib/dm-core/support/hook.rb +388 -0
  97. data/lib/dm-core/support/inflections.rb +60 -0
  98. data/lib/dm-core/support/inflector/inflections.rb +211 -0
  99. data/lib/dm-core/support/inflector/methods.rb +151 -0
  100. data/lib/dm-core/support/lazy_array.rb +451 -0
  101. data/lib/dm-core/support/local_object_space.rb +13 -0
  102. data/lib/dm-core/support/logger.rb +201 -0
  103. data/lib/dm-core/support/mash.rb +176 -0
  104. data/lib/dm-core/support/naming_conventions.rb +109 -0
  105. data/lib/dm-core/support/ordered_set.rb +381 -0
  106. data/lib/dm-core/support/subject.rb +33 -0
  107. data/lib/dm-core/support/subject_set.rb +251 -0
  108. data/lib/dm-core/version.rb +3 -0
  109. data/lib/dm-core.rb +274 -0
  110. data/script/performance.rb +275 -0
  111. data/script/profile.rb +218 -0
  112. data/spec/lib/rspec_immediate_feedback_formatter.rb +54 -0
  113. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +69 -0
  114. data/spec/public/associations/many_to_many_spec.rb +197 -0
  115. data/spec/public/associations/many_to_one_spec.rb +83 -0
  116. data/spec/public/associations/many_to_one_with_boolean_cpk_spec.rb +40 -0
  117. data/spec/public/associations/many_to_one_with_custom_fk_spec.rb +49 -0
  118. data/spec/public/associations/one_to_many_spec.rb +81 -0
  119. data/spec/public/associations/one_to_one_spec.rb +176 -0
  120. data/spec/public/associations/one_to_one_with_boolean_cpk_spec.rb +46 -0
  121. data/spec/public/collection_spec.rb +69 -0
  122. data/spec/public/finalize_spec.rb +77 -0
  123. data/spec/public/model/hook_spec.rb +245 -0
  124. data/spec/public/model/property_spec.rb +91 -0
  125. data/spec/public/model/relationship_spec.rb +1040 -0
  126. data/spec/public/model_spec.rb +456 -0
  127. data/spec/public/property/binary_spec.rb +43 -0
  128. data/spec/public/property/boolean_spec.rb +21 -0
  129. data/spec/public/property/class_spec.rb +27 -0
  130. data/spec/public/property/date_spec.rb +21 -0
  131. data/spec/public/property/date_time_spec.rb +21 -0
  132. data/spec/public/property/decimal_spec.rb +23 -0
  133. data/spec/public/property/discriminator_spec.rb +134 -0
  134. data/spec/public/property/float_spec.rb +22 -0
  135. data/spec/public/property/integer_spec.rb +22 -0
  136. data/spec/public/property/object_spec.rb +117 -0
  137. data/spec/public/property/serial_spec.rb +22 -0
  138. data/spec/public/property/string_spec.rb +21 -0
  139. data/spec/public/property/text_spec.rb +62 -0
  140. data/spec/public/property/time_spec.rb +21 -0
  141. data/spec/public/property_spec.rb +333 -0
  142. data/spec/public/resource/state_spec.rb +72 -0
  143. data/spec/public/resource_spec.rb +289 -0
  144. data/spec/public/sel_spec.rb +53 -0
  145. data/spec/public/setup_spec.rb +145 -0
  146. data/spec/public/shared/association_collection_shared_spec.rb +309 -0
  147. data/spec/public/shared/collection_finder_shared_spec.rb +267 -0
  148. data/spec/public/shared/collection_shared_spec.rb +1637 -0
  149. data/spec/public/shared/finder_shared_spec.rb +1647 -0
  150. data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
  151. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +13 -0
  152. data/spec/semipublic/associations/many_to_many_spec.rb +94 -0
  153. data/spec/semipublic/associations/many_to_one_spec.rb +63 -0
  154. data/spec/semipublic/associations/one_to_many_spec.rb +55 -0
  155. data/spec/semipublic/associations/one_to_one_spec.rb +53 -0
  156. data/spec/semipublic/associations/relationship_spec.rb +200 -0
  157. data/spec/semipublic/associations_spec.rb +177 -0
  158. data/spec/semipublic/collection_spec.rb +110 -0
  159. data/spec/semipublic/model_spec.rb +96 -0
  160. data/spec/semipublic/property/binary_spec.rb +13 -0
  161. data/spec/semipublic/property/boolean_spec.rb +47 -0
  162. data/spec/semipublic/property/class_spec.rb +33 -0
  163. data/spec/semipublic/property/date_spec.rb +43 -0
  164. data/spec/semipublic/property/date_time_spec.rb +46 -0
  165. data/spec/semipublic/property/decimal_spec.rb +83 -0
  166. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  167. data/spec/semipublic/property/float_spec.rb +82 -0
  168. data/spec/semipublic/property/integer_spec.rb +82 -0
  169. data/spec/semipublic/property/lookup_spec.rb +29 -0
  170. data/spec/semipublic/property/serial_spec.rb +13 -0
  171. data/spec/semipublic/property/string_spec.rb +13 -0
  172. data/spec/semipublic/property/text_spec.rb +31 -0
  173. data/spec/semipublic/property/time_spec.rb +50 -0
  174. data/spec/semipublic/property_spec.rb +114 -0
  175. data/spec/semipublic/query/conditions/comparison_spec.rb +1502 -0
  176. data/spec/semipublic/query/conditions/operation_spec.rb +1296 -0
  177. data/spec/semipublic/query/path_spec.rb +471 -0
  178. data/spec/semipublic/query_spec.rb +3665 -0
  179. data/spec/semipublic/resource/state/clean_spec.rb +89 -0
  180. data/spec/semipublic/resource/state/deleted_spec.rb +79 -0
  181. data/spec/semipublic/resource/state/dirty_spec.rb +163 -0
  182. data/spec/semipublic/resource/state/immutable_spec.rb +107 -0
  183. data/spec/semipublic/resource/state/transient_spec.rb +163 -0
  184. data/spec/semipublic/resource/state_spec.rb +230 -0
  185. data/spec/semipublic/resource_spec.rb +23 -0
  186. data/spec/semipublic/shared/condition_shared_spec.rb +9 -0
  187. data/spec/semipublic/shared/resource_shared_spec.rb +198 -0
  188. data/spec/semipublic/shared/resource_state_shared_spec.rb +91 -0
  189. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  190. data/spec/spec_helper.rb +34 -0
  191. data/spec/support/core_ext/hash.rb +10 -0
  192. data/spec/support/core_ext/inheritable_attributes.rb +46 -0
  193. data/spec/support/properties/huge_integer.rb +17 -0
  194. data/spec/unit/array_spec.rb +23 -0
  195. data/spec/unit/blank_spec.rb +73 -0
  196. data/spec/unit/data_mapper/ordered_set/append_spec.rb +26 -0
  197. data/spec/unit/data_mapper/ordered_set/clear_spec.rb +24 -0
  198. data/spec/unit/data_mapper/ordered_set/delete_spec.rb +28 -0
  199. data/spec/unit/data_mapper/ordered_set/each_spec.rb +19 -0
  200. data/spec/unit/data_mapper/ordered_set/empty_spec.rb +20 -0
  201. data/spec/unit/data_mapper/ordered_set/entries_spec.rb +22 -0
  202. data/spec/unit/data_mapper/ordered_set/eql_spec.rb +51 -0
  203. data/spec/unit/data_mapper/ordered_set/equal_value_spec.rb +84 -0
  204. data/spec/unit/data_mapper/ordered_set/hash_spec.rb +12 -0
  205. data/spec/unit/data_mapper/ordered_set/include_spec.rb +23 -0
  206. data/spec/unit/data_mapper/ordered_set/index_spec.rb +28 -0
  207. data/spec/unit/data_mapper/ordered_set/initialize_spec.rb +32 -0
  208. data/spec/unit/data_mapper/ordered_set/merge_spec.rb +36 -0
  209. data/spec/unit/data_mapper/ordered_set/shared/append_spec.rb +24 -0
  210. data/spec/unit/data_mapper/ordered_set/shared/clear_spec.rb +9 -0
  211. data/spec/unit/data_mapper/ordered_set/shared/delete_spec.rb +25 -0
  212. data/spec/unit/data_mapper/ordered_set/shared/each_spec.rb +17 -0
  213. data/spec/unit/data_mapper/ordered_set/shared/empty_spec.rb +9 -0
  214. data/spec/unit/data_mapper/ordered_set/shared/entries_spec.rb +9 -0
  215. data/spec/unit/data_mapper/ordered_set/shared/include_spec.rb +9 -0
  216. data/spec/unit/data_mapper/ordered_set/shared/index_spec.rb +13 -0
  217. data/spec/unit/data_mapper/ordered_set/shared/initialize_spec.rb +28 -0
  218. data/spec/unit/data_mapper/ordered_set/shared/merge_spec.rb +28 -0
  219. data/spec/unit/data_mapper/ordered_set/shared/size_spec.rb +13 -0
  220. data/spec/unit/data_mapper/ordered_set/shared/to_ary_spec.rb +11 -0
  221. data/spec/unit/data_mapper/ordered_set/size_spec.rb +27 -0
  222. data/spec/unit/data_mapper/ordered_set/to_ary_spec.rb +23 -0
  223. data/spec/unit/data_mapper/subject_set/append_spec.rb +47 -0
  224. data/spec/unit/data_mapper/subject_set/clear_spec.rb +34 -0
  225. data/spec/unit/data_mapper/subject_set/delete_spec.rb +40 -0
  226. data/spec/unit/data_mapper/subject_set/each_spec.rb +30 -0
  227. data/spec/unit/data_mapper/subject_set/empty_spec.rb +31 -0
  228. data/spec/unit/data_mapper/subject_set/entries_spec.rb +31 -0
  229. data/spec/unit/data_mapper/subject_set/get_spec.rb +34 -0
  230. data/spec/unit/data_mapper/subject_set/include_spec.rb +32 -0
  231. data/spec/unit/data_mapper/subject_set/named_spec.rb +33 -0
  232. data/spec/unit/data_mapper/subject_set/shared/append_spec.rb +18 -0
  233. data/spec/unit/data_mapper/subject_set/shared/clear_spec.rb +9 -0
  234. data/spec/unit/data_mapper/subject_set/shared/delete_spec.rb +9 -0
  235. data/spec/unit/data_mapper/subject_set/shared/each_spec.rb +9 -0
  236. data/spec/unit/data_mapper/subject_set/shared/empty_spec.rb +9 -0
  237. data/spec/unit/data_mapper/subject_set/shared/entries_spec.rb +9 -0
  238. data/spec/unit/data_mapper/subject_set/shared/get_spec.rb +9 -0
  239. data/spec/unit/data_mapper/subject_set/shared/include_spec.rb +9 -0
  240. data/spec/unit/data_mapper/subject_set/shared/named_spec.rb +9 -0
  241. data/spec/unit/data_mapper/subject_set/shared/size_spec.rb +13 -0
  242. data/spec/unit/data_mapper/subject_set/shared/to_ary_spec.rb +9 -0
  243. data/spec/unit/data_mapper/subject_set/shared/values_at_spec.rb +44 -0
  244. data/spec/unit/data_mapper/subject_set/size_spec.rb +42 -0
  245. data/spec/unit/data_mapper/subject_set/to_ary_spec.rb +34 -0
  246. data/spec/unit/data_mapper/subject_set/values_at_spec.rb +57 -0
  247. data/spec/unit/hash_spec.rb +27 -0
  248. data/spec/unit/hook_spec.rb +1216 -0
  249. data/spec/unit/inflections_spec.rb +14 -0
  250. data/spec/unit/lazy_array_spec.rb +1949 -0
  251. data/spec/unit/mash_spec.rb +289 -0
  252. data/spec/unit/module_spec.rb +70 -0
  253. data/spec/unit/object_spec.rb +38 -0
  254. data/spec/unit/try_dup_spec.rb +46 -0
  255. data/tasks/ci.rake +1 -0
  256. data/tasks/spec.rake +18 -0
  257. data/tasks/yard.rake +9 -0
  258. data/tasks/yardstick.rake +19 -0
  259. metadata +323 -0
@@ -0,0 +1,366 @@
1
+ shared_examples 'An Adapter' do
2
+
3
+ def self.adapter_supports?(*methods)
4
+
5
+ # FIXME: obviously this needs a real fix!
6
+ # --------------------------------------
7
+ # Probably, delaying adapter_supports?
8
+ # to be executed after DataMapper.setup
9
+ # has been called will solve our current
10
+ # problem with described_type() being nil
11
+ # for as long as DataMapper.setup wasn't
12
+ # called
13
+ return true if ENV['ADAPTER_SUPPORTS'] == 'all'
14
+
15
+ methods.all? do |method|
16
+ # TODO: figure out a way to see if the instance method is only inherited
17
+ # from the Abstract Adapter, and not defined in it's class. If that is
18
+ # the case return false
19
+
20
+ # CRUD methods can be inherited from parent class
21
+ described_type.instance_methods.any? { |instance_method| method.to_s == instance_method.to_s }
22
+ end
23
+ end
24
+
25
+ # Hack to detect cases a let(:heffalump_model) is not present
26
+ unless instance_methods.map(&:to_s).include?('heffalump_model')
27
+ # This is the default Heffalump model. You can replace it with your own
28
+ # (using let/let!) # but # be sure the replacement provides the required
29
+ # properties.
30
+ let(:heffalump_model) do
31
+ model = Class.new do
32
+ include DataMapper::Resource
33
+
34
+ property :id, DataMapper::Property::Serial
35
+ property :color, DataMapper::Property::String
36
+ property :num_spots, DataMapper::Property::Integer
37
+ property :striped, DataMapper::Property::Boolean
38
+
39
+ # This is needed for DataMapper.finalize
40
+ def self.name
41
+ 'Heffalump'
42
+ end
43
+ end
44
+
45
+ DataMapper.finalize
46
+
47
+ model
48
+ end
49
+ end
50
+
51
+ before :all do
52
+ raise '+#adapter+ should be defined in a let(:adapter) block' unless respond_to?(:adapter)
53
+ raise '+#repository+ should be defined in a let(:repository) block' unless respond_to?(:repository)
54
+
55
+ DataMapper.finalize
56
+
57
+ # create all tables and constraints before each spec
58
+ if repository.respond_to?(:auto_migrate!)
59
+ heffalump_model.auto_migrate!
60
+ end
61
+ end
62
+
63
+ if adapter_supports?(:create)
64
+ describe '#create' do
65
+ after do
66
+ heffalump_model.destroy
67
+ end
68
+
69
+ it 'does not raise any errors' do
70
+ expect {
71
+ expect(heffalump_model.new(color: 'peach').save).to be(true)
72
+ }.not_to raise_error
73
+ end
74
+
75
+ it 'sets the identity field for the resource' do
76
+ heffalump = heffalump_model.new(color: 'peach')
77
+ expect(heffalump.id).to be_nil
78
+ expect(heffalump.save).to be(true)
79
+ expect(heffalump.id).not_to be_nil
80
+ end
81
+ end
82
+ else
83
+ it 'needs to support #create'
84
+ end
85
+
86
+ if adapter_supports?(:read)
87
+ describe '#read' do
88
+ before :all do
89
+ @heffalump = heffalump_model.create(color: 'brownish hue')
90
+ expect(@heffalump).to be_saved
91
+ @query = heffalump_model.all.query
92
+ end
93
+
94
+ after :all do
95
+ heffalump_model.destroy
96
+ end
97
+
98
+ it 'does not raise any errors' do
99
+ expect {
100
+ heffalump_model.all
101
+ }.not_to raise_error
102
+ end
103
+
104
+ it 'returns expected results' do
105
+ expect(heffalump_model.all).to eq [@heffalump]
106
+ end
107
+ end
108
+ else
109
+ it 'needs to support #read'
110
+ end
111
+
112
+ if adapter_supports?(:update)
113
+ describe '#update' do
114
+ before do
115
+ @heffalump = heffalump_model.create(color: 'peach', num_spots: 1, striped: false)
116
+ expect(@heffalump).to be_saved
117
+ end
118
+
119
+ after do
120
+ heffalump_model.destroy
121
+ end
122
+
123
+ it 'does not raise any errors' do
124
+ expect {
125
+ @heffalump.num_spots = 0
126
+ expect(@heffalump.save).to be(true)
127
+ }.not_to raise_error
128
+ end
129
+
130
+ it 'does not alter the identity field' do
131
+ key = @heffalump.key
132
+ @heffalump.num_spots = 0
133
+ expect(@heffalump.save).to be(true)
134
+ expect(@heffalump.key).to eq key
135
+ end
136
+
137
+ it 'updates altered fields' do
138
+ @heffalump.num_spots = 0
139
+ expect(@heffalump.save).to be(true)
140
+ expect(heffalump_model.get!(*@heffalump.key).num_spots).to be(0)
141
+ end
142
+
143
+ it 'does not alter other fields' do
144
+ num_spots = @heffalump.num_spots
145
+ @heffalump.striped = true
146
+ expect(@heffalump.save).to be(true)
147
+ expect(heffalump_model.get!(*@heffalump.key).num_spots).to be(num_spots)
148
+ end
149
+ end
150
+ else
151
+ it 'needs to support #update'
152
+ end
153
+
154
+ if adapter_supports?(:delete)
155
+ describe '#delete' do
156
+ before do
157
+ @heffalump = heffalump_model.create(color: 'forest green')
158
+ expect(@heffalump).to be_saved
159
+ end
160
+
161
+ after do
162
+ heffalump_model.destroy
163
+ end
164
+
165
+ it 'does not raise any errors' do
166
+ expect {
167
+ @heffalump.destroy
168
+ }.not_to raise_error
169
+ end
170
+
171
+ it 'deletes the requested resource' do
172
+ key = @heffalump.key
173
+ @heffalump.destroy
174
+ expect(heffalump_model.get(*key)).to be_nil
175
+ end
176
+ end
177
+ else
178
+ it 'needs to support #delete'
179
+ end
180
+
181
+ if adapter_supports?(:read, :create)
182
+ describe 'query matching' do
183
+ before :all do
184
+ @red = heffalump_model.create(color: 'red')
185
+ @two = heffalump_model.create(num_spots: 2)
186
+ @five = heffalump_model.create(num_spots: 5)
187
+ [@red, @two, @five].each { |resource| expect(resource).to be_saved }
188
+ end
189
+
190
+ after :all do
191
+ heffalump_model.destroy
192
+ end
193
+
194
+ describe 'conditions' do
195
+ describe 'eql' do
196
+ it 'is able to search for objects included in an inclusive range of values' do
197
+ expect(heffalump_model.all(num_spots: 1..5)).to include(@five)
198
+ end
199
+
200
+ it 'is able to search for objects included in an exclusive range of values' do
201
+ expect(heffalump_model.all(num_spots: 1...6)).to include(@five)
202
+ end
203
+
204
+ it 'is not able to search for values not included in an inclusive range of values' do
205
+ expect(heffalump_model.all(num_spots: 1..4)).not_to include(@five)
206
+ end
207
+
208
+ it 'is not able to search for values not included in an exclusive range of values' do
209
+ expect(heffalump_model.all(num_spots: 1...5)).not_to include(@five)
210
+ end
211
+ end
212
+
213
+ describe 'not' do
214
+ it 'is able to search for objects with not equal value' do
215
+ expect(heffalump_model.all(:color.not => 'red')).not_to include(@red)
216
+ end
217
+
218
+ it 'includes objects that are not like the value' do
219
+ expect(heffalump_model.all(:color.not => 'black')).to include(@red)
220
+ end
221
+
222
+ it 'is able to search for objects with not nil value' do
223
+ expect(heffalump_model.all(:color.not => nil)).to include(@red)
224
+ end
225
+
226
+ it 'does not include objects with a nil value' do
227
+ expect(heffalump_model.all(:color.not => nil)).not_to include(@two)
228
+ end
229
+
230
+ it 'is able to search for object with a nil value using required properties' do
231
+ expect(heffalump_model.all(:id.not => nil)).to eq [@red, @two, @five]
232
+ end
233
+
234
+ it 'is able to search for objects not in an empty list (match all)' do
235
+ expect(heffalump_model.all(:color.not => [])).to eq [@red, @two, @five]
236
+ end
237
+
238
+ it 'is able to search for objects in an empty list and another OR condition (match none on the empty list)' do
239
+ expect(heffalump_model.all(
240
+ conditions: DataMapper::Query::Conditions::Operation.new(
241
+ :or,
242
+ DataMapper::Query::Conditions::Comparison.new(:in, heffalump_model.properties[:color], []),
243
+ DataMapper::Query::Conditions::Comparison.new(:in, heffalump_model.properties[:num_spots], [5])
244
+ )
245
+ )).to eq [@five]
246
+ end
247
+
248
+ it 'is able to search for objects not included in an array of values' do
249
+ expect(heffalump_model.all(:num_spots.not => [1, 3, 5, 7])).to include(@two)
250
+ end
251
+
252
+ it 'is able to search for objects not included in an array of values' do
253
+ expect(heffalump_model.all(:num_spots.not => [1, 3, 5, 7])).not_to include(@five)
254
+ end
255
+
256
+ it 'is able to search for objects not included in an inclusive range of values' do
257
+ expect(heffalump_model.all(:num_spots.not => 1..4)).to include(@five)
258
+ end
259
+
260
+ it 'is able to search for objects not included in an exclusive range of values' do
261
+ expect(heffalump_model.all(:num_spots.not => 1...5)).to include(@five)
262
+ end
263
+
264
+ it 'is not able to search for values not included in an inclusive range of values' do
265
+ expect(heffalump_model.all(:num_spots.not => 1..5)).not_to include(@five)
266
+ end
267
+
268
+ it 'is not able to search for values not included in an exclusive range of values' do
269
+ expect(heffalump_model.all(:num_spots.not => 1...6)).not_to include(@five)
270
+ end
271
+ end
272
+
273
+ describe 'like' do
274
+ it 'is able to search for objects that match value' do
275
+ expect(heffalump_model.all(:color.like => '%ed')).to include(@red)
276
+ end
277
+
278
+ it 'does not search for objects that do not match the value' do
279
+ expect(heffalump_model.all(:color.like => '%blak%')).not_to include(@red)
280
+ end
281
+ end
282
+
283
+ describe 'regexp' do
284
+ before do
285
+ if (defined?(DataMapper::Adapters::SqliteAdapter) && adapter.is_a?(DataMapper::Adapters::SqliteAdapter)) ||
286
+ (defined?(DataMapper::Adapters::SqlserverAdapter) && adapter.is_a?(DataMapper::Adapters::SqlserverAdapter))
287
+ pending 'delegate regexp matches to same system that the InMemory and YAML adapters use'
288
+ end
289
+ end
290
+
291
+ it 'is able to search for objects that match value' do
292
+ expect(heffalump_model.all(color: /ed/)).to include(@red)
293
+ end
294
+
295
+ it 'is not able to search for objects that do not match the value' do
296
+ expect(heffalump_model.all(color: /blak/)).not_to include(@red)
297
+ end
298
+
299
+ it 'is able to do a negated search for objects that match value' do
300
+ expect(heffalump_model.all(:color.not => /blak/)).to include(@red)
301
+ end
302
+
303
+ it 'is not able to do a negated search for objects that do not match value' do
304
+ expect(heffalump_model.all(:color.not => /ed/)).not_to include(@red)
305
+ end
306
+ end
307
+
308
+ describe 'gt' do
309
+ it 'is able to search for objects with value greater than' do
310
+ expect(heffalump_model.all(:num_spots.gt => 1)).to include(@two)
311
+ end
312
+
313
+ it 'does not find objects with a value less than' do
314
+ expect(heffalump_model.all(:num_spots.gt => 3)).not_to include(@two)
315
+ end
316
+ end
317
+
318
+ describe 'gte' do
319
+ it 'is able to search for objects with value greater than' do
320
+ expect(heffalump_model.all(:num_spots.gte => 1)).to include(@two)
321
+ end
322
+
323
+ it 'is able to search for objects with values equal to' do
324
+ expect(heffalump_model.all(:num_spots.gte => 2)).to include(@two)
325
+ end
326
+
327
+ it 'does not find objects with a value less than' do
328
+ expect(heffalump_model.all(:num_spots.gte => 3)).not_to include(@two)
329
+ end
330
+ end
331
+
332
+ describe 'lt' do
333
+ it 'is able to search for objects with value less than' do
334
+ expect(heffalump_model.all(:num_spots.lt => 3)).to include(@two)
335
+ end
336
+
337
+ it 'does not find objects with a value less than' do
338
+ expect(heffalump_model.all(:num_spots.gt => 2)).not_to include(@two)
339
+ end
340
+ end
341
+
342
+ describe 'lte' do
343
+ it 'is able to search for objects with value less than' do
344
+ expect(heffalump_model.all(:num_spots.lte => 3)).to include(@two)
345
+ end
346
+
347
+ it 'is able to search for objects with values equal to' do
348
+ expect(heffalump_model.all(:num_spots.lte => 2)).to include(@two)
349
+ end
350
+
351
+ it 'does not find objects with a value less than' do
352
+ expect(heffalump_model.all(:num_spots.lte => 1)).not_to include(@two)
353
+ end
354
+ end
355
+ end
356
+
357
+ describe 'limits' do
358
+ it 'is able to limit the objects' do
359
+ expect(heffalump_model.all(limit: 2).length).to eq 2
360
+ end
361
+ end
362
+ end
363
+ else
364
+ it 'needs to support #read and #create to test query matching'
365
+ end
366
+ end
@@ -0,0 +1,229 @@
1
+ shared_examples 'A public Property' do
2
+ before :all do
3
+ %w(@type @load_as @name @value @other_value).each do |ivar|
4
+ raise "+#{ivar}+ should be defined in before block" unless instance_variable_defined?(ivar)
5
+ end
6
+
7
+ module ::Blog
8
+ class Article
9
+ include DataMapper::Resource
10
+ property :id, Serial
11
+ end
12
+ end
13
+
14
+ @model = Blog::Article
15
+ @options ||= {}
16
+ end
17
+
18
+ describe 'with a sub-type' do
19
+ before :all do
20
+ class ::SubType < @type; end
21
+ @subtype = ::SubType
22
+ @type.accept_options :foo, :bar
23
+ end
24
+
25
+ before :all do
26
+ @original = @type.accepted_options.dup
27
+ end
28
+
29
+ after :all do
30
+ @type.accepted_options.replace(@original - %i(foo bar))
31
+ end
32
+
33
+ describe 'predefined options' do
34
+ before :all do
35
+ class ::ChildSubType < @subtype
36
+ default nil
37
+ end
38
+ @child_subtype = ChildSubType
39
+ end
40
+
41
+ describe 'when parent type overrides a default' do
42
+ before do
43
+ @subtype.default 'foo'
44
+ end
45
+
46
+ after do
47
+ DataMapper::Property.descendants.delete(ChildSubType)
48
+ Object.send(:remove_const, :ChildSubType)
49
+ end
50
+
51
+ it "does not override the child's type setting" do
52
+ expect(@child_subtype.default).to eql(nil)
53
+ end
54
+ end
55
+ end
56
+
57
+ after :all do
58
+ DataMapper::Property.descendants.delete(SubType)
59
+ Object.send(:remove_const, :SubType)
60
+ end
61
+
62
+ describe '.accept_options' do
63
+ describe 'when provided :foo, :bar' do
64
+ it 'adds new options' do
65
+ [@type, @subtype].each do |type|
66
+ expect(type.accepted_options.include?(:foo)).to be(true)
67
+ expect(type.accepted_options.include?(:bar)).to be(true)
68
+ end
69
+ end
70
+
71
+ it 'creates predefined option setters' do
72
+ [@type, @subtype].each do |type|
73
+ expect(type).to respond_to(:foo)
74
+ expect(type).to respond_to(:bar)
75
+ end
76
+ end
77
+
78
+ describe 'auto-generated option setters' do
79
+ before :all do
80
+ @type.foo true
81
+ @type.bar 1
82
+ @property = @type.new(@model, @name, @options)
83
+ end
84
+
85
+ it 'sets the pre-defined option values' do
86
+ expect(@property.options[:foo]).to eq true
87
+ expect(@property.options[:bar]).to eq 1
88
+ end
89
+
90
+ it 'asks the superclass for the value if unknown' do
91
+ expect(@subtype.foo).to eq true
92
+ expect(@subtype.bar).to eq 1
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '.descendants' do
99
+ it 'includes the sub-type' do
100
+ expect(@type.descendants.include?(SubType)).to be(true)
101
+ end
102
+ end
103
+
104
+ describe '.load_as' do
105
+ it 'returns the load_as' do
106
+ [@type, @subtype].each do |type|
107
+ expect(type.load_as).to be(@load_as)
108
+ end
109
+ end
110
+
111
+ it 'changes the load_as class' do
112
+ @subtype.load_as Object
113
+ expect(@subtype.load_as).to be(Object)
114
+ end
115
+ end
116
+ end
117
+
118
+ %i(allow_blank allow_nil).each do |opt|
119
+ describe "##{method = "#{opt}?"}" do
120
+ [true, false].each do |value|
121
+ describe "when created with :#{opt} => #{value}" do
122
+ before :all do
123
+ @property = @type.new(@model, @name, @options.merge(opt => value))
124
+ end
125
+
126
+ it "returns #{value}" do
127
+ expect(@property.send(method)).to be(value)
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "when created with :#{opt} => true and :required => true" do
133
+ it 'fails with ArgumentError' do
134
+ expect {
135
+ @property = @type.new(@model, @name, @options.merge(opt => true, required: true))
136
+ }.to raise_error(ArgumentError,
137
+ 'options[:required] cannot be mixed with :allow_nil or :allow_blank')
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ %i(key? required? index unique_index unique?).each do |method|
144
+ describe "##{method}" do
145
+ [true, false].each do |value|
146
+ describe "when created with :#{method} => #{value}" do
147
+ before :all do
148
+ opt = method.to_s.chomp('?').to_sym
149
+ @property = @type.new(@model, @name, @options.merge(opt => value))
150
+ end
151
+
152
+ it "returns #{value}" do
153
+ expect(@property.send(method)).to be(value)
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ describe '#lazy?' do
161
+ describe 'when created with :lazy => true, :key => false' do
162
+ before :all do
163
+ @property = @type.new(@model, @name, @options.merge(lazy: true, key: false))
164
+ end
165
+
166
+ it 'returns true' do
167
+ expect(@property.lazy?).to be(true)
168
+ end
169
+ end
170
+
171
+ describe 'when created with :lazy => true, :key => true' do
172
+ before :all do
173
+ @property = @type.new(@model, @name, @options.merge(lazy: true, key: true))
174
+ end
175
+
176
+ it 'returns false' do
177
+ expect(@property.lazy?).to be(false)
178
+ end
179
+ end
180
+ end
181
+
182
+ describe '#instance_of?' do
183
+ subject { property.instance_of?(klass) }
184
+
185
+ let(:property) { @type.new(@model, @name, @options) }
186
+
187
+ context 'when provided the property class' do
188
+ let(:klass) { @type }
189
+
190
+ it { is_expected.to be(true) }
191
+ end
192
+
193
+ context 'when provided the property superclass' do
194
+ let(:klass) { @type.superclass }
195
+
196
+ it { is_expected.to be(false) }
197
+ end
198
+
199
+ context 'when provided the DataMapper::Property class' do
200
+ let(:klass) { DataMapper::Property }
201
+
202
+ it { is_expected.to be(false) }
203
+ end
204
+ end
205
+
206
+ describe '#kind_of?' do
207
+ subject { property.is_a?(klass) }
208
+
209
+ let(:property) { @type.new(@model, @name, @options) }
210
+
211
+ context 'when provided the property class' do
212
+ let(:klass) { @type }
213
+
214
+ it { is_expected.to be(true) }
215
+ end
216
+
217
+ context 'when provided the property superclass' do
218
+ let(:klass) { @type.superclass }
219
+
220
+ it { is_expected.to be(true) }
221
+ end
222
+
223
+ context 'when provided the DataMapper::Property class' do
224
+ let(:klass) { DataMapper::Property }
225
+
226
+ it { is_expected.to be(true) }
227
+ end
228
+ end
229
+ end