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,91 @@
1
+ require 'test_helper'
2
+
3
+ class PaginationTest < Test::Unit::TestCase
4
+ context "Paginating" do
5
+ setup do
6
+ @document = Doc do
7
+ key :first_name, String
8
+ key :last_name, String
9
+ key :age, Integer
10
+
11
+ def self.per_page; 1 end
12
+ end
13
+
14
+ @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
15
+ @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
16
+ @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
17
+ end
18
+
19
+ should "return the total pages" do
20
+ result = @document.paginate(:per_page => 2, :page => 1)
21
+ result.total_pages.should == 2
22
+ end
23
+
24
+ should "return the total pages when defaulting to the document class per_page" do
25
+ result = @document.paginate(:page => 1)
26
+ result.total_pages.should == 3
27
+ end
28
+
29
+ should "return the total of records" do
30
+ result = @document.paginate(:per_page => 2, :page => 1)
31
+ result.total_entries.should == 3
32
+ end
33
+
34
+ should "return the items" do
35
+ result = @document.paginate(:per_page => 2, :page => 1, :order => 'first_name')
36
+ result.size.should == 2
37
+ result.should == [@doc1, @doc3]
38
+ end
39
+
40
+ should "accept conditions" do
41
+ result = @document.paginate({
42
+ :last_name => 'Nunemaker',
43
+ :order => "age DESC",
44
+ :per_page => 2,
45
+ :page => 1,
46
+ })
47
+ result.should == [@doc1, @doc3]
48
+ result.first.age.should == 27
49
+
50
+ result = @document.paginate({
51
+ :conditions => {:last_name => 'Nunemaker'},
52
+ :order => "age DESC",
53
+ :per_page => 2,
54
+ :page => 1} )
55
+ result.should == [@doc1, @doc3]
56
+ result.first.age.should == 27
57
+ end
58
+
59
+ should "withstand rigor" do
60
+ result = @document.paginate({
61
+ :per_page => 1,
62
+ :page => 1,
63
+ :order => 'age desc',
64
+ :last_name => 'Nunemaker'
65
+ })
66
+ result.should == [@doc1]
67
+ result.total_entries.should == 2
68
+ result.total_pages.should == 2
69
+
70
+ result = @document.paginate({
71
+ :per_page => 1,
72
+ :page => 2,
73
+ :order => 'age desc',
74
+ :last_name => 'Nunemaker'
75
+ })
76
+ result.should == [@doc3]
77
+ result.total_entries.should == 2
78
+ result.total_pages.should == 2
79
+
80
+ result = @document.paginate({
81
+ :per_page => 2,
82
+ :page => 1,
83
+ :order => 'age desc',
84
+ :last_name => 'Nunemaker'
85
+ })
86
+ result.should == [@doc1, @doc3]
87
+ result.total_entries.should == 2
88
+ result.total_pages.should == 1
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,175 @@
1
+ require 'test_helper'
2
+
3
+ class ProtectedTest < Test::Unit::TestCase
4
+ context 'A document with protected attributes' do
5
+ setup do
6
+ @doc_class = Doc do
7
+ key :name, String
8
+ key :admin, Boolean, :default => false
9
+
10
+ attr_protected :admin
11
+ end
12
+
13
+ @doc = @doc_class.create(:name => 'Steve Sloan')
14
+ end
15
+
16
+ should "have protected attributes class method" do
17
+ @doc_class.protected_attributes.should == [:admin].to_set
18
+ end
19
+
20
+ should "default protected attributes to nil" do
21
+ Doc().protected_attributes.should be_nil
22
+ end
23
+
24
+ should "have protected attributes instance method" do
25
+ @doc.protected_attributes.should equal(@doc_class.protected_attributes)
26
+ end
27
+
28
+ should "raise error if there are accessible attributes" do
29
+ doc = Doc('Post')
30
+ doc.attr_accessible :name
31
+ lambda { doc.attr_protected :admin }.
32
+ should raise_error(/Declare either attr_protected or attr_accessible for Post/)
33
+ end
34
+
35
+ should "know if using protected attributes" do
36
+ @doc_class.protected_attributes?.should be(true)
37
+ Doc().protected_attributes?.should be(false)
38
+ end
39
+
40
+ should "work with :protected shortcut when defining key" do
41
+ Doc() do
42
+ key :user_id, ObjectId, :protected => true
43
+ end.protected_attributes.should == [:user_id].to_set
44
+ end
45
+
46
+ should "assign protected attribute through accessor" do
47
+ @doc.admin = true
48
+ @doc.admin.should be_true
49
+ end
50
+
51
+ should "ignore protected attribute on #initialize" do
52
+ doc = @doc_class.new(:name => 'John', :admin => true)
53
+ doc.admin.should be_false
54
+ doc.name.should == 'John'
55
+ end
56
+
57
+ should "not ignore protected attributes on #initialize from the database" do
58
+ doc = @doc_class.new(:name => 'John')
59
+ doc.admin = true
60
+ doc.save!
61
+
62
+ doc = @doc_class.first(:name => 'John')
63
+ doc.admin.should be_true
64
+ doc.name.should == 'John'
65
+ end
66
+
67
+ should "ignore protected attribute on #update_attributes" do
68
+ @doc.update_attributes(:name => 'Ren Hoek', :admin => true)
69
+ @doc.name.should == 'Ren Hoek'
70
+ @doc.admin.should be_false
71
+ end
72
+
73
+ should "ignore protected attribute on #update_attributes!" do
74
+ @doc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
75
+ @doc.name.should == 'Stimpson J. Cat'
76
+ @doc.admin.should be_false
77
+ end
78
+
79
+ should "be indifferent to whether the protected keys are strings or symbols" do
80
+ @doc.update_attributes!("name" => 'Stimpson J. Cat', "admin" => true)
81
+ @doc.name.should == 'Stimpson J. Cat'
82
+ @doc.admin.should be_false
83
+ end
84
+
85
+ should "accept nil as constructor's argument without raising exception" do
86
+ lambda { @doc_class.new(nil) }.should_not raise_error
87
+ end
88
+ end
89
+
90
+ context "Single collection inherited protected attributes" do
91
+ setup do
92
+ class ::GrandParent
93
+ include MongoMapper::Document
94
+
95
+ key :site_id, ObjectId
96
+ attr_protected :site_id
97
+ end
98
+ GrandParent.collection.remove
99
+
100
+ class ::Child < ::GrandParent
101
+ key :position, Integer
102
+
103
+ attr_protected :position
104
+ end
105
+
106
+ class ::GrandChild < ::Child; end
107
+
108
+ class ::OtherChild < ::GrandParent
109
+ key :blog_id, ObjectId
110
+
111
+ attr_protected :blog_id
112
+ end
113
+ end
114
+
115
+ teardown do
116
+ Object.send :remove_const, 'GrandParent' if defined?(::GrandParent)
117
+ Object.send :remove_const, 'Child' if defined?(::Child)
118
+ Object.send :remove_const, 'GrandChild' if defined?(::GrandChild)
119
+ Object.send :remove_const, 'OtherChild' if defined?(::OtherChild)
120
+ end
121
+
122
+ should "share keys down the inheritance trail" do
123
+ GrandParent.protected_attributes.should == [:site_id].to_set
124
+ Child.protected_attributes.should == [:site_id, :position].to_set
125
+ GrandChild.protected_attributes.should == [:site_id, :position].to_set
126
+ OtherChild.protected_attributes.should == [:site_id, :blog_id].to_set
127
+ end
128
+ end
129
+
130
+ context 'An embedded document with protected attributes' do
131
+ setup do
132
+ @doc_class = Doc('Project')
133
+ @edoc_class = EDoc('Person') do
134
+ key :name, String
135
+ key :admin, Boolean, :default => false
136
+
137
+ attr_protected :admin
138
+ end
139
+ @doc_class.many :people, :class => @edoc_class
140
+
141
+ @doc = @doc_class.create(:title => 'MongoMapper')
142
+ @edoc = @edoc_class.new(:name => 'Steve Sloan')
143
+ @doc.people << @edoc
144
+ end
145
+
146
+ should "have protected attributes class method" do
147
+ @edoc_class.protected_attributes.should == [:admin].to_set
148
+ end
149
+
150
+ should "default protected attributes to nil" do
151
+ EDoc().protected_attributes.should be_nil
152
+ end
153
+
154
+ should "have protected attributes instance method" do
155
+ @edoc.protected_attributes.should equal(@edoc_class.protected_attributes)
156
+ end
157
+
158
+ should "assign protected attribute through accessor" do
159
+ @edoc.admin = true
160
+ @edoc.admin.should be_true
161
+ end
162
+
163
+ should "ignore protected attribute on #update_attributes" do
164
+ @edoc.update_attributes(:name => 'Ren Hoek', :admin => true)
165
+ @edoc.name.should == 'Ren Hoek'
166
+ @edoc.admin.should be_false
167
+ end
168
+
169
+ should "ignore protected attribute on #update_attributes!" do
170
+ @edoc.update_attributes!(:name => 'Stimpson J. Cat', :admin => true)
171
+ @edoc.name.should == 'Stimpson J. Cat'
172
+ @edoc.admin.should be_false
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,873 @@
1
+ require 'test_helper'
2
+
3
+ class QueryingTesting < Test::Unit::TestCase
4
+ def setup
5
+ @document = Doc do
6
+ key :first_name, String
7
+ key :last_name, String
8
+ key :age, Integer
9
+ key :date, Date
10
+ end
11
+ end
12
+
13
+ context ".query" do
14
+ setup do
15
+ @query = @document.query
16
+ end
17
+
18
+ should "set model to self" do
19
+ @query.model.should == @document
20
+ end
21
+
22
+ should "always return new instance" do
23
+ @document.query.should_not equal(@query)
24
+ end
25
+
26
+ should "apply options" do
27
+ @document.query(:foo => 'bar')[:foo].should == 'bar'
28
+ end
29
+ end
30
+
31
+ context ".criteria_hash" do
32
+ setup do
33
+ @hash = @document.criteria_hash
34
+ end
35
+
36
+ should "set object id keys on hash" do
37
+ @hash.object_ids.should == [:_id]
38
+ end
39
+
40
+ should "always return new instance" do
41
+ @document.criteria_hash.should_not equal(@hash)
42
+ end
43
+
44
+ should "apply provided criteria" do
45
+ @document.criteria_hash(:foo => 'bar')[:foo].should == 'bar'
46
+ end
47
+ end
48
+
49
+ context ".create (single document)" do
50
+ setup do
51
+ @doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
52
+ end
53
+
54
+ should "create a document in correct collection" do
55
+ @document.count.should == 1
56
+ end
57
+
58
+ should "automatically set id" do
59
+ @doc.id.should be_instance_of(BSON::ObjectID)
60
+ @doc._id.should be_instance_of(BSON::ObjectID)
61
+ end
62
+
63
+ should "no longer be new?" do
64
+ @doc.new?.should be_false
65
+ end
66
+
67
+ should "return instance of document" do
68
+ @doc.should be_instance_of(@document)
69
+ @doc.first_name.should == 'John'
70
+ @doc.last_name.should == 'Nunemaker'
71
+ @doc.age.should == 27
72
+ end
73
+
74
+ should "not fail if no attributes provided" do
75
+ document = Doc()
76
+ lambda { document.create }.should change { document.count }.by(1)
77
+ end
78
+ end
79
+
80
+ context ".create (multiple documents)" do
81
+ setup do
82
+ @docs = @document.create([
83
+ {:first_name => 'John', :last_name => 'Nunemaker', :age => '27'},
84
+ {:first_name => 'Steve', :last_name => 'Smith', :age => '28'},
85
+ ])
86
+ end
87
+
88
+ should "create multiple documents" do
89
+ @document.count.should == 2
90
+ end
91
+
92
+ should "return an array of doc instances" do
93
+ @docs.map do |doc|
94
+ doc.should be_instance_of(@document)
95
+ end
96
+ end
97
+ end
98
+
99
+ context ".update (single document)" do
100
+ setup do
101
+ doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
102
+ @doc = @document.update(doc._id, {:age => 40})
103
+ end
104
+
105
+ should "update attributes provided" do
106
+ @doc.age.should == 40
107
+ end
108
+
109
+ should "not update existing attributes that were not set to update" do
110
+ @doc.first_name.should == 'John'
111
+ @doc.last_name.should == 'Nunemaker'
112
+ end
113
+
114
+ should "not create new document" do
115
+ @document.count.should == 1
116
+ end
117
+
118
+ should "raise error if not provided id" do
119
+ doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
120
+ lambda { @document.update }.should raise_error(ArgumentError)
121
+ end
122
+
123
+ should "raise error if not provided attributes" do
124
+ doc = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
125
+ lambda { @document.update(doc._id) }.should raise_error(ArgumentError)
126
+ lambda { @document.update(doc._id, [1]) }.should raise_error(ArgumentError)
127
+ end
128
+ end
129
+
130
+ context ".update (multiple documents)" do
131
+ setup do
132
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
133
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
134
+
135
+ @docs = @document.update({
136
+ @doc1._id => {:age => 30},
137
+ @doc2._id => {:age => 30},
138
+ })
139
+ end
140
+
141
+ should "not create any new documents" do
142
+ @document.count.should == 2
143
+ end
144
+
145
+ should "should return an array of doc instances" do
146
+ @docs.map do |doc|
147
+ doc.should be_instance_of(@document)
148
+ end
149
+ end
150
+
151
+ should "update the documents" do
152
+ @document.find(@doc1._id).age.should == 30
153
+ @document.find(@doc2._id).age.should == 30
154
+ end
155
+
156
+ should "raise error if not a hash" do
157
+ lambda { @document.update([1, 2]) }.should raise_error(ArgumentError)
158
+ end
159
+ end
160
+
161
+ context ".find" do
162
+ setup do
163
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
164
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
165
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
166
+ end
167
+
168
+ should "return nil if nothing provided for find" do
169
+ @document.find.should be_nil
170
+ end
171
+
172
+ should "raise document not found if nothing provided for find!" do
173
+ assert_raises(MongoMapper::DocumentNotFound) do
174
+ @document.find!
175
+ end
176
+ end
177
+
178
+ context "(with a single id)" do
179
+ should "work" do
180
+ @document.find(@doc1._id).should == @doc1
181
+ end
182
+
183
+ should "return nil if document not found with find" do
184
+ @document.find(123).should be_nil
185
+ end
186
+
187
+ should "raise error if document not found with find!" do
188
+ assert_raises(MongoMapper::DocumentNotFound) { @document.find!(123) }
189
+ end
190
+ end
191
+
192
+ context "(with multiple id's)" do
193
+ should "work as arguments" do
194
+ @document.find(@doc1._id, @doc2._id).should == [@doc1, @doc2]
195
+ end
196
+
197
+ should "work as arguments with string ids" do
198
+ @document.find(@doc1._id.to_s, @doc2._id.to_s).should == [@doc1, @doc2]
199
+ end
200
+
201
+ should "work as array" do
202
+ @document.find([@doc1._id, @doc2._id]).should == [@doc1, @doc2]
203
+ end
204
+
205
+ should "work as array with string ids" do
206
+ @document.find([@doc1._id.to_s, @doc2._id.to_s]).should == [@doc1, @doc2]
207
+ end
208
+
209
+ should "compact not found when using find" do
210
+ @document.find(@doc1._id, BSON::ObjectID.new.to_s).should == [@doc1]
211
+ end
212
+
213
+ should "raise error if not all found when using find!" do
214
+ assert_raises(MongoMapper::DocumentNotFound) do
215
+ @document.find!(@doc1._id, BSON::ObjectID.new.to_s)
216
+ end
217
+ end
218
+
219
+ should "return array if array with one element" do
220
+ @document.find([@doc1._id]).should == [@doc1]
221
+ end
222
+ end
223
+
224
+ should "be able to find using condition auto-detection" do
225
+ @document.first(:first_name => 'John').should == @doc1
226
+ @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
227
+ end
228
+
229
+ context "#all" do
230
+ should "find all documents with options" do
231
+ @document.all(:order => 'first_name').should == [@doc1, @doc3, @doc2]
232
+ @document.all(:last_name => 'Nunemaker', :order => 'age desc').should == [@doc1, @doc3]
233
+ end
234
+ end
235
+
236
+ context "#first" do
237
+ should "find first document with options" do
238
+ @document.first(:order => 'first_name').should == @doc1
239
+ @document.first(:age => 28).should == @doc2
240
+ end
241
+ end
242
+
243
+ context "#last" do
244
+ should "find last document with options" do
245
+ @document.last(:order => 'age').should == @doc2
246
+ @document.last(:order => 'age', :age => 28).should == @doc2
247
+ end
248
+ end
249
+
250
+ context "#find_each" do
251
+ should "yield all documents found based on options" do
252
+ yield_documents = []
253
+ @document.find_each(:order => "first_name") {|doc| yield_documents << doc }
254
+ yield_documents.should == [@doc1, @doc3, @doc2]
255
+
256
+ yield_documents = []
257
+ @document.find_each(:last_name => 'Nunemaker', :order => 'age desc') {|doc| yield_documents << doc }
258
+ yield_documents.should == [@doc1, @doc3]
259
+ end
260
+ end
261
+ end # finding documents
262
+
263
+ context ".find_by_id" do
264
+ setup do
265
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
266
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
267
+ end
268
+
269
+ should "be able to find by id" do
270
+ @document.find_by_id(@doc1._id).should == @doc1
271
+ @document.find_by_id(@doc2._id).should == @doc2
272
+ end
273
+
274
+ should "return nil if document not found" do
275
+ @document.find_by_id(1234).should be_nil
276
+ end
277
+ end
278
+
279
+ context ".first_or_create" do
280
+ should "find if exists" do
281
+ created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
282
+ lambda {
283
+ found = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
284
+ found.should == created
285
+ }.should_not change { @document.count }
286
+ end
287
+
288
+ should "create if not found" do
289
+ lambda {
290
+ created = @document.first_or_create(:first_name => 'John', :last_name => 'Nunemaker')
291
+ created.first_name.should == 'John'
292
+ created.last_name.should == 'Nunemaker'
293
+ }.should change { @document.count }.by(1)
294
+ end
295
+
296
+ should "disregard non-keys when creating, but use them in the query" do
297
+ assert_nothing_raised do
298
+ @document.create(:first_name => 'John', :age => 9)
299
+ lambda {
300
+ @document.first_or_create(:first_name => 'John', :age.gt => 10).first_name.should == 'John'
301
+ }.should change { @document.count }.by(1)
302
+ end
303
+ end
304
+ end
305
+
306
+ context ".first_or_new" do
307
+ should "find if exists" do
308
+ created = @document.create(:first_name => 'John', :last_name => 'Nunemaker')
309
+ lambda {
310
+ found = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
311
+ found.should == created
312
+ }.should_not change { @document.count }
313
+ end
314
+
315
+ should "initialize if not found" do
316
+ lambda {
317
+ created = @document.first_or_new(:first_name => 'John', :last_name => 'Nunemaker')
318
+ created.first_name.should == 'John'
319
+ created.last_name.should == 'Nunemaker'
320
+ created.should be_new
321
+ }.should_not change { @document.count }
322
+ end
323
+
324
+ should "disregard non-keys when initializing, but use them in the query" do
325
+ assert_nothing_raised do
326
+ @document.create(:first_name => 'John', :age => 9)
327
+ @document.first_or_new(:first_name => 'John', :age.gt => 10).first_name.should == 'John'
328
+ end
329
+ end
330
+ end
331
+
332
+ context ".delete (single document)" do
333
+ setup do
334
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
335
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
336
+ @document.delete(@doc1._id)
337
+ end
338
+
339
+ should "remove document from collection" do
340
+ @document.count.should == 1
341
+ end
342
+
343
+ should "not remove other documents" do
344
+ @document.find(@doc2._id).should_not be(nil)
345
+ end
346
+ end
347
+
348
+ context ".delete (multiple documents)" do
349
+ should "work with multiple arguments" do
350
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
351
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
352
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
353
+ @document.delete(@doc1._id, @doc2._id)
354
+
355
+ @document.count.should == 1
356
+ end
357
+
358
+ should "work with array as argument" do
359
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
360
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
361
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
362
+ @document.delete([@doc1._id, @doc2._id])
363
+
364
+ @document.count.should == 1
365
+ end
366
+ end
367
+
368
+ context ".delete_all" do
369
+ setup do
370
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
371
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
372
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
373
+ end
374
+
375
+ should "remove all documents when given no conditions" do
376
+ @document.delete_all
377
+ @document.count.should == 0
378
+ end
379
+
380
+ should "only remove matching documents when given conditions" do
381
+ @document.delete_all({:first_name => 'John'})
382
+ @document.count.should == 2
383
+ end
384
+
385
+ should "convert the conditions to mongo criteria" do
386
+ @document.delete_all(:age => [26, 27])
387
+ @document.count.should == 1
388
+ end
389
+ end
390
+
391
+ context ".destroy (single document)" do
392
+ setup do
393
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
394
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
395
+ @document.destroy(@doc1._id)
396
+ end
397
+
398
+ should "remove document from collection" do
399
+ @document.count.should == 1
400
+ end
401
+
402
+ should "not remove other documents" do
403
+ @document.find(@doc2._id).should_not be(nil)
404
+ end
405
+ end
406
+
407
+ context ".destroy (multiple documents)" do
408
+ should "work with multiple arguments" do
409
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
410
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
411
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
412
+ @document.destroy(@doc1._id, @doc2._id)
413
+
414
+ @document.count.should == 1
415
+ end
416
+
417
+ should "work with array as argument" do
418
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
419
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
420
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
421
+ @document.destroy([@doc1._id, @doc2._id])
422
+
423
+ @document.count.should == 1
424
+ end
425
+ end
426
+
427
+ context ".destroy_all" do
428
+ setup do
429
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
430
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
431
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
432
+ end
433
+
434
+ should "remove all documents when given no conditions" do
435
+ @document.destroy_all
436
+ @document.count.should == 0
437
+ end
438
+
439
+ should "only remove matching documents when given conditions" do
440
+ @document.destroy_all(:first_name => 'John')
441
+ @document.count.should == 2
442
+ @document.destroy_all(:age => 26)
443
+ @document.count.should == 1
444
+ end
445
+
446
+ should "convert the conditions to mongo criteria" do
447
+ @document.destroy_all(:age => [26, 27])
448
+ @document.count.should == 1
449
+ end
450
+ end
451
+
452
+ context ".count" do
453
+ setup do
454
+ @doc1 = @document.create({:first_name => 'John', :last_name => 'Nunemaker', :age => '27'})
455
+ @doc2 = @document.create({:first_name => 'Steve', :last_name => 'Smith', :age => '28'})
456
+ @doc3 = @document.create({:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26'})
457
+ end
458
+
459
+ should "count all with no arguments" do
460
+ @document.count.should == 3
461
+ end
462
+
463
+ should "return 0 if there are no documents in the collection" do
464
+ @document.delete_all
465
+ @document.count.should == 0
466
+ end
467
+
468
+ should "return 0 if the collection does not exist" do
469
+ klass = Doc do
470
+ set_collection_name 'foobarbazwickdoesnotexist'
471
+ end
472
+
473
+ klass.count.should == 0
474
+ end
475
+
476
+ should "return count for matching documents if conditions provided" do
477
+ @document.count(:age => 27).should == 1
478
+ end
479
+
480
+ should "convert the conditions to mongo criteria" do
481
+ @document.count(:age => [26, 27]).should == 2
482
+ end
483
+ end
484
+
485
+ context ".exists?" do
486
+ setup do
487
+ @doc = @document.create(:first_name => "James", :age => 27)
488
+ end
489
+
490
+ should "be true when at least one document exists" do
491
+ @document.exists?.should == true
492
+ end
493
+
494
+ should "be false when no documents exist" do
495
+ @doc.destroy
496
+ @document.exists?.should == false
497
+ end
498
+
499
+ should "be true when at least one document exists that matches the conditions" do
500
+ @document.exists?(:first_name => "James").should == true
501
+ end
502
+
503
+ should "be false when no documents exist with the provided conditions" do
504
+ @document.exists?(:first_name => "Jean").should == false
505
+ end
506
+ end
507
+
508
+ context ".where" do
509
+ setup do
510
+ @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
511
+ @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
512
+ @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
513
+ @query = @document.where(:last_name => 'Nunemaker')
514
+ end
515
+
516
+ should "fetch documents when kicker called" do
517
+ docs = @query.all
518
+ docs.should include(@doc1)
519
+ docs.should include(@doc3)
520
+ docs.should_not include(@doc2)
521
+ end
522
+
523
+ should "be chainable" do
524
+ @query.sort(:age).first.should == @doc3
525
+ end
526
+ end
527
+
528
+ context ".fields" do
529
+ setup do
530
+ @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
531
+ @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
532
+ @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
533
+ @query = @document.fields(:age)
534
+ end
535
+
536
+ should "fetch documents when kicker called" do
537
+ docs = @query.all
538
+ docs.should include(@doc1)
539
+ docs.should include(@doc3)
540
+ docs.should include(@doc2)
541
+ docs.each do |doc|
542
+ doc.age.should_not be_nil
543
+ doc.first_name.should be_nil # key was not loaded
544
+ doc.last_name.should be_nil # key was not loaded
545
+ end
546
+ end
547
+
548
+ should "be chainable" do
549
+ @query.sort(:age).all.map(&:age).should == [26, 27, 28]
550
+ end
551
+ end
552
+
553
+ context ".limit" do
554
+ setup do
555
+ @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
556
+ @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
557
+ @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
558
+ @query = @document.limit(2)
559
+ end
560
+
561
+ should "fetch documents when kicker called" do
562
+ docs = @query.all
563
+ docs.size.should == 2
564
+ end
565
+
566
+ should "be chainable" do
567
+ result = [26, 27]
568
+ @query.sort(:age).all.map(&:age).should == result
569
+ @query.count.should > result.size
570
+ end
571
+ end
572
+
573
+ context ".skip" do
574
+ setup do
575
+ @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
576
+ @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
577
+ @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
578
+ @query = @document.skip(1)
579
+ end
580
+
581
+ should "fetch documents when kicker called" do
582
+ docs = @query.all
583
+ docs.size.should == 2 # skipping 1 out of 3
584
+ end
585
+
586
+ should "be chainable" do
587
+ result = [27, 28]
588
+ @query.sort(:age).all.map(&:age).should == result
589
+ @query.count.should > result.size
590
+ end
591
+ end
592
+
593
+ context ".sort" do
594
+ setup do
595
+ @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
596
+ @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
597
+ @doc3 = @document.create(:first_name => 'Steph', :last_name => 'Nunemaker', :age => '26')
598
+ @query = @document.sort(:age)
599
+ end
600
+
601
+ should "fetch documents when kicker called" do
602
+ @query.all.should == [@doc3, @doc1, @doc2]
603
+ end
604
+
605
+ should "be chainable" do
606
+ result = [28]
607
+ @query.skip(2).all.map(&:age).should == result
608
+ @query.count.should > result.size
609
+ end
610
+ end
611
+
612
+ context "#update_attributes (new document)" do
613
+ setup do
614
+ @doc = @document.new(:first_name => 'John', :age => '27')
615
+ @doc.update_attributes(:first_name => 'Johnny', :age => 30)
616
+ end
617
+
618
+ should "insert document into the collection" do
619
+ @document.count.should == 1
620
+ end
621
+
622
+ should "assign an id for the document" do
623
+ @doc.id.should be_instance_of(BSON::ObjectID)
624
+ end
625
+
626
+ should "save attributes" do
627
+ @doc.first_name.should == 'Johnny'
628
+ @doc.age.should == 30
629
+ end
630
+
631
+ should "update attributes in the database" do
632
+ doc = @doc.reload
633
+ doc.should == @doc
634
+ doc.first_name.should == 'Johnny'
635
+ doc.age.should == 30
636
+ end
637
+
638
+ should "allow updating custom attributes" do
639
+ @doc.update_attributes(:gender => 'mALe')
640
+ @doc.reload.gender.should == 'mALe'
641
+ end
642
+ end
643
+
644
+ context "#update_attributes (existing document)" do
645
+ setup do
646
+ @doc = @document.create(:first_name => 'John', :age => '27')
647
+ @doc.update_attributes(:first_name => 'Johnny', :age => 30)
648
+ end
649
+
650
+ should "not insert document into collection" do
651
+ @document.count.should == 1
652
+ end
653
+
654
+ should "update attributes" do
655
+ @doc.first_name.should == 'Johnny'
656
+ @doc.age.should == 30
657
+ end
658
+
659
+ should "update attributes in the database" do
660
+ doc = @doc.reload
661
+ doc.first_name.should == 'Johnny'
662
+ doc.age.should == 30
663
+ end
664
+ end
665
+
666
+ context "#update_attributes (return value)" do
667
+ setup do
668
+ @document.key :foo, String, :required => true
669
+ end
670
+
671
+ should "be true if document valid" do
672
+ @document.new.update_attributes(:foo => 'bar').should be_true
673
+ end
674
+
675
+ should "be false if document not valid" do
676
+ @document.new.update_attributes({}).should be_false
677
+ end
678
+ end
679
+
680
+ context "#save (new document)" do
681
+ setup do
682
+ @doc = @document.new(:first_name => 'John', :age => '27')
683
+ @doc.save
684
+ end
685
+
686
+ should "insert document into the collection" do
687
+ @document.count.should == 1
688
+ end
689
+
690
+ should "assign an id for the document" do
691
+ @doc.id.should be_instance_of(BSON::ObjectID)
692
+ end
693
+
694
+ should "save attributes" do
695
+ @doc.first_name.should == 'John'
696
+ @doc.age.should == 27
697
+ end
698
+
699
+ should "update attributes in the database" do
700
+ doc = @doc.reload
701
+ doc.should == @doc
702
+ doc.first_name.should == 'John'
703
+ doc.age.should == 27
704
+ end
705
+
706
+ should "allow to add custom attributes to the document" do
707
+ @doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male', :tags => [1, "2"])
708
+ @doc.save
709
+ doc = @doc.reload
710
+ doc.gender.should == 'male'
711
+ doc.tags.should == [1, "2"]
712
+ end
713
+
714
+ should "allow to use custom methods to assign properties" do
715
+ klass = Doc do
716
+ key :name, String
717
+
718
+ def realname=(value)
719
+ self.name = value
720
+ end
721
+ end
722
+
723
+ person = klass.new(:realname => 'David')
724
+ person.save
725
+ person.reload.name.should == 'David'
726
+ end
727
+
728
+ context "with key of type date" do
729
+ should "save the date value as a Time object" do
730
+ doc = @document.new(:first_name => 'John', :age => '27', :date => "2009-12-01")
731
+ doc.save
732
+ doc.date.should == Date.new(2009, 12, 1)
733
+ end
734
+ end
735
+ end
736
+
737
+ context "#save (existing document)" do
738
+ setup do
739
+ @doc = @document.create(:first_name => 'John', :age => '27')
740
+ @doc.first_name = 'Johnny'
741
+ @doc.age = 30
742
+ @doc.save
743
+ end
744
+
745
+ should "not insert document into collection" do
746
+ @document.count.should == 1
747
+ end
748
+
749
+ should "update attributes" do
750
+ @doc.first_name.should == 'Johnny'
751
+ @doc.age.should == 30
752
+ end
753
+
754
+ should "update attributes in the database" do
755
+ doc = @doc.reload
756
+ doc.first_name.should == 'Johnny'
757
+ doc.age.should == 30
758
+ end
759
+
760
+ should "allow updating custom attributes" do
761
+ @doc = @document.new(:first_name => 'David', :age => '26', :gender => 'male')
762
+ @doc.gender = 'Male'
763
+ @doc.save
764
+ @doc.reload.gender.should == 'Male'
765
+ end
766
+ end
767
+
768
+ context "#save (with validations off)" do
769
+ setup do
770
+ @document = Doc do
771
+ key :name, String, :required => true
772
+ end
773
+ end
774
+
775
+ should "insert invalid document" do
776
+ doc = @document.new
777
+ doc.expects(:valid?).never
778
+ doc.save(:validate => false)
779
+ @document.count.should == 1
780
+ end
781
+ end
782
+
783
+ context "#save (with options)" do
784
+ setup do
785
+ @document = Doc do
786
+ key :name, String
787
+ end
788
+ @document.ensure_index :name, :unique => true
789
+ end
790
+ teardown { drop_indexes(@document) }
791
+
792
+ should "allow passing safe" do
793
+ @document.create(:name => 'John')
794
+ assert_raises(Mongo::OperationFailure) do
795
+ @document.new(:name => 'John').save(:safe => true)
796
+ end
797
+ end
798
+
799
+ should "raise argument error if options has unsupported key" do
800
+ assert_raises(ArgumentError) do
801
+ @document.new.save(:foo => true)
802
+ end
803
+ end
804
+ end
805
+
806
+ context "#save! (with options)" do
807
+ setup do
808
+ @document = Doc { key :name, String }
809
+ @document.ensure_index :name, :unique => true
810
+ end
811
+ teardown { drop_indexes(@document) }
812
+
813
+ should "allow passing safe" do
814
+ @document.create(:name => 'John')
815
+ assert_raises(Mongo::OperationFailure) do
816
+ @document.new(:name => 'John').save!(:safe => true)
817
+ end
818
+ end
819
+
820
+ should "raise argument error if options has unsupported key" do
821
+ assert_raises(ArgumentError) do
822
+ @document.new.save!(:foo => true)
823
+ end
824
+ end
825
+
826
+ should "raise argument error if using validate as that would be pointless with save!" do
827
+ assert_raises(ArgumentError) do
828
+ @document.new.save!(:validate => false)
829
+ end
830
+ end
831
+ end
832
+
833
+ context "#destroy" do
834
+ setup do
835
+ @doc = @document.create(:first_name => 'John', :age => '27')
836
+ @doc.destroy
837
+ end
838
+
839
+ should "remove the document from the collection" do
840
+ @document.count.should == 0
841
+ end
842
+ end
843
+
844
+ context "#delete" do
845
+ setup do
846
+ @doc1 = @document.create(:first_name => 'John', :last_name => 'Nunemaker', :age => '27')
847
+ @doc2 = @document.create(:first_name => 'Steve', :last_name => 'Smith', :age => '28')
848
+
849
+ @document.class_eval do
850
+ before_destroy :before_destroy_callback
851
+ after_destroy :after_destroy_callback
852
+
853
+ def history; @history ||= [] end
854
+ def before_destroy_callback; history << :after_destroy end
855
+ def after_destroy_callback; history << :after_destroy end
856
+ end
857
+
858
+ @doc1.delete
859
+ end
860
+
861
+ should "remove document from collection" do
862
+ @document.count.should == 1
863
+ end
864
+
865
+ should "not remove other documents" do
866
+ @document.find(@doc2.id).should_not be(nil)
867
+ end
868
+
869
+ should "not call before/after destroy callbacks" do
870
+ @doc1.history.should == []
871
+ end
872
+ end
873
+ end