mongo_mapper 0.7.6 → 0.8.0

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 (134) hide show
  1. data/README.rdoc +4 -8
  2. data/bin/mmconsole +1 -1
  3. data/examples/keys.rb +37 -0
  4. data/examples/plugins.rb +41 -0
  5. data/examples/querying.rb +35 -0
  6. data/examples/scopes.rb +52 -0
  7. data/lib/mongo_mapper.rb +77 -97
  8. data/lib/mongo_mapper/connection.rb +83 -0
  9. data/lib/mongo_mapper/document.rb +10 -252
  10. data/lib/mongo_mapper/embedded_document.rb +7 -46
  11. data/lib/mongo_mapper/exceptions.rb +30 -0
  12. data/lib/mongo_mapper/extensions/array.rb +19 -0
  13. data/lib/mongo_mapper/extensions/binary.rb +22 -0
  14. data/lib/mongo_mapper/extensions/boolean.rb +44 -0
  15. data/lib/mongo_mapper/extensions/date.rb +25 -0
  16. data/lib/mongo_mapper/extensions/float.rb +14 -0
  17. data/lib/mongo_mapper/extensions/hash.rb +14 -0
  18. data/lib/mongo_mapper/extensions/integer.rb +19 -0
  19. data/lib/mongo_mapper/extensions/kernel.rb +9 -0
  20. data/lib/mongo_mapper/extensions/nil_class.rb +18 -0
  21. data/lib/mongo_mapper/extensions/object.rb +27 -0
  22. data/lib/mongo_mapper/extensions/object_id.rb +30 -0
  23. data/lib/mongo_mapper/extensions/set.rb +20 -0
  24. data/lib/mongo_mapper/extensions/string.rb +18 -0
  25. data/lib/mongo_mapper/extensions/time.rb +29 -0
  26. data/lib/mongo_mapper/plugins.rb +1 -21
  27. data/lib/mongo_mapper/plugins/accessible.rb +44 -0
  28. data/lib/mongo_mapper/plugins/associations.rb +7 -24
  29. data/lib/mongo_mapper/plugins/associations/base.rb +1 -0
  30. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +5 -6
  31. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +5 -6
  32. data/lib/mongo_mapper/plugins/associations/collection.rb +1 -0
  33. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +2 -1
  34. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +22 -39
  35. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +4 -4
  36. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +22 -23
  37. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +1 -0
  38. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +1 -0
  39. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +1 -0
  40. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +2 -3
  41. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +6 -7
  42. data/lib/mongo_mapper/plugins/associations/proxy.rb +8 -6
  43. data/lib/mongo_mapper/plugins/caching.rb +21 -0
  44. data/lib/mongo_mapper/plugins/callbacks.rb +4 -3
  45. data/lib/mongo_mapper/plugins/clone.rb +10 -4
  46. data/lib/mongo_mapper/plugins/descendants.rb +1 -0
  47. data/lib/mongo_mapper/plugins/dirty.rb +1 -0
  48. data/lib/mongo_mapper/plugins/document.rb +41 -0
  49. data/lib/mongo_mapper/plugins/dynamic_querying.rb +41 -0
  50. data/lib/mongo_mapper/{support/find.rb → plugins/dynamic_querying/dynamic_finder.rb} +3 -36
  51. data/lib/mongo_mapper/plugins/embedded_document.rb +49 -0
  52. data/lib/mongo_mapper/plugins/equality.rb +3 -9
  53. data/lib/mongo_mapper/plugins/identity_map.rb +8 -10
  54. data/lib/mongo_mapper/plugins/indexes.rb +12 -0
  55. data/lib/mongo_mapper/plugins/inspect.rb +1 -0
  56. data/lib/mongo_mapper/plugins/keys.rb +15 -27
  57. data/lib/mongo_mapper/plugins/keys/key.rb +14 -3
  58. data/lib/mongo_mapper/plugins/logger.rb +1 -0
  59. data/lib/mongo_mapper/plugins/modifiers.rb +3 -2
  60. data/lib/mongo_mapper/plugins/pagination.rb +5 -15
  61. data/lib/mongo_mapper/plugins/persistence.rb +12 -11
  62. data/lib/mongo_mapper/plugins/protected.rb +8 -0
  63. data/lib/mongo_mapper/plugins/querying.rb +236 -0
  64. data/lib/mongo_mapper/plugins/querying/decorator.rb +46 -0
  65. data/lib/mongo_mapper/plugins/rails.rb +1 -0
  66. data/lib/mongo_mapper/plugins/safe.rb +28 -0
  67. data/lib/mongo_mapper/plugins/sci.rb +32 -0
  68. data/lib/mongo_mapper/plugins/scopes.rb +21 -0
  69. data/lib/mongo_mapper/plugins/serialization.rb +1 -0
  70. data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
  71. data/lib/mongo_mapper/plugins/userstamps.rb +1 -0
  72. data/lib/mongo_mapper/plugins/validations.rb +5 -1
  73. data/lib/mongo_mapper/support/descendant_appends.rb +5 -6
  74. data/lib/mongo_mapper/version.rb +2 -1
  75. data/test/NOTE_ON_TESTING +1 -0
  76. data/test/active_model_lint_test.rb +13 -0
  77. data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +63 -0
  78. data/test/functional/associations/test_belongs_to_proxy.rb +93 -0
  79. data/test/functional/associations/test_in_array_proxy.rb +319 -0
  80. data/test/functional/associations/test_many_documents_as_proxy.rb +229 -0
  81. data/test/functional/associations/test_many_documents_proxy.rb +536 -0
  82. data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +176 -0
  83. data/test/functional/associations/test_many_embedded_proxy.rb +256 -0
  84. data/test/functional/associations/test_many_polymorphic_proxy.rb +302 -0
  85. data/test/functional/associations/test_one_embedded_proxy.rb +58 -0
  86. data/test/functional/associations/test_one_proxy.rb +182 -0
  87. data/test/functional/test_accessible.rb +168 -0
  88. data/test/functional/test_associations.rb +44 -0
  89. data/test/functional/test_binary.rb +27 -0
  90. data/test/functional/test_caching.rb +76 -0
  91. data/test/functional/test_callbacks.rb +151 -0
  92. data/test/functional/test_dirty.rb +163 -0
  93. data/test/functional/test_document.rb +253 -0
  94. data/test/functional/test_dynamic_querying.rb +75 -0
  95. data/test/functional/test_embedded_document.rb +210 -0
  96. data/test/functional/test_identity_map.rb +506 -0
  97. data/test/functional/test_indexes.rb +42 -0
  98. data/test/functional/test_logger.rb +20 -0
  99. data/test/functional/test_modifiers.rb +416 -0
  100. data/test/functional/test_pagination.rb +91 -0
  101. data/test/functional/test_protected.rb +175 -0
  102. data/test/functional/test_querying.rb +873 -0
  103. data/test/functional/test_safe.rb +76 -0
  104. data/test/functional/test_sci.rb +230 -0
  105. data/test/functional/test_scopes.rb +171 -0
  106. data/test/functional/test_string_id_compatibility.rb +67 -0
  107. data/test/functional/test_timestamps.rb +62 -0
  108. data/test/functional/test_userstamps.rb +27 -0
  109. data/test/functional/test_validations.rb +342 -0
  110. data/test/models.rb +227 -0
  111. data/test/test_helper.rb +98 -0
  112. data/test/unit/associations/test_base.rb +212 -0
  113. data/test/unit/associations/test_proxy.rb +105 -0
  114. data/test/unit/serializers/test_json_serializer.rb +202 -0
  115. data/test/unit/test_clone.rb +69 -0
  116. data/test/unit/test_descendant_appends.rb +71 -0
  117. data/test/unit/test_document.rb +213 -0
  118. data/test/unit/test_dynamic_finder.rb +125 -0
  119. data/test/unit/test_embedded_document.rb +644 -0
  120. data/test/unit/test_extensions.rb +380 -0
  121. data/test/unit/test_key.rb +185 -0
  122. data/test/unit/test_keys.rb +55 -0
  123. data/test/unit/test_mongo_mapper.rb +110 -0
  124. data/test/unit/test_pagination.rb +11 -0
  125. data/test/unit/test_plugins.rb +50 -0
  126. data/test/unit/test_rails.rb +181 -0
  127. data/test/unit/test_rails_compatibility.rb +52 -0
  128. data/test/unit/test_serialization.rb +51 -0
  129. data/test/unit/test_time_zones.rb +39 -0
  130. data/test/unit/test_validations.rb +544 -0
  131. metadata +113 -44
  132. data/lib/mongo_mapper/plugins/pagination/proxy.rb +0 -72
  133. data/lib/mongo_mapper/query.rb +0 -23
  134. data/lib/mongo_mapper/support.rb +0 -196
