mark_mapper 0.0.1

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 (211) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.rdoc +39 -0
  4. data/examples/attr_accessible.rb +24 -0
  5. data/examples/attr_protected.rb +24 -0
  6. data/examples/cache_key.rb +26 -0
  7. data/examples/custom_types.rb +26 -0
  8. data/examples/identity_map.rb +30 -0
  9. data/examples/identity_map/automatic.rb +2 -0
  10. data/examples/keys.rb +42 -0
  11. data/examples/modifiers/set.rb +27 -0
  12. data/examples/plugins.rb +40 -0
  13. data/examples/querying.rb +39 -0
  14. data/examples/sample_app.rb +43 -0
  15. data/examples/scopes.rb +56 -0
  16. data/examples/validating/embedded_docs.rb +31 -0
  17. data/lib/mark_mapper.rb +125 -0
  18. data/lib/mark_mapper/config.rb +90 -0
  19. data/lib/mark_mapper/connection.rb +60 -0
  20. data/lib/mark_mapper/criteria_hash.rb +194 -0
  21. data/lib/mark_mapper/document.rb +46 -0
  22. data/lib/mark_mapper/embedded_document.rb +32 -0
  23. data/lib/mark_mapper/exceptions.rb +33 -0
  24. data/lib/mark_mapper/extensions/array.rb +27 -0
  25. data/lib/mark_mapper/extensions/boolean.rb +45 -0
  26. data/lib/mark_mapper/extensions/date.rb +29 -0
  27. data/lib/mark_mapper/extensions/duplicable.rb +86 -0
  28. data/lib/mark_mapper/extensions/float.rb +18 -0
  29. data/lib/mark_mapper/extensions/hash.rb +26 -0
  30. data/lib/mark_mapper/extensions/integer.rb +27 -0
  31. data/lib/mark_mapper/extensions/kernel.rb +11 -0
  32. data/lib/mark_mapper/extensions/nil_class.rb +18 -0
  33. data/lib/mark_mapper/extensions/object.rb +30 -0
  34. data/lib/mark_mapper/extensions/object_id.rb +18 -0
  35. data/lib/mark_mapper/extensions/set.rb +20 -0
  36. data/lib/mark_mapper/extensions/string.rb +31 -0
  37. data/lib/mark_mapper/extensions/symbol.rb +87 -0
  38. data/lib/mark_mapper/extensions/time.rb +29 -0
  39. data/lib/mark_mapper/locale/en.yml +5 -0
  40. data/lib/mark_mapper/middleware/identity_map.rb +41 -0
  41. data/lib/mark_mapper/normalizers/criteria_hash_key.rb +17 -0
  42. data/lib/mark_mapper/normalizers/criteria_hash_value.rb +66 -0
  43. data/lib/mark_mapper/normalizers/fields_value.rb +26 -0
  44. data/lib/mark_mapper/normalizers/hash_key.rb +19 -0
  45. data/lib/mark_mapper/normalizers/integer.rb +19 -0
  46. data/lib/mark_mapper/normalizers/options_hash_value.rb +83 -0
  47. data/lib/mark_mapper/normalizers/sort_value.rb +55 -0
  48. data/lib/mark_mapper/options_hash.rb +103 -0
  49. data/lib/mark_mapper/pagination.rb +6 -0
  50. data/lib/mark_mapper/pagination/collection.rb +32 -0
  51. data/lib/mark_mapper/pagination/paginator.rb +46 -0
  52. data/lib/mark_mapper/plugins.rb +22 -0
  53. data/lib/mark_mapper/plugins/accessible.rb +61 -0
  54. data/lib/mark_mapper/plugins/active_model.rb +18 -0
  55. data/lib/mark_mapper/plugins/associations.rb +96 -0
  56. data/lib/mark_mapper/plugins/associations/base.rb +98 -0
  57. data/lib/mark_mapper/plugins/associations/belongs_to_association.rb +63 -0
  58. data/lib/mark_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +35 -0
  59. data/lib/mark_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
  60. data/lib/mark_mapper/plugins/associations/collection.rb +29 -0
  61. data/lib/mark_mapper/plugins/associations/embedded_collection.rb +44 -0
  62. data/lib/mark_mapper/plugins/associations/in_array_proxy.rb +133 -0
  63. data/lib/mark_mapper/plugins/associations/many_association.rb +63 -0
  64. data/lib/mark_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  65. data/lib/mark_mapper/plugins/associations/many_documents_proxy.rb +142 -0
  66. data/lib/mark_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  67. data/lib/mark_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  68. data/lib/mark_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  69. data/lib/mark_mapper/plugins/associations/one_as_proxy.rb +22 -0
  70. data/lib/mark_mapper/plugins/associations/one_association.rb +48 -0
  71. data/lib/mark_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  72. data/lib/mark_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
  73. data/lib/mark_mapper/plugins/associations/one_proxy.rb +95 -0
  74. data/lib/mark_mapper/plugins/associations/proxy.rb +138 -0
  75. data/lib/mark_mapper/plugins/associations/single_association.rb +46 -0
  76. data/lib/mark_mapper/plugins/caching.rb +21 -0
  77. data/lib/mark_mapper/plugins/callbacks.rb +42 -0
  78. data/lib/mark_mapper/plugins/clone.rb +24 -0
  79. data/lib/mark_mapper/plugins/counter_cache.rb +97 -0
  80. data/lib/mark_mapper/plugins/dirty.rb +61 -0
  81. data/lib/mark_mapper/plugins/document.rb +41 -0
  82. data/lib/mark_mapper/plugins/dumpable.rb +22 -0
  83. data/lib/mark_mapper/plugins/dynamic_querying.rb +45 -0
  84. data/lib/mark_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  85. data/lib/mark_mapper/plugins/embedded_callbacks.rb +81 -0
  86. data/lib/mark_mapper/plugins/embedded_document.rb +53 -0
  87. data/lib/mark_mapper/plugins/equality.rb +23 -0
  88. data/lib/mark_mapper/plugins/identity_map.rb +144 -0
  89. data/lib/mark_mapper/plugins/indexable.rb +86 -0
  90. data/lib/mark_mapper/plugins/inspect.rb +16 -0
  91. data/lib/mark_mapper/plugins/keys.rb +470 -0
  92. data/lib/mark_mapper/plugins/keys/key.rb +134 -0
  93. data/lib/mark_mapper/plugins/keys/static.rb +45 -0
  94. data/lib/mark_mapper/plugins/logger.rb +18 -0
  95. data/lib/mark_mapper/plugins/modifiers.rb +140 -0
  96. data/lib/mark_mapper/plugins/pagination.rb +16 -0
  97. data/lib/mark_mapper/plugins/partial_updates.rb +77 -0
  98. data/lib/mark_mapper/plugins/persistence.rb +79 -0
  99. data/lib/mark_mapper/plugins/protected.rb +45 -0
  100. data/lib/mark_mapper/plugins/querying.rb +173 -0
  101. data/lib/mark_mapper/plugins/querying/decorated_markmapper_query.rb +75 -0
  102. data/lib/mark_mapper/plugins/rails.rb +79 -0
  103. data/lib/mark_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  104. data/lib/mark_mapper/plugins/sci.rb +82 -0
  105. data/lib/mark_mapper/plugins/scopes.rb +28 -0
  106. data/lib/mark_mapper/plugins/serialization.rb +109 -0
  107. data/lib/mark_mapper/plugins/timestamps.rb +29 -0
  108. data/lib/mark_mapper/plugins/touch.rb +18 -0
  109. data/lib/mark_mapper/plugins/userstamps.rb +18 -0
  110. data/lib/mark_mapper/plugins/validations.rb +96 -0
  111. data/lib/mark_mapper/query.rb +278 -0
  112. data/lib/mark_mapper/railtie.rb +52 -0
  113. data/lib/mark_mapper/railtie/database.rake +65 -0
  114. data/lib/mark_mapper/translation.rb +10 -0
  115. data/lib/mark_mapper/version.rb +4 -0
  116. data/lib/rails/generators/mark_mapper/config/config_generator.rb +37 -0
  117. data/lib/rails/generators/mark_mapper/config/templates/marklogic.yml +19 -0
  118. data/lib/rails/generators/mark_mapper/model/model_generator.rb +40 -0
  119. data/lib/rails/generators/mark_mapper/model/templates/model.rb +17 -0
  120. data/spec/config/mark_mapper.yml +6 -0
  121. data/spec/examples_spec.rb +25 -0
  122. data/spec/functional/accessible_spec.rb +198 -0
  123. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +64 -0
  124. data/spec/functional/associations/belongs_to_proxy_spec.rb +255 -0
  125. data/spec/functional/associations/in_array_proxy_spec.rb +349 -0
  126. data/spec/functional/associations/many_documents_as_proxy_spec.rb +230 -0
  127. data/spec/functional/associations/many_documents_proxy_spec.rb +968 -0
  128. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +238 -0
  129. data/spec/functional/associations/many_embedded_proxy_spec.rb +288 -0
  130. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +302 -0
  131. data/spec/functional/associations/one_as_proxy_spec.rb +489 -0
  132. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +207 -0
  133. data/spec/functional/associations/one_embedded_proxy_spec.rb +100 -0
  134. data/spec/functional/associations/one_proxy_spec.rb +406 -0
  135. data/spec/functional/associations_spec.rb +48 -0
  136. data/spec/functional/caching_spec.rb +75 -0
  137. data/spec/functional/callbacks_spec.rb +330 -0
  138. data/spec/functional/counter_cache_spec.rb +235 -0
  139. data/spec/functional/dirty_spec.rb +316 -0
  140. data/spec/functional/document_spec.rb +310 -0
  141. data/spec/functional/dumpable_spec.rb +24 -0
  142. data/spec/functional/dynamic_querying_spec.rb +75 -0
  143. data/spec/functional/embedded_document_spec.rb +316 -0
  144. data/spec/functional/equality_spec.rb +20 -0
  145. data/spec/functional/extensions_spec.rb +16 -0
  146. data/spec/functional/identity_map_spec.rb +483 -0
  147. data/spec/functional/keys_spec.rb +339 -0
  148. data/spec/functional/logger_spec.rb +20 -0
  149. data/spec/functional/modifiers_spec.rb +446 -0
  150. data/spec/functional/options_hash_spec.rb +41 -0
  151. data/spec/functional/pagination_spec.rb +89 -0
  152. data/spec/functional/partial_updates_spec.rb +530 -0
  153. data/spec/functional/protected_spec.rb +199 -0
  154. data/spec/functional/querying_spec.rb +984 -0
  155. data/spec/functional/rails_spec.rb +55 -0
  156. data/spec/functional/sci_spec.rb +374 -0
  157. data/spec/functional/scopes_spec.rb +204 -0
  158. data/spec/functional/static_keys_spec.rb +153 -0
  159. data/spec/functional/timestamps_spec.rb +97 -0
  160. data/spec/functional/touch_spec.rb +125 -0
  161. data/spec/functional/userstamps_spec.rb +46 -0
  162. data/spec/functional/validations_spec.rb +416 -0
  163. data/spec/quality_spec.rb +51 -0
  164. data/spec/spec_helper.rb +150 -0
  165. data/spec/support/matchers.rb +15 -0
  166. data/spec/support/models.rb +256 -0
  167. data/spec/symbol_operator_spec.rb +70 -0
  168. data/spec/symbol_spec.rb +9 -0
  169. data/spec/unit/associations/base_spec.rb +146 -0
  170. data/spec/unit/associations/belongs_to_association_spec.rb +30 -0
  171. data/spec/unit/associations/many_association_spec.rb +64 -0
  172. data/spec/unit/associations/one_association_spec.rb +48 -0
  173. data/spec/unit/associations/proxy_spec.rb +103 -0
  174. data/spec/unit/clone_spec.rb +79 -0
  175. data/spec/unit/config_generator_spec.rb +24 -0
  176. data/spec/unit/criteria_hash_spec.rb +218 -0
  177. data/spec/unit/document_spec.rb +251 -0
  178. data/spec/unit/dynamic_finder_spec.rb +125 -0
  179. data/spec/unit/embedded_document_spec.rb +676 -0
  180. data/spec/unit/equality_spec.rb +38 -0
  181. data/spec/unit/exceptions_spec.rb +12 -0
  182. data/spec/unit/extensions_spec.rb +368 -0
  183. data/spec/unit/identity_map_middleware_spec.rb +134 -0
  184. data/spec/unit/inspect_spec.rb +47 -0
  185. data/spec/unit/key_spec.rb +276 -0
  186. data/spec/unit/keys_spec.rb +155 -0
  187. data/spec/unit/mark_mapper_spec.rb +37 -0
  188. data/spec/unit/model_generator_spec.rb +45 -0
  189. data/spec/unit/normalizers/criteria_hash_key_spec.rb +37 -0
  190. data/spec/unit/normalizers/criteria_hash_value_spec.rb +200 -0
  191. data/spec/unit/normalizers/fields_value_spec.rb +45 -0
  192. data/spec/unit/normalizers/hash_key_spec.rb +15 -0
  193. data/spec/unit/normalizers/integer_spec.rb +24 -0
  194. data/spec/unit/normalizers/options_hash_value_spec.rb +99 -0
  195. data/spec/unit/normalizers/sort_value_spec.rb +98 -0
  196. data/spec/unit/options_hash_spec.rb +64 -0
  197. data/spec/unit/pagination/collection_spec.rb +30 -0
  198. data/spec/unit/pagination/paginator_spec.rb +118 -0
  199. data/spec/unit/pagination_spec.rb +11 -0
  200. data/spec/unit/plugins_spec.rb +89 -0
  201. data/spec/unit/query_spec.rb +837 -0
  202. data/spec/unit/rails_compatibility_spec.rb +40 -0
  203. data/spec/unit/rails_reflect_on_association_spec.rb +118 -0
  204. data/spec/unit/rails_spec.rb +188 -0
  205. data/spec/unit/serialization_spec.rb +169 -0
  206. data/spec/unit/serializers/json_serializer_spec.rb +218 -0
  207. data/spec/unit/serializers/xml_serializer_spec.rb +198 -0
  208. data/spec/unit/time_zones_spec.rb +44 -0
  209. data/spec/unit/translation_spec.rb +27 -0
  210. data/spec/unit/validations_spec.rb +588 -0
  211. metadata +307 -0
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Equality" do
4
+ context "Case equality" do
5
+ before do
6
+ @person = Doc()
7
+ @address = Doc()
8
+
9
+ @person.one :address, :class => @address, :foreign_key => :person_id
10
+ @address.belongs_to :person, :class => @person
11
+ end
12
+
13
+ it "should work with proxies" do
14
+ person = @person.create!
15
+ address = @address.create!(:person => person)
16
+ @person.should === address.person
17
+ @address.should === person.address
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Core Extensions" do
4
+ describe "Time" do
5
+ let(:doc) do
6
+ Doc do
7
+ key :created_at, Time
8
+ end
9
+ end
10
+
11
+ it "should match the precision of Time types stored in the database" do
12
+ d = doc.create(:created_at => Time.now)
13
+ d.created_at.to_s.should == d.reload.created_at.to_s
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,483 @@
1
+ require 'spec_helper'
2
+
3
+ describe "IdentityMap" do
4
+ def assert_in_map(*resources)
5
+ [resources].flatten.each do |resource|
6
+ MarkMapper::Plugins::IdentityMap.include?(resource).should be_truthy
7
+ end
8
+ end
9
+
10
+ def assert_not_in_map(*resources)
11
+ [resources].flatten.each do |resource|
12
+ MarkMapper::Plugins::IdentityMap.include?(resource).should be_falsey
13
+ end
14
+ end
15
+
16
+ def expect_no_queries
17
+ expect_any_instance_of(MarkLogic::Collection).to receive(:find_one).never
18
+ expect_any_instance_of(MarkLogic::Collection).to receive(:find).never
19
+ end
20
+
21
+ def expects_one_query
22
+ expect_any_instance_of(MarkLogic::Collection).to receive(:find_one).once.and_return({})
23
+ end
24
+
25
+ def clear_identity_map
26
+ MarkMapper::Plugins::IdentityMap.clear
27
+ end
28
+
29
+ it "should default identity map to off" do
30
+ MarkMapper::Plugins::IdentityMap.enabled?.should be_falsey
31
+ end
32
+
33
+ context "Document" do
34
+ before do
35
+ @original_identity_map_enabled = MarkMapper::Plugins::IdentityMap.enabled
36
+ MarkMapper::Plugins::IdentityMap.enabled = true
37
+
38
+ @person_class = Doc('Person') do
39
+ key :name, String
40
+ end
41
+
42
+ @post_class = Doc('Post') do
43
+ key :title, String
44
+ key :person_id, ObjectId
45
+ end
46
+
47
+ @post_class.belongs_to :person, :class => @person_class
48
+ @person_class.many :posts, :class => @post_class
49
+
50
+ clear_identity_map
51
+ end
52
+
53
+ after do
54
+ MarkMapper::Plugins::IdentityMap.enabled = @original_identity_map_enabled
55
+ end
56
+
57
+ it "should be able to clear the map of all models" do
58
+ person = @person_class.create(:name => 'John')
59
+ post = @post_class.create(:title => 'IM 4eva')
60
+
61
+ assert_in_map(person, post)
62
+ clear_identity_map
63
+ assert_not_in_map(person, post)
64
+
65
+ MarkMapper::Plugins::IdentityMap.repository.should be_empty
66
+ end
67
+
68
+ context ".use" do
69
+ before do
70
+ @person = @person_class.create
71
+ clear_identity_map
72
+ end
73
+
74
+ it "should use the identity map" do
75
+ MarkMapper::Plugins::IdentityMap.enabled = false
76
+ MarkMapper::Plugins::IdentityMap.use do
77
+ @person_class.find(@person.id).should equal(@person_class.find(@person.id))
78
+ end
79
+ end
80
+
81
+ it "should clear the map" do
82
+ MarkMapper::Plugins::IdentityMap.enabled = false
83
+ MarkMapper::Plugins::IdentityMap.repository['hello'] = 'world'
84
+ MarkMapper::Plugins::IdentityMap.use do
85
+ @person_class.find(@person.id)
86
+ end
87
+ MarkMapper::Plugins::IdentityMap.repository.empty?.should be_truthy
88
+ end
89
+
90
+ it "should set enabled back to original status" do
91
+ MarkMapper::Plugins::IdentityMap.enabled = false
92
+ MarkMapper::Plugins::IdentityMap.enabled?.should be_falsey
93
+ MarkMapper::Plugins::IdentityMap.use do
94
+ MarkMapper::Plugins::IdentityMap.enabled?.should be_truthy
95
+ end
96
+ MarkMapper::Plugins::IdentityMap.enabled?.should be_falsey
97
+ end
98
+ end
99
+
100
+ context ".without" do
101
+ before do
102
+ @person = @person_class.create
103
+ clear_identity_map
104
+ end
105
+
106
+ it "should skip the map" do
107
+ MarkMapper::Plugins::IdentityMap.without do
108
+ @person_class.find(@person.id).should_not equal(@person_class.find(@person.id))
109
+ end
110
+ end
111
+
112
+ it "should set enabled back to original value" do
113
+ MarkMapper::Plugins::IdentityMap.enabled = true
114
+ MarkMapper::Plugins::IdentityMap.enabled?.should be_truthy
115
+ MarkMapper::Plugins::IdentityMap.without do
116
+ MarkMapper::Plugins::IdentityMap.enabled?.should be_falsey
117
+ end
118
+ MarkMapper::Plugins::IdentityMap.enabled?.should be_truthy
119
+ end
120
+ end
121
+
122
+ it "should default identity map to hash" do
123
+ MarkMapper::Plugins::IdentityMap.repository.should == {}
124
+ end
125
+
126
+ it "should add key to map when saved" do
127
+ person = @person_class.new
128
+ assert_not_in_map(person)
129
+ person.save.should be_truthy
130
+ assert_in_map(person)
131
+ end
132
+
133
+ it "should allow saving with options" do
134
+ person = @person_class.new
135
+ assert_not_in_map(person)
136
+ person.save(:validate => false).should be_truthy
137
+ assert_in_map(person)
138
+ end
139
+
140
+ it "should remove key from map when deleted" do
141
+ person = @person_class.create(:name => 'Fred')
142
+ assert_in_map(person)
143
+ person.delete
144
+ assert_not_in_map(person)
145
+ end
146
+
147
+ it "should remove key from map when destroyed" do
148
+ person = @person_class.create(:name => 'Fred')
149
+ assert_in_map(person)
150
+ person.destroy
151
+ assert_not_in_map(person)
152
+ end
153
+
154
+ context "#reload" do
155
+ before do
156
+ @person = @person_class.create(:name => 'Fred')
157
+ end
158
+
159
+ it "should re-query the object" do
160
+ assert_in_map(@person)
161
+ expects_one_query
162
+ @person.reload
163
+ end
164
+ end
165
+
166
+ context "#load" do
167
+ before do
168
+ @id = MarkLogic::ObjectId.new
169
+ end
170
+
171
+ it "should add document to map" do
172
+ loaded = @person_class.load('_id' => @id, 'name' => 'Frank')
173
+ assert_in_map(loaded)
174
+ end
175
+
176
+ it "should return document if already in map" do
177
+ first_load = @person_class.load('_id' => @id, 'name' => 'Frank')
178
+ second_load = @person_class.load('_id' => @id, 'name' => 'Frank')
179
+ first_load.should equal(second_load)
180
+ end
181
+
182
+ it "should allow passing with_cast" do
183
+ person_with_time_class = Doc('PersonWithTime') do
184
+ key :name, String
185
+ key :created_at, Time
186
+ end
187
+
188
+ expect do
189
+ loaded = person_with_time_class.load({'_id' => @id, 'name' => 'Frank', 'created_at' => '2014-12-07T20:36:45.529-08:00'}, true)
190
+ loaded.should be_present
191
+ loaded.created_at.should be_an_instance_of(Time)
192
+ end.to_not raise_error
193
+ end
194
+ end
195
+
196
+ context "#find (with one id)" do
197
+ it "should return nil if not found " do
198
+ @person_class.find(1234).should be_nil
199
+ end
200
+
201
+ context "for object not in map" do
202
+ before do
203
+ @person = @person_class.create(:name => 'Fred')
204
+ clear_identity_map
205
+ end
206
+
207
+ it "should query the database" do
208
+ expects_one_query
209
+ @person_class.find(@person.id)
210
+ end
211
+
212
+ it "should add object to map" do
213
+ assert_not_in_map(@person)
214
+ found_person = @person_class.find(@person.id)
215
+ assert_in_map(found_person)
216
+ end
217
+ end
218
+
219
+ context "for object in map" do
220
+ before do
221
+ @person = @person_class.create(:name => 'Fred')
222
+ end
223
+
224
+ it "should not query database" do
225
+ expect_no_queries
226
+ @person_class.find(@person.id)
227
+ end
228
+
229
+ it "should return exact object" do
230
+ assert_in_map(@person)
231
+ found_person = @person_class.find(@person.id)
232
+ found_person.should equal(@person)
233
+ end
234
+ end
235
+ end
236
+
237
+ context "#find (with one id and options)" do
238
+ before do
239
+ @person = @person_class.create(:name => 'Fred')
240
+ @post1 = @person.posts.create(:title => 'I Love MarkLogic')
241
+ @post2 = @person.posts.create(:title => 'Migrations Suck!')
242
+ end
243
+
244
+ # There are times when even though the id matches, other criteria doesn't
245
+ # so we need to do the query to ensure that when criteria doesn't match
246
+ # the document is in fact not found.
247
+ #
248
+ # I'm open to not making this query if someone can figure out reliable
249
+ # way to check if document matches criteria without querying.
250
+ it "should query the database" do
251
+ assert_in_map(@post1)
252
+ expects_one_query
253
+ @person.posts.find(@post1.id)
254
+ end
255
+
256
+ it "should return exact object" do
257
+ assert_in_map(@post1)
258
+ post = @person.posts.find(@post1.id)
259
+ post.should equal(@post1)
260
+ end
261
+
262
+ it "should return nil if not found " do
263
+ @person.posts.find(1234).should be_nil
264
+ end
265
+ end
266
+
267
+ context "#find (with multiple ids)" do
268
+ it "should add all documents to map" do
269
+ person1 = @person_class.create(:name => 'Fred')
270
+ person2 = @person_class.create(:name => 'Bill')
271
+ person3 = @person_class.create(:name => 'Jesse')
272
+ clear_identity_map
273
+
274
+ people = @person_class.find(person1.id, person2.id, person3.id)
275
+ assert_in_map(people)
276
+ end
277
+
278
+ it "should add missing documents to map and return existing ones" do
279
+ person1 = @person_class.create(:name => 'Fred')
280
+ clear_identity_map
281
+ person2 = @person_class.create(:name => 'Bill')
282
+ person3 = @person_class.create(:name => 'Jesse')
283
+
284
+ assert_not_in_map(person1)
285
+ assert_in_map(person2, person3)
286
+
287
+ people = @person_class.find(person1.id, person2.id, person3.id)
288
+
289
+ assert_in_map(people.first) # making sure one that wasn't mapped now is
290
+ assert_in_map(person2, person3)
291
+ end
292
+ end
293
+
294
+ context "#first" do
295
+ context "for object not in map" do
296
+ before do
297
+ @person = @person_class.create(:name => 'Fred')
298
+ clear_identity_map
299
+ end
300
+
301
+ it "should query the database" do
302
+ expects_one_query
303
+ @person_class.first(:_id => @person.id)
304
+ end
305
+
306
+ it "should add object to map" do
307
+ assert_not_in_map(@person)
308
+ found_person = @person_class.first(:_id => @person.id)
309
+ assert_in_map(found_person)
310
+ end
311
+
312
+ it "should return nil if not found" do
313
+ @person_class.first(:name => 'Bill').should be_nil
314
+ end
315
+ end
316
+
317
+ context "for object in map" do
318
+ before do
319
+ @person = @person_class.create(:name => 'Fred')
320
+ end
321
+
322
+ it "should not query database" do
323
+ expect_no_queries
324
+ @person_class.first(:_id => @person.id)
325
+ end
326
+
327
+ it "should return exact object" do
328
+ assert_in_map(@person)
329
+ found_person = @person_class.first(:_id => @person.id)
330
+ found_person.should equal(@person)
331
+ end
332
+ end
333
+ end
334
+
335
+ context "#all" do
336
+ it "should add all documents to map" do
337
+ person1 = @person_class.create(:name => 'Fred')
338
+ person2 = @person_class.create(:name => 'Bill')
339
+ person3 = @person_class.create(:name => 'Jesse')
340
+ clear_identity_map
341
+
342
+ people = @person_class.all(:_id => [person1.id, person2.id, person3.id])
343
+ assert_in_map(people)
344
+ end
345
+
346
+ it "should add missing documents to map and return existing ones" do
347
+ person1 = @person_class.create(:name => 'Fred')
348
+ clear_identity_map
349
+ person2 = @person_class.create(:name => 'Bill')
350
+ person3 = @person_class.create(:name => 'Jesse')
351
+
352
+ assert_not_in_map(person1)
353
+ assert_in_map(person2, person3)
354
+
355
+ people = @person_class.all(:_id => [person1.id, person2.id, person3.id])
356
+ # people.first is making sure one that wasn't mapped now is
357
+ assert_in_map(people.first, person2, person3)
358
+ end
359
+ end
360
+
361
+ context "#find_by_id" do
362
+ before do
363
+ @person = @person_class.create(:name => 'Bill')
364
+ end
365
+
366
+ it "should return nil for document id not found in collection" do
367
+ assert_in_map(@person)
368
+ @person_class.find_by_id(MarkLogic::ObjectId.new).should be_nil
369
+ end
370
+ end
371
+
372
+ context "#remove_documents_from_map" do
373
+ before do
374
+ @person = @person_class.create(:name => 'Fred')
375
+ end
376
+
377
+ it "should remove documents from the map" do
378
+ assert_in_map @person
379
+ @person_class.remove_documents_from_map(@person)
380
+ assert_not_in_map @person
381
+ end
382
+ end
383
+
384
+ context "querying and selecting certain fields" do
385
+ before do
386
+ @person = @person_class.create(:name => 'Bill')
387
+ clear_identity_map
388
+ end
389
+
390
+ it "should not add to map" do
391
+ assert_not_in_map(@person)
392
+ @person_class.first(:_id => @person.id, :select => 'name').should == @person
393
+ @person_class.first(:_id => @person.id, 'fields' => ['name']).should == @person
394
+ @person_class.last(:_id => @person.id, :select => 'name', :order => 'name').should == @person
395
+ @person_class.fields(:name).find(@person.id).should == @person
396
+ @person_class.all(:_id => @person.id, :select => 'name').should == [@person]
397
+ assert_not_in_map(@person)
398
+ end
399
+
400
+ it "should not add to map using where and each" do
401
+ @person_class.where(:id => @person.id).each{|_|}
402
+ assert_in_map(@person)
403
+ @person_class.where(:id => @person.id).only(:id).each{|_|}
404
+ assert_not_in_map(@person)
405
+ end
406
+
407
+ it "should return nil if not found" do
408
+ @person_class.fields(:name).find(MarkLogic::ObjectId.new).should be_nil
409
+ end
410
+ end
411
+
412
+ context "single collection inherited models" do
413
+ before do
414
+ class ::Item
415
+ include MarkMapper::Document
416
+
417
+ key :title, String
418
+ key :parent_id, ObjectId
419
+
420
+ belongs_to :parent, :class_name => 'Item'
421
+ one :blog, :class_name => 'Blog', :foreign_key => 'parent_id'
422
+ end
423
+ Item.collection.remove
424
+
425
+ class ::Blog < ::Item; end
426
+
427
+ class ::BlogPost < ::Item
428
+ key :blog_id, ObjectId
429
+ belongs_to :blog
430
+ end
431
+ end
432
+
433
+ after do
434
+ Object.send :remove_const, 'Item' if defined?(::Item)
435
+ Object.send :remove_const, 'Blog' if defined?(::Blog)
436
+ Object.send :remove_const, 'BlogPost' if defined?(::BlogPost)
437
+ end
438
+
439
+ it "should not query when finding by _id and _type" do
440
+ blog = Blog.create(:title => 'Blog')
441
+ post = BlogPost.create(:title => 'MarkLogic Rocks', :blog => blog)
442
+ clear_identity_map
443
+
444
+ blog = Item.find(blog.id)
445
+ post = Item.find(post.id)
446
+ assert_in_map(blog, post)
447
+
448
+ expect_no_queries
449
+ post.blog
450
+ Blog.find(blog.id)
451
+ end
452
+
453
+ it "should load from map when using parent collection inherited class" do
454
+ blog = Blog.create(:title => 'Jill')
455
+ Item.find(blog.id).should equal(blog)
456
+ end
457
+
458
+ it "should work correctly with belongs to proxy" do
459
+ root = Item.create(:title => 'Root')
460
+ assert_in_map(root)
461
+
462
+ blog = Blog.create(:title => 'Jill', :parent => root)
463
+ assert_in_map(blog)
464
+ root.should equal(blog.parent.target)
465
+ end
466
+
467
+ it "should work correctly with one proxy" do
468
+ blog = Blog.create(:title => 'Jill')
469
+ assert_in_map(blog)
470
+
471
+ root = Item.create(:title => 'Root', :blog => blog)
472
+ assert_in_map(root)
473
+ blog.should equal(root.blog.target)
474
+ end
475
+
476
+ it "should work correctly with one proxy create" do
477
+ root = Item.create(:title => 'Root')
478
+ blog = root.create_blog(:title => 'Blog')
479
+ blog.parent.should equal(root)
480
+ end
481
+ end
482
+ end
483
+ end