lookout-mongo_mapper 0.11.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +33 -0
  3. data/UPGRADES +26 -0
  4. data/bin/mmconsole +59 -0
  5. data/examples/attr_accessible.rb +22 -0
  6. data/examples/attr_protected.rb +22 -0
  7. data/examples/cache_key.rb +24 -0
  8. data/examples/custom_types.rb +24 -0
  9. data/examples/identity_map.rb +33 -0
  10. data/examples/identity_map/automatic.rb +2 -0
  11. data/examples/keys.rb +40 -0
  12. data/examples/modifiers/set.rb +25 -0
  13. data/examples/plugins.rb +38 -0
  14. data/examples/querying.rb +35 -0
  15. data/examples/safe.rb +43 -0
  16. data/examples/scopes.rb +52 -0
  17. data/examples/validating/embedded_docs.rb +29 -0
  18. data/lib/mongo_mapper.rb +94 -0
  19. data/lib/mongo_mapper/connection.rb +96 -0
  20. data/lib/mongo_mapper/document.rb +42 -0
  21. data/lib/mongo_mapper/embedded_document.rb +32 -0
  22. data/lib/mongo_mapper/exceptions.rb +30 -0
  23. data/lib/mongo_mapper/extensions/array.rb +19 -0
  24. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  25. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  26. data/lib/mongo_mapper/extensions/date.rb +25 -0
  27. data/lib/mongo_mapper/extensions/float.rb +14 -0
  28. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  29. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  30. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  31. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  32. data/lib/mongo_mapper/extensions/object.rb +26 -0
  33. data/lib/mongo_mapper/extensions/object_id.rb +32 -0
  34. data/lib/mongo_mapper/extensions/set.rb +20 -0
  35. data/lib/mongo_mapper/extensions/string.rb +18 -0
  36. data/lib/mongo_mapper/extensions/time.rb +28 -0
  37. data/lib/mongo_mapper/locale/en.yml +5 -0
  38. data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
  39. data/lib/mongo_mapper/plugins.rb +22 -0
  40. data/lib/mongo_mapper/plugins/accessible.rb +52 -0
  41. data/lib/mongo_mapper/plugins/active_model.rb +18 -0
  42. data/lib/mongo_mapper/plugins/associations.rb +90 -0
  43. data/lib/mongo_mapper/plugins/associations/base.rb +92 -0
  44. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +54 -0
  45. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +34 -0
  46. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +52 -0
  47. data/lib/mongo_mapper/plugins/associations/collection.rb +27 -0
  48. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +44 -0
  49. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +133 -0
  50. data/lib/mongo_mapper/plugins/associations/many_association.rb +63 -0
  51. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
  52. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +118 -0
  53. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +32 -0
  54. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +24 -0
  55. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +14 -0
  56. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +22 -0
  57. data/lib/mongo_mapper/plugins/associations/one_association.rb +48 -0
  58. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
  59. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +44 -0
  60. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +95 -0
  61. data/lib/mongo_mapper/plugins/associations/proxy.rb +134 -0
  62. data/lib/mongo_mapper/plugins/associations/single_association.rb +46 -0
  63. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  64. data/lib/mongo_mapper/plugins/callbacks.rb +29 -0
  65. data/lib/mongo_mapper/plugins/clone.rb +22 -0
  66. data/lib/mongo_mapper/plugins/dirty.rb +60 -0
  67. data/lib/mongo_mapper/plugins/document.rb +41 -0
  68. data/lib/mongo_mapper/plugins/dynamic_querying.rb +45 -0
  69. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +44 -0
  70. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +56 -0
  71. data/lib/mongo_mapper/plugins/embedded_document.rb +53 -0
  72. data/lib/mongo_mapper/plugins/equality.rb +23 -0
  73. data/lib/mongo_mapper/plugins/identity_map.rb +128 -0
  74. data/lib/mongo_mapper/plugins/indexes.rb +13 -0
  75. data/lib/mongo_mapper/plugins/inspect.rb +16 -0
  76. data/lib/mongo_mapper/plugins/keys.rb +313 -0
  77. data/lib/mongo_mapper/plugins/keys/key.rb +61 -0
  78. data/lib/mongo_mapper/plugins/logger.rb +18 -0
  79. data/lib/mongo_mapper/plugins/modifiers.rb +134 -0
  80. data/lib/mongo_mapper/plugins/pagination.rb +16 -0
  81. data/lib/mongo_mapper/plugins/persistence.rb +69 -0
  82. data/lib/mongo_mapper/plugins/protected.rb +45 -0
  83. data/lib/mongo_mapper/plugins/querying.rb +165 -0
  84. data/lib/mongo_mapper/plugins/querying/decorator.rb +36 -0
  85. data/lib/mongo_mapper/plugins/rails.rb +58 -0
  86. data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
  87. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  88. data/lib/mongo_mapper/plugins/sci.rb +36 -0
  89. data/lib/mongo_mapper/plugins/scopes.rb +27 -0
  90. data/lib/mongo_mapper/plugins/serialization.rb +109 -0
  91. data/lib/mongo_mapper/plugins/timestamps.rb +22 -0
  92. data/lib/mongo_mapper/plugins/touch.rb +18 -0
  93. data/lib/mongo_mapper/plugins/userstamps.rb +18 -0
  94. data/lib/mongo_mapper/plugins/validations.rb +86 -0
  95. data/lib/mongo_mapper/railtie.rb +48 -0
  96. data/lib/mongo_mapper/railtie/database.rake +65 -0
  97. data/lib/mongo_mapper/translation.rb +10 -0
  98. data/lib/mongo_mapper/version.rb +4 -0
  99. data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
  100. data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
  101. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
  102. data/lib/rails/generators/mongo_mapper/model/templates/model.rb +13 -0
  103. data/test/_NOTE_ON_TESTING +1 -0
  104. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +64 -0
  105. data/test/functional/associations/test_belongs_to_proxy.rb +238 -0
  106. data/test/functional/associations/test_in_array_proxy.rb +349 -0
  107. data/test/functional/associations/test_many_documents_as_proxy.rb +231 -0
  108. data/test/functional/associations/test_many_documents_proxy.rb +866 -0
  109. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +239 -0
  110. data/test/functional/associations/test_many_embedded_proxy.rb +289 -0
  111. data/test/functional/associations/test_many_polymorphic_proxy.rb +303 -0
  112. data/test/functional/associations/test_one_as_proxy.rb +491 -0
  113. data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
  114. data/test/functional/associations/test_one_embedded_proxy.rb +100 -0
  115. data/test/functional/associations/test_one_proxy.rb +383 -0
  116. data/test/functional/test_accessible.rb +198 -0
  117. data/test/functional/test_associations.rb +46 -0
  118. data/test/functional/test_binary.rb +27 -0
  119. data/test/functional/test_caching.rb +77 -0
  120. data/test/functional/test_callbacks.rb +232 -0
  121. data/test/functional/test_dirty.rb +301 -0
  122. data/test/functional/test_document.rb +282 -0
  123. data/test/functional/test_dynamic_querying.rb +75 -0
  124. data/test/functional/test_embedded_document.rb +288 -0
  125. data/test/functional/test_equality.rb +20 -0
  126. data/test/functional/test_identity_map.rb +513 -0
  127. data/test/functional/test_indexes.rb +50 -0
  128. data/test/functional/test_logger.rb +20 -0
  129. data/test/functional/test_modifiers.rb +537 -0
  130. data/test/functional/test_pagination.rb +91 -0
  131. data/test/functional/test_protected.rb +201 -0
  132. data/test/functional/test_querying.rb +935 -0
  133. data/test/functional/test_safe.rb +76 -0
  134. data/test/functional/test_sci.rb +240 -0
  135. data/test/functional/test_scopes.rb +171 -0
  136. data/test/functional/test_timestamps.rb +62 -0
  137. data/test/functional/test_touch.rb +125 -0
  138. data/test/functional/test_userstamps.rb +44 -0
  139. data/test/functional/test_validations.rb +414 -0
  140. data/test/models.rb +261 -0
  141. data/test/support/railtie.rb +4 -0
  142. data/test/support/railtie/autoloaded.rb +2 -0
  143. data/test/support/railtie/not_autoloaded.rb +3 -0
  144. data/test/support/railtie/parent.rb +3 -0
  145. data/test/test_active_model_lint.rb +18 -0
  146. data/test/test_helper.rb +93 -0
  147. data/test/unit/associations/test_base.rb +146 -0
  148. data/test/unit/associations/test_belongs_to_association.rb +29 -0
  149. data/test/unit/associations/test_many_association.rb +63 -0
  150. data/test/unit/associations/test_one_association.rb +47 -0
  151. data/test/unit/associations/test_proxy.rb +100 -0
  152. data/test/unit/serializers/test_json_serializer.rb +216 -0
  153. data/test/unit/serializers/test_xml_serializer.rb +196 -0
  154. data/test/unit/test_clone.rb +69 -0
  155. data/test/unit/test_document.rb +249 -0
  156. data/test/unit/test_dynamic_finder.rb +125 -0
  157. data/test/unit/test_embedded_document.rb +682 -0
  158. data/test/unit/test_equality.rb +38 -0
  159. data/test/unit/test_exceptions.rb +12 -0
  160. data/test/unit/test_extensions.rb +380 -0
  161. data/test/unit/test_identity_map_middleware.rb +34 -0
  162. data/test/unit/test_inspect.rb +47 -0
  163. data/test/unit/test_key.rb +205 -0
  164. data/test/unit/test_keys.rb +65 -0
  165. data/test/unit/test_mongo_mapper.rb +143 -0
  166. data/test/unit/test_pagination.rb +11 -0
  167. data/test/unit/test_plugins.rb +89 -0
  168. data/test/unit/test_rails.rb +183 -0
  169. data/test/unit/test_rails_compatibility.rb +38 -0
  170. data/test/unit/test_rails_reflect_on_association.rb +118 -0
  171. data/test/unit/test_railtie.rb +66 -0
  172. data/test/unit/test_serialization.rb +166 -0
  173. data/test/unit/test_time_zones.rb +44 -0
  174. data/test/unit/test_translation.rb +27 -0
  175. data/test/unit/test_validations.rb +562 -0
  176. metadata +285 -0