@@ -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,230 @@
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
+
16
+ DocSon.many :children, :class_name => 'DocGrandSon'
17
+
18
+ @parent = DocParent.new({:name => "Daddy Warbucks"})
19
+ @daughter = DocDaughter.new({:name => "Little Orphan Annie"})
20
+ end
21
+
22
+ teardown do
23
+ Object.send :remove_const, 'DocParent' if defined?(::DocParent)
24
+ Object.send :remove_const, 'DocDaughter' if defined?(::DocDaughter)
25
+ Object.send :remove_const, 'DocSon' if defined?(::DocSon)
26
+ Object.send :remove_const, 'DocGrandSon' if defined?(::DocGrandSon)
27
+ end
28
+
29
+ should "automatically add _type key to store class" do
30
+ DocParent.key?(:_type).should be_true
31
+ end
32
+
33
+ should "use the same collection in the subclass" do
34
+ DocDaughter.collection.name.should == DocParent.collection.name
35
+ end
36
+
37
+ context ".single_collection_inherited?" do
38
+ should "be false if has not inherited" do
39
+ DocParent.should_not be_single_collection_inherited
40
+ end
41
+
42
+ should "be true if inherited" do
43
+ DocDaughter.should be_single_collection_inherited
44
+ DocSon.should be_single_collection_inherited
45
+ DocGrandSon.should be_single_collection_inherited
46
+ end
47
+ end
48
+
49
+ should "set _type on initialize" do
50
+ DocDaughter.new._type.should == 'DocDaughter'
51
+ DocSon.new._type.should == 'DocSon'
52
+ DocGrandSon.new._type.should == 'DocGrandSon'
53
+ end
54
+
55
+ should "set _type based on class and ignore assigned values" do
56
+ DocSon.new(:_type => 'DocDaughter')._type.should == 'DocSon'
57
+ end
58
+
59
+ context "loading" do
60
+ should "be based on _type" do
61
+ @parent.save
62
+ @daughter.save
63
+
64
+ collection = DocParent.all
65
+ collection.size.should == 2
66
+ collection.first.should be_kind_of(DocParent)
67
+ collection.first.name.should == "Daddy Warbucks"
68
+ collection.last.should be_kind_of(DocDaughter)
69
+ collection.last.name.should == "Little Orphan Annie"
70
+ end
71
+
72
+ should "gracefully handle when _type cannot be constantized" do
73
+ doc = DocParent.new(:name => 'Nunes')
74
+ doc._type = 'FoobarBaz'
75
+ doc.save
76
+
77
+ collection = DocParent.all
78
+ collection.last.should == doc
79
+ collection.last.should be_kind_of(DocParent)
80
+ end
81
+ end
82
+
83
+ context "querying" do
84
+ should "find scoped to class" do
85
+ john = DocSon.create(:name => 'John')
86
+ steve = DocSon.create(:name => 'Steve')
87
+ steph = DocDaughter.create(:name => 'Steph')
88
+ carrie = DocDaughter.create(:name => 'Carrie')
89
+
90
+ DocGrandSon.all(:order => 'name').should == []
91
+ DocSon.all(:order => 'name').should == [john, steve]
92
+ DocDaughter.all(:order => 'name').should == [carrie, steph]
93
+ DocParent.all(:order => 'name').should == [carrie, john, steph, steve]
94
+ end
95
+
96
+ should "work with nested hash conditions" do
97
+ john = DocSon.create(:name => 'John')
98
+ steve = DocSon.create(:name => 'Steve')
99
+ DocSon.all(:name => {'$ne' => 'Steve'}).should == [john]
100
+ end
101
+
102
+ should "raise error if not found scoped to class" do
103
+ john = DocSon.create(:name => 'John')
104
+ steph = DocDaughter.create(:name => 'Steph')
105
+
106
+ lambda {
107
+ DocSon.find!(steph._id)
108
+ }.should raise_error(MongoMapper::DocumentNotFound)
109
+ end
110
+
111
+ should "not raise error for find with parent" do
112
+ john = DocSon.create(:name => 'John')
113
+
114
+ DocParent.find!(john._id).should == john
115
+ end
116
+
117
+ should "count scoped to class" do
118
+ john = DocSon.create(:name => 'John')
119
+ steve = DocSon.create(:name => 'Steve')
120
+ steph = DocDaughter.create(:name => 'Steph')
121
+ carrie = DocDaughter.create(:name => 'Carrie')
122
+
123
+ DocGrandSon.count.should == 0
124
+ DocSon.count.should == 2
125
+ DocDaughter.count.should == 2
126
+ DocParent.count.should == 4
127
+ end
128
+
129
+ should "not be able to destroy each other" do
130
+ john = DocSon.create(:name => 'John')
131
+ steph = DocDaughter.create(:name => 'Steph')
132
+
133
+ lambda {
134
+ DocSon.destroy(steph._id)
135
+ }.should raise_error(MongoMapper::DocumentNotFound)
136
+ end
137
+
138
+ should "not be able to delete each other" do
139
+ john = DocSon.create(:name => 'John')
140
+ steph = DocDaughter.create(:name => 'Steph')
141
+
142
+ lambda {
143
+ DocSon.delete(steph._id)
144
+ }.should_not change { DocParent.count }
145
+ end
146
+
147
+ should "be able to destroy using parent" do
148
+ john = DocSon.create(:name => 'John')
149
+ steph = DocDaughter.create(:name => 'Steph')
150
+
151
+ lambda {
152
+ DocParent.destroy_all
153
+ }.should change { DocParent.count }.by(-2)
154
+ end
155
+
156
+ should "be able to delete using parent" do
157
+ john = DocSon.create(:name => 'John')
158
+ steph = DocDaughter.create(:name => 'Steph')
159
+
160
+ lambda {
161
+ DocParent.delete_all
162
+ }.should change { DocParent.count }.by(-2)
163
+ end
164
+ end
165
+
166
+ should "be able to reload single collection inherited parent class" do
167
+ brian = DocParent.create(:name => 'Brian')
168
+ brian.name = 'B-Dawg'
169
+ brian.reload
170
+ brian.name.should == 'Brian'
171
+ end
172
+ end
173
+
174
+ context "Single collection inheritance (embedded document)" do
175
+ setup do
176
+ class ::Grandparent
177
+ include MongoMapper::EmbeddedDocument
178
+ key :grandparent, String
179
+ end
180
+
181
+ class ::Parent < ::Grandparent
182
+ include MongoMapper::EmbeddedDocument
183
+ key :parent, String
184
+ end
185
+
186
+ class ::Child < ::Parent
187
+ include MongoMapper::EmbeddedDocument
188
+ key :child, String
189
+ end
190
+
191
+ class ::OtherChild < ::Parent
192
+ include MongoMapper::EmbeddedDocument
193
+ key :other_child, String
194
+ end
195
+ end
196
+
197
+ teardown do
198
+ Object.send :remove_const, 'Grandparent' if defined?(::Grandparent)
199
+ Object.send :remove_const, 'Parent' if defined?(::Parent)
200
+ Object.send :remove_const, 'Child' if defined?(::Child)
201
+ Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
202
+ end
203
+
204
+ should "automatically add _type key" do
205
+ Grandparent.key?(:_type).should be_true
206
+ end
207
+
208
+ context ".single_collection_inherited?" do
209
+ should "be false if has not inherited" do
210
+ Grandparent.should_not be_single_collection_inherited
211
+ end
212
+
213
+ should "be true if inherited" do
214
+ Parent.should be_single_collection_inherited
215
+ Child.should be_single_collection_inherited
216
+ OtherChild.should be_single_collection_inherited
217
+ end
218
+ end
219
+
220
+ should "set _type on initialize" do
221
+ Parent.new._type.should == 'Parent'
222
+ Child.new._type.should == 'Child'
223
+ OtherChild.new._type.should == 'OtherChild'
224
+ end
225
+
226
+ should "set _type based on class and ignore assigned values" do
227
+ Child.new(:_type => 'OtherChild')._type.should == 'Child'
228
+ end
229
+ end
230
+ 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