mark_mapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Documents with the Rails plugin" do
4
+ let(:doc) { Doc {
5
+ key :foo, String
6
+ key :long_field, String, :alias => "lf"
7
+ }}
8
+
9
+ context "with values from the DB" do
10
+ subject { doc.create(:foo => "bar", :long_field => "long value") }
11
+ it "should have x_before_type_cast" do
12
+ subject.foo_before_type_cast.should == "bar"
13
+ end
14
+
15
+ it "should have x_before_type_cast for aliased fields" do
16
+ subject.long_field_before_type_cast.should == "long value"
17
+ end
18
+
19
+ it "should honor app-set values over DB-set values" do
20
+ subject.foo = nil
21
+ subject.foo_before_type_cast.should == nil
22
+ end
23
+ end
24
+
25
+ context "when blank" do
26
+ subject { doc.create() }
27
+ it "should have x_before_type_cast" do
28
+ subject.foo_before_type_cast.should == nil
29
+ end
30
+
31
+ it "should honor app-set values over DB-set values" do
32
+ subject.foo = nil
33
+ subject.foo_before_type_cast.should == nil
34
+
35
+ subject.foo = :baz
36
+ subject.foo_before_type_cast.should == :baz
37
+
38
+ subject.save
39
+ subject.reload.foo_before_type_cast.should == "baz"
40
+ end
41
+ end
42
+
43
+ context "#has_one" do
44
+ subject do
45
+ Doc do
46
+ has_one :foo
47
+ end
48
+ end
49
+
50
+ it "should create a one association" do
51
+ subject.associations.should have_key :foo
52
+ subject.associations[:foo].should be_a MarkMapper::Plugins::Associations::OneAssociation
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,374 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Single collection inheritance (document)" do
4
+ # context "without a connection", :without_connection => true do
5
+ # it "should attempt to create a connection during inheritance" do
6
+ # expect(MarkLogic::Connection).to_not receive(:new)
7
+ # doc = Class.new
8
+ # doc.send(:include, MarkMapper::Document)
9
+ # expect {
10
+ # Class.new(doc)
11
+ # }.to_not raise_error
12
+ # end
13
+
14
+ # it "should pick up a connection if one wasn't set" do
15
+ # doc = Class.new
16
+ # doc.send(:include, MarkMapper::Document)
17
+ # klass = Class.new(doc)
18
+ # klass.connection.should be_nil
19
+ # MarkMapper.connection
20
+ # klass.connection.should be_a MarkLogic::Connection
21
+ # end
22
+ # end
23
+
24
+ context "with a connection" do
25
+ before do
26
+ class ::DocParent
27
+ include MarkMapper::Document
28
+ key :name, String
29
+ end
30
+ DocParent.collection.remove
31
+
32
+ class ::DocDaughter < ::DocParent; end
33
+ class ::DocSon < ::DocParent; end
34
+ class ::DocGrandSon < ::DocSon; end
35
+ class ::DocGrandGrandSon < ::DocGrandSon; end
36
+
37
+ DocSon.many :children, :class_name => 'DocGrandSon'
38
+
39
+ @parent = DocParent.new({:name => "Daddy Warbucks"})
40
+ @daughter = DocDaughter.new({:name => "Little Orphan Annie"})
41
+ end
42
+
43
+ after do
44
+ Object.send :remove_const, 'DocParent' if defined?(::DocParent)
45
+ Object.send :remove_const, 'DocDaughter' if defined?(::DocDaughter)
46
+ Object.send :remove_const, 'DocSon' if defined?(::DocSon)
47
+ Object.send :remove_const, 'DocGrandSon' if defined?(::DocGrandSon)
48
+ Object.send :remove_const, 'DocGrandGrandSon' if defined?(::DocGrandGrandSon)
49
+ end
50
+
51
+ it "should automatically add _type key to store class" do
52
+ DocParent.key?(:_type).should be_truthy
53
+ end
54
+
55
+ it "should use the same connection in the subclass" do
56
+ parent_class = Class.new do
57
+ include MarkMapper::Document
58
+ connection MarkLogic::Connection.new(HOST, PORT)
59
+ end
60
+
61
+ child_class = Class.new(parent_class) do
62
+ include MarkMapper::Document
63
+ end
64
+
65
+ child_class.connection.should == child_class.connection
66
+ end
67
+
68
+ it "should use the same database in the subclass" do
69
+ parent_class = Class.new do
70
+ include MarkMapper::Document
71
+ database = MarkMapper.application.content_databases[0]
72
+ end
73
+
74
+ child_class = Class.new(parent_class) do
75
+ include MarkMapper::Document
76
+ end
77
+
78
+ child_class.database.should == MarkMapper.application.content_databases[0]
79
+ end
80
+
81
+ it "should use the same collection in the subclass" do
82
+ DocDaughter.collection.name.should == DocParent.collection.name
83
+ end
84
+
85
+ context "if the subclass changes its collection" do
86
+ before do
87
+ class ::DocSCIOrphan < ::DocParent
88
+ set_collection_name "foobars"
89
+ end
90
+ end
91
+
92
+ after do
93
+ Object.send :remove_const, 'DocSCIOrphan' if defined?(::DocSCIOrphan)
94
+ end
95
+
96
+ it "should negate SCI" do
97
+ DocSCIOrphan.collection.name.should == "foobars"
98
+ DocSCIOrphan.should_not be_single_collection_inherited
99
+ end
100
+
101
+ it "should remove the _type key" do
102
+ DocParent.keys.should_not have_key "_type"
103
+ DocSCIOrphan.keys.should_not have_key "_type"
104
+ end
105
+
106
+ context "and then is subclassed again" do
107
+ before do
108
+ class ::DocSCIOrphanChild < ::DocSCIOrphan
109
+ end
110
+ end
111
+
112
+ after do
113
+ Object.send :remove_const, 'DocSCIOrphanChild' if defined?(::DocSCIOrphanChild)
114
+ end
115
+
116
+ it "should reinstate SCI" do
117
+ DocSCIOrphan.should_not be_single_collection_inherited
118
+ DocSCIOrphanChild.should be_single_collection_inherited
119
+ end
120
+
121
+ it "should have the _type key" do
122
+ DocSCIOrphan.keys.should have_key "_type"
123
+ DocSCIOrphanChild.keys.should have_key "_type"
124
+ end
125
+ end
126
+ end
127
+
128
+ it "should know single_collection_parent" do
129
+ DocParent.single_collection_parent.should be_nil
130
+ DocDaughter.single_collection_parent.should == DocParent
131
+ DocSon.single_collection_parent.should == DocParent
132
+ DocGrandSon.single_collection_parent.should == DocSon
133
+ DocGrandGrandSon.single_collection_parent.should == DocGrandSon
134
+ end
135
+
136
+ it "should know single_collection_root" do
137
+ DocParent.single_collection_root.should == DocParent
138
+ DocDaughter.single_collection_root.should == DocParent
139
+ DocSon.single_collection_root.should == DocParent
140
+ DocGrandSon.single_collection_root.should == DocParent
141
+ DocGrandGrandSon.single_collection_root.should == DocParent
142
+ end
143
+
144
+ context ".single_collection_inherited?" do
145
+ it "should be false if has not inherited" do
146
+ DocParent.should_not be_single_collection_inherited
147
+ end
148
+
149
+ it "should be true if inherited" do
150
+ DocDaughter.should be_single_collection_inherited
151
+ DocSon.should be_single_collection_inherited
152
+ DocGrandSon.should be_single_collection_inherited
153
+ end
154
+ end
155
+
156
+ it "should set _type on initialize" do
157
+ DocDaughter.new._type.should == 'DocDaughter'
158
+ DocSon.new._type.should == 'DocSon'
159
+ DocGrandSon.new._type.should == 'DocGrandSon'
160
+ end
161
+
162
+ it "should set _type based on class and ignore assigned values" do
163
+ DocSon.new(:_type => 'DocDaughter')._type.should == 'DocSon'
164
+ end
165
+
166
+ context "loading" do
167
+ it "should be based on _type" do
168
+ @parent.save
169
+ @daughter.save
170
+
171
+ collection = DocParent.all
172
+ collection.size.should == 2
173
+ collection.first.should be_kind_of(DocParent)
174
+ collection.first.name.should == "Daddy Warbucks"
175
+ collection.last.should be_kind_of(DocDaughter)
176
+ collection.last.name.should == "Little Orphan Annie"
177
+ end
178
+
179
+ it "should gracefully handle when _type cannot be constantized" do
180
+ doc = DocParent.new(:name => 'Nunes')
181
+ doc._type = 'FoobarBaz'
182
+ doc.save
183
+
184
+ collection = DocParent.all
185
+ collection.last.should == doc
186
+ collection.last.should be_kind_of(DocParent)
187
+ end
188
+ end
189
+
190
+ context "querying" do
191
+ it "should find scoped to class" do
192
+ john = DocSon.create(:name => 'John')
193
+ steve = DocSon.create(:name => 'Steve')
194
+ steph = DocDaughter.create(:name => 'Steph')
195
+ carrie = DocDaughter.create(:name => 'Carrie')
196
+ boris = DocGrandSon.create(:name => 'Boris')
197
+
198
+ DocGrandGrandSon.all(:order => 'name').should == []
199
+ DocGrandSon.all(:order => 'name').should == [boris]
200
+ DocSon.all(:order => 'name').should == [boris, john, steve]
201
+ DocDaughter.all(:order => 'name').should == [carrie, steph]
202
+ DocParent.all(:order => 'name').should == [boris, carrie, john, steph, steve]
203
+
204
+ sigmund = DocGrandGrandSon.create(:name => 'Sigmund')
205
+
206
+ DocGrandSon.all(:order => 'name').should == [boris, sigmund]
207
+ DocSon.all(:order => 'name').should == [boris, john, sigmund, steve]
208
+ DocParent.all(:order => 'name').should == [boris, carrie, john, sigmund, steph, steve]
209
+ end
210
+
211
+ it "should work with nested hash conditions" do
212
+ john = DocSon.create(:name => 'John')
213
+ steve = DocSon.create(:name => 'Steve')
214
+ DocSon.all(:name => {'$ne' => 'Steve'}).should == [john]
215
+ end
216
+
217
+ it "should raise error if not found scoped to class" do
218
+ john = DocSon.create(:name => 'John')
219
+ steph = DocDaughter.create(:name => 'Steph')
220
+
221
+ lambda {
222
+ DocSon.find!(steph._id)
223
+ }.should raise_error(MarkMapper::DocumentNotFound)
224
+ end
225
+
226
+ it "should not raise error for find with parent" do
227
+ john = DocSon.create(:name => 'John')
228
+
229
+ DocParent.find!(john._id).should == john
230
+ end
231
+
232
+ it "should count scoped to class" do
233
+ john = DocSon.create(:name => 'John')
234
+ steve = DocSon.create(:name => 'Steve')
235
+ steph = DocDaughter.create(:name => 'Steph')
236
+ carrie = DocDaughter.create(:name => 'Carrie')
237
+
238
+ DocGrandSon.count.should == 0
239
+ DocSon.count.should == 2
240
+ DocDaughter.count.should == 2
241
+ DocParent.count.should == 4
242
+ end
243
+
244
+ it "should not be able to destroy each other" do
245
+ john = DocSon.create(:name => 'John')
246
+ steph = DocDaughter.create(:name => 'Steph')
247
+
248
+ lambda {
249
+ DocSon.destroy(steph._id)
250
+ }.should raise_error(MarkMapper::DocumentNotFound)
251
+ end
252
+
253
+ it "should not be able to delete each other" do
254
+ john = DocSon.create(:name => 'John')
255
+ steph = DocDaughter.create(:name => 'Steph')
256
+
257
+ lambda {
258
+ DocSon.delete(steph._id)
259
+ }.should_not change { DocParent.count }
260
+ end
261
+
262
+ it "should be able to destroy using parent" do
263
+ john = DocSon.create(:name => 'John')
264
+ steph = DocDaughter.create(:name => 'Steph')
265
+
266
+ lambda {
267
+ DocParent.destroy_all
268
+ }.should change { DocParent.count }.by(-2)
269
+ end
270
+
271
+ it "should be able to delete using parent" do
272
+ john = DocSon.create(:name => 'John')
273
+ steph = DocDaughter.create(:name => 'Steph')
274
+
275
+ lambda {
276
+ DocParent.delete_all
277
+ }.should change { DocParent.count }.by(-2)
278
+ end
279
+ end
280
+
281
+ it "should be able to reload single collection inherited parent class" do
282
+ brian = DocParent.create(:name => 'Brian')
283
+ brian.name = 'B-Dawg'
284
+ brian.reload
285
+ brian.name.should == 'Brian'
286
+ end
287
+ end
288
+
289
+ describe "Single collection inheritance (embedded document)" do
290
+ before do
291
+ class ::Grandparent
292
+ include MarkMapper::EmbeddedDocument
293
+ key :grandparent, String
294
+ end
295
+
296
+ class ::Parent < ::Grandparent
297
+ include MarkMapper::EmbeddedDocument
298
+ key :parent, String
299
+ end
300
+
301
+ class ::Child < ::Parent
302
+ include MarkMapper::EmbeddedDocument
303
+ key :child, String
304
+ end
305
+
306
+ class ::OtherChild < ::Parent
307
+ include MarkMapper::EmbeddedDocument
308
+ key :other_child, String
309
+ end
310
+ end
311
+
312
+ after do
313
+ Object.send :remove_const, 'Grandparent' if defined?(::Grandparent)
314
+ Object.send :remove_const, 'Parent' if defined?(::Parent)
315
+ Object.send :remove_const, 'Child' if defined?(::Child)
316
+ Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
317
+ end
318
+
319
+ it "should automatically add _type key" do
320
+ Grandparent.key?(:_type).should be_truthy
321
+ end
322
+
323
+ context ".single_collection_inherited?" do
324
+ it "should be false if has not inherited" do
325
+ Grandparent.should_not be_single_collection_inherited
326
+ end
327
+
328
+ it "should be true if inherited" do
329
+ Parent.should be_single_collection_inherited
330
+ Child.should be_single_collection_inherited
331
+ OtherChild.should be_single_collection_inherited
332
+ end
333
+ end
334
+
335
+ it "should set _type on initialize" do
336
+ Parent.new._type.should == 'Parent'
337
+ Child.new._type.should == 'Child'
338
+ OtherChild.new._type.should == 'OtherChild'
339
+ end
340
+
341
+ it "should set _type based on class and ignore assigned values" do
342
+ Child.new(:_type => 'OtherChild')._type.should == 'Child'
343
+ end
344
+ end
345
+
346
+ describe "With polymorphism" do
347
+ before :all do
348
+ class SciPolymorphicPost
349
+ include MarkMapper::Document
350
+ belongs_to :article_parent, :polymorphic => true
351
+ end
352
+
353
+ class GalleryItem
354
+ include MarkMapper::Document
355
+ belongs_to :gallery_album
356
+ key :text, Hash
357
+ timestamps!
358
+ end
359
+
360
+ class TextGalleryItem < GalleryItem;
361
+ many :sci_polymorphic_posts, :as => :article_parent
362
+ end
363
+ end
364
+
365
+ it "should find polymorphic SCI items" do
366
+ item = TextGalleryItem.new()
367
+ p = SciPolymorphicPost.create(:article_parent => item)
368
+ p.article_parent_id.should be_a MarkLogic::ObjectId
369
+ p.article_parent_type.should == "TextGalleryItem"
370
+
371
+ p.reload.article_parent.sci_polymorphic_posts.all.should include(p)
372
+ end
373
+ end
374
+ end
@@ -0,0 +1,204 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Scopes" do
4
+ context "Scopes" do
5
+ before do
6
+ @document = Doc() do
7
+ key :name, String
8
+ key :age, Integer
9
+ timestamps!
10
+ end
11
+ end
12
+
13
+ context "basic scopes" do
14
+ before do
15
+ @document.class_eval do
16
+ scope :old, :age.gt => 60
17
+ scope :teens, :age.ge => 13, :age.le => 19
18
+ end
19
+ end
20
+
21
+ it "should know what scopes have been added" do
22
+ @document.scopes.size.should == 2
23
+ @document.scopes.keys.map(&:to_s).sort.should == %w(old teens)
24
+ end
25
+
26
+ it "should return a query" do
27
+ @document.old.should be_kind_of(MarkMapper::Query)
28
+ end
29
+
30
+ it "should work" do
31
+ @document.create(:name => 'John', :age => 99)
32
+ @document.create(:name => 'Frank', :age => 15)
33
+ docs = @document.old.all
34
+ docs.size.should == 1
35
+ docs[0].name.should == 'John'
36
+ end
37
+
38
+ # Regression test for #534
39
+ context "when where() is invoked via a scope before a key is defined" do
40
+ let(:given_id) { MarkLogic::ObjectId.new }
41
+ let(:doc) { Doc {
42
+ key :type, String
43
+
44
+ # Ordering is important here; where needs to happen before foo_id is defined
45
+ # in order to produce the behavior we're testing against regression.
46
+ scope :type, where(:type => "bar")
47
+ key :foo_id, ObjectId
48
+ }}
49
+ before {
50
+ doc.collection.drop
51
+ doc.create({:foo_id => given_id})
52
+ }
53
+
54
+ it "should work without typecasts" do
55
+ doc.where(:foo_id => given_id).count.should == 1
56
+ end
57
+
58
+ it "should work with typecasts" do
59
+ doc.where(:foo_id => given_id.to_s).count.should == 1
60
+ end
61
+ end
62
+ end
63
+
64
+ context "dynamic scopes" do
65
+ before do
66
+ @document.class_eval do
67
+ scope :age, lambda { |age| {:age => age} }
68
+ scope :ages, lambda { |low, high| {:age.ge => low, :age.le => high} }
69
+ scope :ordered, lambda { |sort| sort(sort) }
70
+ end
71
+ end
72
+
73
+ it "should work with single argument" do
74
+ @document.create(:name => 'John', :age => 60)
75
+ @document.create(:name => 'Frank', :age => 50)
76
+ docs = @document.age(60).all
77
+ docs.size.should == 1
78
+ docs.first.name.should == 'John'
79
+ end
80
+
81
+ it "should work with multiple arguments" do
82
+ @document.create(:name => 'John', :age => 60)
83
+ @document.create(:name => 'Frank', :age => 50)
84
+ @document.create(:name => 'Bill', :age => 40)
85
+ docs = @document.ages(50, 70).all
86
+ docs.size.should == 2
87
+ docs.map(&:name).sort.should == %w(Frank John)
88
+ end
89
+
90
+ it "should work with queries" do
91
+ john = @document.create(:name => 'John', :age => 60)
92
+ frank = @document.create(:name => 'Frank', :age => 50)
93
+ bill = @document.create(:name => 'Bill', :age => 40)
94
+ @document.ordered(:age).all.should == [bill, frank, john]
95
+ end
96
+ end
97
+
98
+ context "query scopes" do
99
+ before do
100
+ @document.class_eval do
101
+ scope :boomers, where(:age.ge => 60).sort(:age)
102
+ end
103
+ end
104
+
105
+ it "should work" do
106
+ todd = @document.create(:name => 'Todd', :age => 65)
107
+ john = @document.create(:name => 'John', :age => 60)
108
+ @document.create(:name => 'Frank', :age => 50)
109
+ @document.create(:name => 'Bill', :age => 40)
110
+ docs = @document.boomers.all
111
+ docs[0].should == john
112
+ docs[1].should == todd
113
+ end
114
+ end
115
+
116
+ context "chaining" do
117
+ before do
118
+ @document.class_eval do
119
+ scope :by_age, lambda { |age| {:age => age} }
120
+ scope :by_name, lambda { |name| {:name => name} }
121
+ end
122
+ end
123
+
124
+ it "should work with scope methods" do
125
+ @document.create(:name => 'John', :age => 60)
126
+ @document.create(:name => 'Frank', :age => 60)
127
+ @document.create(:name => 'Bill', :age => 50)
128
+ docs = @document.by_age(60).by_name('John').all
129
+ docs.size.should == 1
130
+ docs.first.name.should == 'John'
131
+ end
132
+
133
+ it "should work on query methods" do
134
+ @document.create(:name => 'John', :age => 60)
135
+ @document.create(:name => 'John', :age => 50)
136
+ @document.create(:name => 'Bill', :age => 50)
137
+ docs = @document.where(:name => 'John').by_age(50).all
138
+ docs.size.should == 1
139
+ docs.first.age.should == 50
140
+ end
141
+
142
+ context "with model methods" do
143
+ it "should work if method returns a query" do
144
+ @document.create(:name => 'John', :age => 10)
145
+ @document.create(:name => 'John', :age => 20)
146
+ @document.class_eval do
147
+ def self.young
148
+ query(:age.le => 12)
149
+ end
150
+ end
151
+ docs = @document.by_name('John').young.all
152
+ docs.size.should == 1
153
+ docs.first.age.should == 10
154
+ end
155
+
156
+ it "should not work if method does not return a query" do
157
+ @document.class_eval { def self.age; 20 end }
158
+ @document.by_name('John').age.should == 20
159
+ end
160
+ end
161
+ end
162
+
163
+ context "with single collection inheritance" do
164
+ before do
165
+ class ::Item
166
+ include MarkMapper::Document
167
+ scope :by_title, lambda { |title| {:title => title} }
168
+ scope :published, lambda { {:published_at.le => Time.now.utc} }
169
+
170
+ key :title, String
171
+ key :published_at, Time
172
+ end
173
+ Item.collection.remove
174
+
175
+ class ::Page < ::Item; end
176
+ class ::Blog < ::Item
177
+ key :slug, String
178
+ scope :by_slug, lambda { |slug| {:slug => slug} }
179
+ end
180
+ end
181
+
182
+ after do
183
+ Object.send :remove_const, 'Item' if defined?(::Item)
184
+ Object.send :remove_const, 'Page' if defined?(::Page)
185
+ Object.send :remove_const, 'Blog' if defined?(::Blog)
186
+ end
187
+
188
+ it "should inherit scopes" do
189
+ Page.scopes.keys.map(&:to_s).sort.should == %w(by_title published)
190
+ end
191
+
192
+ it "should work with _type" do
193
+ item = Item.create(:title => 'Home')
194
+ page = Page.create(:title => 'Home')
195
+ Page.by_title('Home').first.should == page
196
+ end
197
+
198
+ it "should limit subclass scopes to subclasses" do
199
+ Item.scopes.keys.map(&:to_s).should =~ %w(by_title published)
200
+ Blog.scopes.keys.map(&:to_s).should =~ %w(by_slug by_title published)
201
+ end
202
+ end
203
+ end
204
+ end