@@ -0,0 +1,76 @@
1
+ require 'test_helper'
2
+
3
+ class SafeTest < Test::Unit::TestCase
4
+ context "A Document" do
5
+ should "default safe to off" do
6
+ Doc().should_not be_safe
7
+ end
8
+
9
+ should "allow turning safe on" do
10
+ Doc() { safe }.should be_safe
11
+ end
12
+
13
+ context "inherited with safe setting on" do
14
+ should "set subclass safe setting on" do
15
+ inherited = Class.new(Doc() { safe })
16
+ inherited.should be_safe
17
+ end
18
+ end
19
+
20
+ context "inherited with safe setting off" do
21
+ should "leave subclass safe setting off" do
22
+ inherited = Class.new(Doc())
23
+ inherited.should_not be_safe
24
+ end
25
+ end
26
+ end
27
+
28
+ context "A safe document" do
29
+ setup do
30
+ @klass = Doc() do
31
+ safe
32
+ end
33
+ end
34
+ teardown { drop_indexes(@klass) }
35
+
36
+ context "#save" do
37
+ setup do
38
+ @klass.ensure_index :email, :unique => true
39
+ end
40
+
41
+ context "using safe setting from class" do
42
+ should "work fine when all is well" do
43
+ assert_nothing_raised do
44
+ @klass.new(:email => 'john@doe.com').save
45
+ end
46
+ end
47
+
48
+ should "raise error when operation fails" do
49
+ assert_raises(Mongo::OperationFailure) do
50
+ 2.times do
51
+ @klass.new(:email => 'john@doe.com').save
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ context "overriding safe setting" do
58
+ should "raise error if safe is true" do
59
+ assert_raises(Mongo::OperationFailure) do
60
+ 2.times do
61
+ @klass.new(:email => 'john@doe.com').save(:safe => true)
62
+ end
63
+ end
64
+ end
65
+
66
+ should "not raise error if safe is false" do
67
+ assert_nothing_raised do
68
+ 2.times do
69
+ @klass.new(:email => 'john@doe.com').save(:safe => false)
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,240 @@
1
+ require 'test_helper'
2
+
3
+ class SciTest < Test::Unit::TestCase
4
+ context "Single collection inheritance (document)" do
5
+ setup do
6
+ class ::DocParent
7
+ include MongoMapper::Document
8
+ key :name, String
9
+ end
10
+ DocParent.collection.remove
11
+
12
+ class ::DocDaughter < ::DocParent; end
13
+ class ::DocSon < ::DocParent; end
14
+ class ::DocGrandSon < ::DocSon; end
15
+ class ::DocGrandGrandSon < ::DocGrandSon; end
16
+
17
+ DocSon.many :children, :class_name => 'DocGrandSon'
18
+
19
+ @parent = DocParent.new({:name => "Daddy Warbucks"})
20
+ @daughter = DocDaughter.new({:name => "Little Orphan Annie"})
21
+ end
22
+
23
+ teardown do
24
+ Object.send :remove_const, 'DocParent' if defined?(::DocParent)
25
+ Object.send :remove_const, 'DocDaughter' if defined?(::DocDaughter)
26
+ Object.send :remove_const, 'DocSon' if defined?(::DocSon)
27
+ Object.send :remove_const, 'DocGrandSon' if defined?(::DocGrandSon)
28
+ Object.send :remove_const, 'DocGrandGrandSon' if defined?(::DocGrandGrandSon)
29
+ end
30
+
31
+ should "automatically add _type key to store class" do
32
+ DocParent.key?(:_type).should be_true
33
+ end
34
+
35
+ should "use the same collection in the subclass" do
36
+ DocDaughter.collection.name.should == DocParent.collection.name
37
+ end
38
+
39
+ context ".single_collection_inherited?" do
40
+ should "be false if has not inherited" do
41
+ DocParent.should_not be_single_collection_inherited
42
+ end
43
+
44
+ should "be true if inherited" do
45
+ DocDaughter.should be_single_collection_inherited
46
+ DocSon.should be_single_collection_inherited
47
+ DocGrandSon.should be_single_collection_inherited
48
+ end
49
+ end
50
+
51
+ should "set _type on initialize" do
52
+ DocDaughter.new._type.should == 'DocDaughter'
53
+ DocSon.new._type.should == 'DocSon'
54
+ DocGrandSon.new._type.should == 'DocGrandSon'
55
+ end
56
+
57
+ should "set _type based on class and ignore assigned values" do
58
+ DocSon.new(:_type => 'DocDaughter')._type.should == 'DocSon'
59
+ end
60
+
61
+ context "loading" do
62
+ should "be based on _type" do
63
+ @parent.save
64
+ @daughter.save
65
+
66
+ collection = DocParent.all
67
+ collection.size.should == 2
68
+ collection.first.should be_kind_of(DocParent)
69
+ collection.first.name.should == "Daddy Warbucks"
70
+ collection.last.should be_kind_of(DocDaughter)
71
+ collection.last.name.should == "Little Orphan Annie"
72
+ end
73
+
74
+ should "gracefully handle when _type cannot be constantized" do
75
+ doc = DocParent.new(:name => 'Nunes')
76
+ doc._type = 'FoobarBaz'
77
+ doc.save
78
+
79
+ collection = DocParent.all
80
+ collection.last.should == doc
81
+ collection.last.should be_kind_of(DocParent)
82
+ end
83
+ end
84
+
85
+ context "querying" do
86
+ should "find scoped to class" do
87
+ john = DocSon.create(:name => 'John')
88
+ steve = DocSon.create(:name => 'Steve')
89
+ steph = DocDaughter.create(:name => 'Steph')
90
+ carrie = DocDaughter.create(:name => 'Carrie')
91
+ boris = DocGrandSon.create(:name => 'Boris')
92
+
93
+ DocGrandGrandSon.all(:order => 'name').should == []
94
+ DocGrandSon.all(:order => 'name').should == [boris]
95
+ DocSon.all(:order => 'name').should == [boris, john, steve]
96
+ DocDaughter.all(:order => 'name').should == [carrie, steph]
97
+ DocParent.all(:order => 'name').should == [boris, carrie, john, steph, steve]
98
+
99
+ sigmund = DocGrandGrandSon.create(:name => 'Sigmund')
100
+
101
+ DocGrandSon.all(:order => 'name').should == [boris, sigmund]
102
+ DocSon.all(:order => 'name').should == [boris, john, sigmund, steve]
103
+ DocParent.all(:order => 'name').should == [boris, carrie, john, sigmund, steph, steve]
104
+ end
105
+
106
+ should "work with nested hash conditions" do
107
+ john = DocSon.create(:name => 'John')
108
+ steve = DocSon.create(:name => 'Steve')
109
+ DocSon.all(:name => {'$ne' => 'Steve'}).should == [john]
110
+ end
111
+
112
+ should "raise error if not found scoped to class" do
113
+ john = DocSon.create(:name => 'John')
114
+ steph = DocDaughter.create(:name => 'Steph')
115
+
116
+ lambda {
117
+ DocSon.find!(steph._id)
118
+ }.should raise_error(MongoMapper::DocumentNotFound)
119
+ end
120
+
121
+ should "not raise error for find with parent" do
122
+ john = DocSon.create(:name => 'John')
123
+
124
+ DocParent.find!(john._id).should == john
125
+ end
126
+
127
+ should "count scoped to class" do
128
+ john = DocSon.create(:name => 'John')
129
+ steve = DocSon.create(:name => 'Steve')
130
+ steph = DocDaughter.create(:name => 'Steph')
131
+ carrie = DocDaughter.create(:name => 'Carrie')
132
+
133
+ DocGrandSon.count.should == 0
134
+ DocSon.count.should == 2
135
+ DocDaughter.count.should == 2
136
+ DocParent.count.should == 4
137
+ end
138
+
139
+ should "not be able to destroy each other" do
140
+ john = DocSon.create(:name => 'John')
141
+ steph = DocDaughter.create(:name => 'Steph')
142
+
143
+ lambda {
144
+ DocSon.destroy(steph._id)
145
+ }.should raise_error(MongoMapper::DocumentNotFound)
146
+ end
147
+
148
+ should "not be able to delete each other" do
149
+ john = DocSon.create(:name => 'John')
150
+ steph = DocDaughter.create(:name => 'Steph')
151
+
152
+ lambda {
153
+ DocSon.delete(steph._id)
154
+ }.should_not change { DocParent.count }
155
+ end
156
+
157
+ should "be able to destroy using parent" do
158
+ john = DocSon.create(:name => 'John')
159
+ steph = DocDaughter.create(:name => 'Steph')
160
+
161
+ lambda {
162
+ DocParent.destroy_all
163
+ }.should change { DocParent.count }.by(-2)
164
+ end
165
+
166
+ should "be able to delete using parent" do
167
+ john = DocSon.create(:name => 'John')
168
+ steph = DocDaughter.create(:name => 'Steph')
169
+
170
+ lambda {
171
+ DocParent.delete_all
172
+ }.should change { DocParent.count }.by(-2)
173
+ end
174
+ end
175
+
176
+ should "be able to reload single collection inherited parent class" do
177
+ brian = DocParent.create(:name => 'Brian')
178
+ brian.name = 'B-Dawg'
179
+ brian.reload
180
+ brian.name.should == 'Brian'
181
+ end
182
+ end
183
+
184
+ context "Single collection inheritance (embedded document)" do
185
+ setup do
186
+ class ::Grandparent
187
+ include MongoMapper::EmbeddedDocument
188
+ key :grandparent, String
189
+ end
190
+
191
+ class ::Parent < ::Grandparent
192
+ include MongoMapper::EmbeddedDocument
193
+ key :parent, String
194
+ end
195
+
196
+ class ::Child < ::Parent
197
+ include MongoMapper::EmbeddedDocument
198
+ key :child, String
199
+ end
200
+
201
+ class ::OtherChild < ::Parent
202
+ include MongoMapper::EmbeddedDocument
203
+ key :other_child, String
204
+ end
205
+ end
206
+
207
+ teardown do
208
+ Object.send :remove_const, 'Grandparent' if defined?(::Grandparent)
209
+ Object.send :remove_const, 'Parent' if defined?(::Parent)
210
+ Object.send :remove_const, 'Child' if defined?(::Child)
211
+ Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
212
+ end
213
+
214
+ should "automatically add _type key" do
215
+ Grandparent.key?(:_type).should be_true
216
+ end
217
+
218
+ context ".single_collection_inherited?" do
219
+ should "be false if has not inherited" do
220
+ Grandparent.should_not be_single_collection_inherited
221
+ end
222
+
223
+ should "be true if inherited" do
224
+ Parent.should be_single_collection_inherited
225
+ Child.should be_single_collection_inherited
226
+ OtherChild.should be_single_collection_inherited
227
+ end
228
+ end
229
+
230
+ should "set _type on initialize" do
231
+ Parent.new._type.should == 'Parent'
232
+ Child.new._type.should == 'Child'
233
+ OtherChild.new._type.should == 'OtherChild'
234
+ end
235
+
236
+ should "set _type based on class and ignore assigned values" do
237
+ Child.new(:_type => 'OtherChild')._type.should == 'Child'
238
+ end
239
+ end
240
+ end
@@ -0,0 +1,171 @@
1
+ require 'test_helper'
2
+
3
+ class ScopesTest < Test::Unit::TestCase
4
+ context "Scopes" do
5
+ setup 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
+ setup do
15
+ @document.class_eval do
16
+ scope :old, :age.gt => 60
17
+ scope :teens, :age.gte => 13, :age.lte => 19
18
+ end
19
+ end
20
+
21
+ 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
+ should "return a plucky query" do
27
+ @document.old.should be_instance_of(Plucky::Query)
28
+ end
29
+
30
+ 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
+ end
38
+
39
+ context "dynamic scopes" do
40
+ setup do
41
+ @document.class_eval do
42
+ scope :age, lambda { |age| {:age => age} }
43
+ scope :ages, lambda { |low, high| {:age.gte => low, :age.lte => high} }
44
+ scope :ordered, lambda { |sort| sort(sort) }
45
+ end
46
+ end
47
+
48
+ should "work with single argument" do
49
+ @document.create(:name => 'John', :age => 60)
50
+ @document.create(:name => 'Frank', :age => 50)
51
+ docs = @document.age(60).all
52
+ docs.size.should == 1
53
+ docs.first.name.should == 'John'
54
+ end
55
+
56
+ should "work with multiple arguments" do
57
+ @document.create(:name => 'John', :age => 60)
58
+ @document.create(:name => 'Frank', :age => 50)
59
+ @document.create(:name => 'Bill', :age => 40)
60
+ docs = @document.ages(50, 70).all
61
+ docs.size.should == 2
62
+ docs.map(&:name).sort.should == %w(Frank John)
63
+ end
64
+
65
+ should "work with queries" do
66
+ john = @document.create(:name => 'John', :age => 60)
67
+ frank = @document.create(:name => 'Frank', :age => 50)
68
+ bill = @document.create(:name => 'Bill', :age => 40)
69
+ @document.ordered(:age).all.should == [bill, frank, john]
70
+ end
71
+ end
72
+
73
+ context "query scopes" do
74
+ setup do
75
+ @document.class_eval do
76
+ scope :boomers, where(:age.gte => 60).sort(:age)
77
+ end
78
+ end
79
+
80
+ should "work" do
81
+ todd = @document.create(:name => 'Todd', :age => 65)
82
+ john = @document.create(:name => 'John', :age => 60)
83
+ @document.create(:name => 'Frank', :age => 50)
84
+ @document.create(:name => 'Bill', :age => 40)
85
+ docs = @document.boomers.all
86
+ docs[0].should == john
87
+ docs[1].should == todd
88
+ end
89
+ end
90
+
91
+ context "chaining" do
92
+ setup do
93
+ @document.class_eval do
94
+ scope :by_age, lambda { |age| {:age => age} }
95
+ scope :by_name, lambda { |name| {:name => name} }
96
+ end
97
+ end
98
+
99
+ should "work with scope methods" do
100
+ @document.create(:name => 'John', :age => 60)
101
+ @document.create(:name => 'Frank', :age => 60)
102
+ @document.create(:name => 'Bill', :age => 50)
103
+ docs = @document.by_age(60).by_name('John').all
104
+ docs.size.should == 1
105
+ docs.first.name.should == 'John'
106
+ end
107
+
108
+ should "work on query methods" do
109
+ @document.create(:name => 'John', :age => 60)
110
+ @document.create(:name => 'John', :age => 50)
111
+ @document.create(:name => 'Bill', :age => 50)
112
+ docs = @document.where(:name => 'John').by_age(50).all
113
+ docs.size.should == 1
114
+ docs.first.age.should == 50
115
+ end
116
+
117
+ context "with model methods" do
118
+ should "work if method returns a query" do
119
+ @document.create(:name => 'John', :age => 10)
120
+ @document.create(:name => 'John', :age => 20)
121
+ @document.class_eval do
122
+ def self.young
123
+ query(:age.lte => 12)
124
+ end
125
+ end
126
+ docs = @document.by_name('John').young.all
127
+ docs.size.should == 1
128
+ docs.first.age.should == 10
129
+ end
130
+
131
+ should "not work if method does not return a query" do
132
+ @document.class_eval { def self.age; 20 end }
133
+ lambda { @document.by_name('John').age }.should raise_error(NoMethodError)
134
+ end
135
+ end
136
+ end
137
+
138
+ context "with single collection inheritance" do
139
+ setup do
140
+ class ::Item
141
+ include MongoMapper::Document
142
+ scope :by_title, lambda { |title| {:title => title} }
143
+ scope :published, lambda { {:published_at.lte => Time.now.utc} }
144
+
145
+ key :title, String
146
+ key :published_at, Time
147
+ end
148
+ Item.collection.remove
149
+
150
+ class ::Page < ::Item; end
151
+ class ::Blog < ::Item; end
152
+ end
153
+
154
+ teardown do
155
+ Object.send :remove_const, 'Item' if defined?(::Item)
156
+ Object.send :remove_const, 'Page' if defined?(::Page)
157
+ Object.send :remove_const, 'Blog' if defined?(::Blog)
158
+ end
159
+
160
+ should "inherit scopes" do
161
+ Page.scopes.keys.map(&:to_s).sort.should == %w(by_title published)
162
+ end
163
+
164
+ should "work with _type" do
165
+ item = Item.create(:title => 'Home')
166
+ page = Page.create(:title => 'Home')
167
+ Page.by_title('Home').first.should == page
168
+ end
169
+ end
170
+ end
171
+ end