mongo_mapper 0.13.1 → 0.15.2

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 (133) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +61 -0
  4. data/examples/keys.rb +1 -1
  5. data/examples/modifiers/set.rb +1 -1
  6. data/examples/querying.rb +1 -1
  7. data/examples/safe.rb +2 -2
  8. data/examples/scopes.rb +1 -1
  9. data/lib/mongo_mapper.rb +4 -0
  10. data/lib/mongo_mapper/connection.rb +16 -38
  11. data/lib/mongo_mapper/document.rb +2 -0
  12. data/lib/mongo_mapper/extensions/array.rb +14 -6
  13. data/lib/mongo_mapper/extensions/hash.rb +15 -3
  14. data/lib/mongo_mapper/extensions/object.rb +4 -0
  15. data/lib/mongo_mapper/extensions/object_id.rb +5 -1
  16. data/lib/mongo_mapper/extensions/string.rb +13 -5
  17. data/lib/mongo_mapper/plugins/accessible.rb +13 -12
  18. data/lib/mongo_mapper/plugins/associations.rb +7 -6
  19. data/lib/mongo_mapper/plugins/associations/base.rb +23 -14
  20. data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +1 -1
  21. data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +9 -8
  22. data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +18 -11
  23. data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +4 -4
  24. data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +60 -29
  25. data/lib/mongo_mapper/plugins/associations/in_foreign_array_proxy.rb +136 -0
  26. data/lib/mongo_mapper/plugins/associations/many_association.rb +4 -2
  27. data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +18 -16
  28. data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +55 -48
  29. data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +14 -13
  30. data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +7 -6
  31. data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +7 -5
  32. data/lib/mongo_mapper/plugins/associations/one_as_proxy.rb +14 -11
  33. data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +14 -13
  34. data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +12 -10
  35. data/lib/mongo_mapper/plugins/associations/one_proxy.rb +27 -26
  36. data/lib/mongo_mapper/plugins/associations/proxy.rb +38 -27
  37. data/lib/mongo_mapper/plugins/associations/single_association.rb +5 -4
  38. data/lib/mongo_mapper/plugins/callbacks.rb +13 -0
  39. data/lib/mongo_mapper/plugins/counter_cache.rb +23 -4
  40. data/lib/mongo_mapper/plugins/dirty.rb +29 -37
  41. data/lib/mongo_mapper/plugins/document.rb +1 -1
  42. data/lib/mongo_mapper/plugins/dynamic_querying.rb +10 -9
  43. data/lib/mongo_mapper/plugins/dynamic_querying/dynamic_finder.rb +18 -17
  44. data/lib/mongo_mapper/plugins/embedded_callbacks.rb +2 -1
  45. data/lib/mongo_mapper/plugins/embedded_document.rb +2 -2
  46. data/lib/mongo_mapper/plugins/identity_map.rb +4 -2
  47. data/lib/mongo_mapper/plugins/indexes.rb +14 -7
  48. data/lib/mongo_mapper/plugins/keys.rb +164 -159
  49. data/lib/mongo_mapper/plugins/keys/key.rb +27 -16
  50. data/lib/mongo_mapper/plugins/keys/static.rb +45 -0
  51. data/lib/mongo_mapper/plugins/modifiers.rb +64 -38
  52. data/lib/mongo_mapper/plugins/partial_updates.rb +86 -0
  53. data/lib/mongo_mapper/plugins/persistence.rb +13 -8
  54. data/lib/mongo_mapper/plugins/protected.rb +6 -5
  55. data/lib/mongo_mapper/plugins/querying.rb +85 -42
  56. data/lib/mongo_mapper/plugins/querying/decorated_plucky_query.rb +20 -15
  57. data/lib/mongo_mapper/plugins/safe.rb +10 -4
  58. data/lib/mongo_mapper/plugins/scopes.rb +94 -7
  59. data/lib/mongo_mapper/plugins/stats.rb +1 -3
  60. data/lib/mongo_mapper/plugins/strong_parameters.rb +26 -0
  61. data/lib/mongo_mapper/plugins/timestamps.rb +1 -0
  62. data/lib/mongo_mapper/plugins/validations.rb +0 -0
  63. data/lib/mongo_mapper/railtie.rb +1 -0
  64. data/lib/mongo_mapper/utils.rb +2 -2
  65. data/lib/mongo_mapper/version.rb +1 -1
  66. data/lib/rails/generators/mongo_mapper/config/config_generator.rb +12 -13
  67. data/lib/rails/generators/mongo_mapper/model/model_generator.rb +9 -9
  68. data/spec/examples.txt +1728 -0
  69. data/spec/functional/accessible_spec.rb +19 -13
  70. data/spec/functional/associations/belongs_to_polymorphic_proxy_spec.rb +13 -13
  71. data/spec/functional/associations/belongs_to_proxy_spec.rb +54 -20
  72. data/spec/functional/associations/in_array_proxy_spec.rb +145 -10
  73. data/spec/functional/associations/in_foreign_array_proxy_spec.rb +321 -0
  74. data/spec/functional/associations/many_documents_as_proxy_spec.rb +6 -6
  75. data/spec/functional/associations/many_documents_proxy_spec.rb +85 -14
  76. data/spec/functional/associations/many_embedded_polymorphic_proxy_spec.rb +13 -13
  77. data/spec/functional/associations/many_embedded_proxy_spec.rb +1 -1
  78. data/spec/functional/associations/many_polymorphic_proxy_spec.rb +4 -4
  79. data/spec/functional/associations/one_as_proxy_spec.rb +10 -10
  80. data/spec/functional/associations/one_embedded_polymorphic_proxy_spec.rb +9 -9
  81. data/spec/functional/associations/one_embedded_proxy_spec.rb +31 -3
  82. data/spec/functional/associations/one_proxy_spec.rb +21 -11
  83. data/spec/functional/associations_spec.rb +3 -3
  84. data/spec/functional/binary_spec.rb +2 -2
  85. data/spec/functional/caching_spec.rb +8 -15
  86. data/spec/functional/callbacks_spec.rb +89 -2
  87. data/spec/functional/counter_cache_spec.rb +89 -0
  88. data/spec/functional/dirty_spec.rb +84 -46
  89. data/spec/functional/dirty_with_callbacks_spec.rb +59 -0
  90. data/spec/functional/document_spec.rb +2 -5
  91. data/spec/functional/dumpable_spec.rb +1 -1
  92. data/spec/functional/embedded_document_spec.rb +17 -17
  93. data/spec/functional/identity_map_spec.rb +29 -16
  94. data/spec/functional/indexes_spec.rb +19 -18
  95. data/spec/functional/keys_spec.rb +55 -28
  96. data/spec/functional/logger_spec.rb +3 -3
  97. data/spec/functional/modifiers_spec.rb +81 -19
  98. data/spec/functional/partial_updates_spec.rb +577 -0
  99. data/spec/functional/protected_spec.rb +14 -14
  100. data/spec/functional/querying_spec.rb +77 -28
  101. data/spec/functional/safe_spec.rb +23 -27
  102. data/spec/functional/sci_spec.rb +9 -9
  103. data/spec/functional/scopes_spec.rb +323 -2
  104. data/spec/functional/static_keys_spec.rb +153 -0
  105. data/spec/functional/stats_spec.rb +28 -16
  106. data/spec/functional/strong_parameters_spec.rb +49 -0
  107. data/spec/functional/touch_spec.rb +1 -1
  108. data/spec/functional/validations_spec.rb +51 -57
  109. data/spec/quality_spec.rb +2 -2
  110. data/spec/spec_helper.rb +37 -9
  111. data/spec/support/matchers.rb +5 -14
  112. data/spec/unit/associations/base_spec.rb +12 -12
  113. data/spec/unit/associations/belongs_to_association_spec.rb +2 -2
  114. data/spec/unit/associations/many_association_spec.rb +2 -2
  115. data/spec/unit/associations/one_association_spec.rb +2 -2
  116. data/spec/unit/associations/proxy_spec.rb +26 -20
  117. data/spec/unit/clone_spec.rb +1 -1
  118. data/spec/unit/document_spec.rb +8 -8
  119. data/spec/unit/dynamic_finder_spec.rb +8 -8
  120. data/spec/unit/embedded_document_spec.rb +18 -19
  121. data/spec/unit/extensions_spec.rb +17 -17
  122. data/spec/unit/identity_map_middleware_spec.rb +65 -96
  123. data/spec/unit/key_spec.rb +28 -26
  124. data/spec/unit/keys_spec.rb +20 -11
  125. data/spec/unit/mongo_mapper_spec.rb +38 -85
  126. data/spec/unit/serialization_spec.rb +1 -1
  127. data/spec/unit/time_zones_spec.rb +2 -2
  128. data/spec/unit/validations_spec.rb +46 -33
  129. metadata +56 -32
  130. data/README.rdoc +0 -59
  131. data/lib/mongo_mapper/connections/10gen.rb +0 -0
  132. data/lib/mongo_mapper/connections/moped.rb +0 -0
  133. data/lib/mongo_mapper/extensions/ordered_hash.rb +0 -23
@@ -23,11 +23,9 @@ describe "Caching" do
23
23
  end
24
24
 
25
25
  it "should work with suffix" do
26
- @doc.cache_key(:foo).
27
- should == 'Post/new/foo'
26
+ @doc.cache_key(:foo).should == 'Post/new/foo'
28
27
 
29
- @doc.cache_key(:foo, :bar).
30
- should == 'Post/new/foo/bar'
28
+ @doc.cache_key(:foo, :bar).should == 'Post/new/foo/bar'
31
29
  end
32
30
  end
33
31
 
@@ -35,7 +33,7 @@ describe "Caching" do
35
33
  before do
36
34
  @object_id = BSON::ObjectId.new
37
35
  @doc = @klass.new
38
- @doc.stub(:persisted).and_return(true)
36
+ @doc.stub(:persisted?).and_return(true)
39
37
  @doc.stub(:id).and_return(@object_id)
40
38
  end
41
39
 
@@ -50,11 +48,9 @@ describe "Caching" do
50
48
  end
51
49
 
52
50
  it "should work with suffix" do
53
- @doc.cache_key(:foo).
54
- should == "Post/#{@object_id}-20100620081007/foo"
51
+ @doc.cache_key(:foo).should == "Post/#{@object_id}-20100620081007/foo"
55
52
 
56
- @doc.cache_key(:foo, :bar).
57
- should == "Post/#{@object_id}-20100620081007/foo/bar"
53
+ @doc.cache_key(:foo, :bar).should == "Post/#{@object_id}-20100620081007/foo/bar"
58
54
  end
59
55
  end
60
56
 
@@ -64,12 +60,9 @@ describe "Caching" do
64
60
  end
65
61
 
66
62
  it "should work with suffix" do
67
- @doc.cache_key(:foo).
68
- should == "Post/#{@object_id}/foo"
69
-
70
- @doc.cache_key(:foo, :bar, :baz).
71
- should == "Post/#{@object_id}/foo/bar/baz"
63
+ @doc.cache_key(:foo).should == "Post/#{@object_id}/foo"
64
+ @doc.cache_key(:foo, :bar, :baz).should == "Post/#{@object_id}/foo/bar/baz"
72
65
  end
73
66
  end
74
67
  end
75
- end
68
+ end
@@ -148,11 +148,11 @@ describe "Callbacks" do
148
148
  @root_class.define_callbacks :after_publish
149
149
  @root_class.after_save { |d| d.run_callbacks(:after_publish) }
150
150
 
151
- expect {
151
+ lambda {
152
152
  child = @child_class.new(:name => 'Child')
153
153
  root = @root_class.create(:name => 'Parent', :children => [child])
154
154
  child.history.should_not include(:after_publish)
155
- }.to_not raise_error
155
+ }.should_not raise_error
156
156
  end
157
157
  end
158
158
 
@@ -240,4 +240,91 @@ describe "Callbacks" do
240
240
  doc.message.should == 'Ho!'
241
241
  end
242
242
  end
243
+
244
+ describe "after_find" do
245
+ before do
246
+ @found_objects = []
247
+ found_objects = @found_objects # use a local for closure
248
+
249
+ @doc_class = Doc("User") do
250
+ after_find :set_found_object
251
+
252
+ define_method :set_found_object do
253
+ found_objects << self
254
+ end
255
+ end
256
+ end
257
+
258
+ it "should run after finding an object with find!" do
259
+ @doc = @doc_class.create!
260
+
261
+ @doc_class.find!(@doc.id)
262
+ @found_objects.should == [@doc]
263
+ end
264
+
265
+ it "should not have run if nothing was queried" do
266
+ @found_objects.should == []
267
+ end
268
+
269
+ it "should run for multiple objects" do
270
+ @doc1 = @doc_class.create!
271
+ @doc2 = @doc_class.create!
272
+
273
+ @doc_class.all
274
+ @found_objects.should == [@doc1, @doc2]
275
+ end
276
+
277
+ it "should run after finding an object through the query proxy" do
278
+ @doc = @doc_class.create!
279
+ @doc_class.where(:_id => @doc.id).first
280
+ @found_objects.should == [@doc]
281
+ end
282
+
283
+ it "should still return the object" do
284
+ @doc = @doc_class.create!
285
+ @doc_class.where(:_id => @doc.id).first.should == @doc
286
+ end
287
+
288
+ it "should not bail if the method return false" do
289
+ @doc_class = Doc("User") do
290
+ after_find :set_found_object
291
+
292
+ define_method :set_found_object do
293
+ false
294
+ end
295
+ end
296
+
297
+ @doc = @doc_class.create!
298
+ @doc_class.where(:_id => @doc.id).first.should == @doc
299
+ end
300
+ end
301
+
302
+ describe "after_initialize" do
303
+ before do
304
+ @objects = []
305
+ objects = @objects
306
+
307
+ @doc_class = Doc("User") do
308
+ after_initialize :set_initialized_object
309
+
310
+ define_method :set_initialized_object do
311
+ objects << self
312
+ end
313
+ end
314
+ end
315
+
316
+ it "should be triggered for objects created with new" do
317
+ @objects.should == []
318
+ obj = @doc_class.new
319
+ @objects.should == [obj]
320
+ end
321
+
322
+ it "should be triggered for objects found in the db" do
323
+ @doc = @doc_class.create!
324
+ @objects.clear # don't re-assign as we want the operation to be in place
325
+
326
+ @doc_class.all
327
+ @objects.should == [@doc]
328
+ end
329
+ end
243
330
  end
@@ -15,6 +15,7 @@ module CounterCacheFixtureModels
15
15
 
16
16
  key :comments_count, Integer, :default => 0
17
17
  key :some_custom_comments_count, Integer, :default => 0
18
+ key :commentable_count, Integer, :default => 0
18
19
 
19
20
  has_many :comments,
20
21
  :class_name => "CounterCacheFixtureModels::Comment"
@@ -22,6 +23,20 @@ module CounterCacheFixtureModels
22
23
  belongs_to :user,
23
24
  :counter_cache => true,
24
25
  :class_name => "CounterCacheFixtureModels::User"
26
+
27
+ many :polymorphic_comments,
28
+ :as => :commentable,
29
+ :class_name => "CounterCacheFixtureModels::Comment"
30
+ end
31
+
32
+ class Article
33
+ include MongoMapper::Document
34
+
35
+ key :commentable_count, Integer, :default => 0
36
+
37
+ many :polymorphic_comments,
38
+ :as => :commentable,
39
+ :class_name => "CounterCacheFixtureModels::Comment"
25
40
  end
26
41
 
27
42
  class Comment
@@ -30,6 +45,10 @@ module CounterCacheFixtureModels
30
45
  belongs_to :post,
31
46
  :counter_cache => true,
32
47
  :class_name => "CounterCacheFixtureModels::Post"
48
+
49
+ belongs_to :commentable,
50
+ :polymorphic => true,
51
+ :counter_cache => :commentable_count
33
52
  end
34
53
 
35
54
  class CustomComment
@@ -143,4 +162,74 @@ describe MongoMapper::Plugins::CounterCache do
143
162
  end
144
163
  }.should raise_error(MongoMapper::Plugins::CounterCache::InvalidCounterCacheError, "Missing `key :invalid_field, Integer, :default => 0' on model CounterCacheFixtureModels::Post")
145
164
  end
165
+
166
+ describe "with polymorphic associations" do
167
+ before do
168
+ @article = CounterCacheFixtureModels::Article.new
169
+ @comment = CounterCacheFixtureModels::Comment.new
170
+ @comment.commentable = @article
171
+ end
172
+
173
+ it "should update the counter cache on save" do
174
+ lambda {
175
+ @comment.save!
176
+ @article.reload
177
+ }.should change(@article, :commentable_count).by(1)
178
+ end
179
+
180
+ it "should increment with a second object" do
181
+ @comment.save!
182
+
183
+ lambda {
184
+ second_comment = CounterCacheFixtureModels::Comment.new
185
+ second_comment.commentable = @article
186
+ second_comment.save!
187
+ @article.reload
188
+ }.should change(@article, :commentable_count).by(1)
189
+ end
190
+
191
+ it "should decrement the counter cache on destroy" do
192
+ @comment.save!
193
+
194
+ lambda {
195
+ @comment.destroy
196
+ @article.reload
197
+ }.should change(@article, :commentable_count).by(-1)
198
+ end
199
+
200
+ it "should increment with a different type of object" do
201
+ @comment.save!
202
+
203
+ lambda {
204
+ second_comment = CounterCacheFixtureModels::Comment.new
205
+ second_comment.commentable = @article
206
+ second_comment.save!
207
+
208
+ @article.reload
209
+ }.should change(@article, :commentable_count).by(1)
210
+ end
211
+
212
+ describe "without a counter cache field" do
213
+ before do
214
+ @comment = CounterCacheFixtureModels::Comment.new
215
+ @klass = Class.new do
216
+ include MongoMapper::Document
217
+
218
+ many :polymorphic_comments,
219
+ :as => :commentable,
220
+ :class_name => "CounterCacheFixtureModels::Comment"
221
+ end
222
+
223
+ @obj = @klass.new
224
+ end
225
+
226
+ it "should raise at save (runtime) if there is no counter cache field" do
227
+ @comment.commentable = @obj
228
+
229
+ lambda {
230
+ @comment.save!
231
+ }.should raise_error(MongoMapper::Plugins::CounterCache::InvalidCounterCacheError)
232
+ end
233
+ end
234
+ end
146
235
  end
@@ -9,40 +9,47 @@ describe "Dirty" do
9
9
  end
10
10
 
11
11
  context "marking changes" do
12
+ it "should have the changed? methods" do
13
+ obj = @document.new
14
+ obj.should respond_to(:changed?)
15
+ obj.should respond_to(:phrase_changed?)
16
+ obj.should respond_to(:paragraph_changed?)
17
+ end
18
+
12
19
  it "should not happen if there are none" do
13
20
  doc = @document.new
14
- doc.phrase_changed?.should be_false
21
+ doc.phrase_changed?.should be_falsey
15
22
  doc.phrase_change.should be_nil
16
23
  end
17
24
 
18
25
  it "should happen when change happens" do
19
26
  doc = @document.new
20
27
  doc.phrase = 'Golly Gee Willikers Batman'
21
- doc.phrase_changed?.should be_true
28
+ doc.phrase_changed?.should be_truthy
22
29
  doc.phrase_was.should be_nil
23
30
  doc.phrase_change.should == [nil, 'Golly Gee Willikers Batman']
24
31
  end
25
32
 
26
33
  it "should happen when initializing" do
27
34
  doc = @document.new(:phrase => 'Foo')
28
- doc.changed?.should be_true
35
+ doc.changed?.should be_truthy
29
36
  end
30
37
 
31
38
  it "should clear changes on save" do
32
39
  doc = @document.new
33
40
  doc.phrase = 'Golly Gee Willikers Batman'
34
- doc.phrase_changed?.should be_true
41
+ doc.phrase_changed?.should be_truthy
35
42
  doc.save
36
- doc.phrase_changed?.should_not be_true
43
+ doc.phrase_changed?.should_not be_truthy
37
44
  doc.phrase_change.should be_nil
38
45
  end
39
46
 
40
47
  it "should clear changes on save!" do
41
48
  doc = @document.new
42
49
  doc.phrase = 'Golly Gee Willikers Batman'
43
- doc.phrase_changed?.should be_true
50
+ doc.phrase_changed?.should be_truthy
44
51
  doc.save!
45
- doc.phrase_changed?.should_not be_true
52
+ doc.phrase_changed?.should_not be_truthy
46
53
  doc.phrase_change.should be_nil
47
54
  end
48
55
 
@@ -51,33 +58,33 @@ describe "Dirty" do
51
58
  @document.any_instance.should_receive(:attribute_will_change!).never
52
59
  @document.any_instance.should_receive(:attribute_changed?).never
53
60
  doc = @document.find(doc.id)
54
- doc.changed?.should be_false
61
+ doc.changed?.should be_falsey
55
62
  end
56
63
 
57
64
  it "should not happen when reloading from database" do
58
65
  doc = @document.create(:phrase => 'Foo')
59
66
  doc = @document.find(doc.id)
60
67
 
61
- doc.changed?.should be_false
68
+ doc.changed?.should be_falsey
62
69
  doc.phrase = 'Fart'
63
- doc.changed?.should be_true
70
+ doc.changed?.should be_truthy
64
71
  doc.reload
65
- doc.changed?.should be_false
72
+ doc.changed?.should be_falsey
66
73
  end
67
74
 
68
75
  it "should happen if changed after loading from database" do
69
76
  doc = @document.create(:phrase => 'Foo')
70
77
  doc.reload
71
- doc.changed?.should be_false
78
+ doc.changed?.should be_falsey
72
79
  doc.phrase = 'Bar'
73
- doc.changed?.should be_true
80
+ doc.changed?.should be_truthy
74
81
  end
75
82
 
76
83
  it "should happen with aliased keys" do
77
84
  doc = @document.create(:paragraph => 'Wibbly')
78
85
  doc.paragraph = "Wobbly"
79
- doc.changed?.should be_true
80
- doc.paragraph_changed?.should be_true
86
+ doc.changed?.should be_truthy
87
+ doc.paragraph_changed?.should be_truthy
81
88
  end
82
89
  end
83
90
 
@@ -88,7 +95,7 @@ describe "Dirty" do
88
95
  [nil, ''].each do |value|
89
96
  doc = @document.new
90
97
  doc.age = value
91
- doc.age_changed?.should be_false
98
+ doc.age_changed?.should be_falsey
92
99
  doc.age_change.should be_nil
93
100
  end
94
101
  end
@@ -101,7 +108,7 @@ describe "Dirty" do
101
108
  [nil, ''].each do |value|
102
109
  doc = @document.new
103
110
  doc.amount = value
104
- doc.amount_changed?.should be_false
111
+ doc.amount_changed?.should be_falsey
105
112
  doc.amount_change.should be_nil
106
113
  end
107
114
  end
@@ -111,27 +118,27 @@ describe "Dirty" do
111
118
  it "should be true if key changed" do
112
119
  doc = @document.new
113
120
  doc.phrase = 'A penny saved is a penny earned.'
114
- doc.changed?.should be_true
121
+ doc.changed?.should be_truthy
115
122
  end
116
123
 
117
124
  it "should be false if no keys changed" do
118
- @document.new.changed?.should be_false
125
+ @document.new.changed?.should be_falsey
119
126
  end
120
127
 
121
128
  it "should not raise when key name is 'value'" do
122
129
  @document.key :value, Integer
123
130
 
124
131
  doc = @document.new
125
- doc.value_changed?.should be_false
132
+ doc.value_changed?.should be_falsey
126
133
  end
127
134
 
128
135
  it "should be false if the same ObjectId was assigned in String format" do
129
136
  @document.key :doc_id, ObjectId
130
137
 
131
138
  doc = @document.create!(:doc_id => BSON::ObjectId.new)
132
- doc.changed?.should be_false
139
+ doc.changed?.should be_falsey
133
140
  doc.doc_id = doc.doc_id.to_s
134
- doc.changed?.should be_false
141
+ doc.changed?.should be_falsey
135
142
  end
136
143
  end
137
144
 
@@ -164,14 +171,14 @@ describe "Dirty" do
164
171
  doc = @document.create(:phrase => 'Foo')
165
172
 
166
173
  doc.phrase << 'bar'
167
- doc.phrase_changed?.should be_false
174
+ doc.phrase_changed?.should be_falsey
168
175
 
169
176
  doc.phrase_will_change!
170
- doc.phrase_changed?.should be_true
177
+ doc.phrase_changed?.should be_truthy
171
178
  doc.phrase_change.should == ['Foobar', 'Foobar']
172
179
 
173
180
  doc.phrase << '!'
174
- doc.phrase_changed?.should be_true
181
+ doc.phrase_changed?.should be_truthy
175
182
  doc.phrase_change.should == ['Foobar', 'Foobar!']
176
183
  end
177
184
  end
@@ -190,7 +197,7 @@ describe "Dirty" do
190
197
 
191
198
  milestone = milestone_class.create(:name => 'Launch')
192
199
  milestone.project = project_class.create(:name => 'Harmony')
193
- milestone.changed?.should be_true
200
+ milestone.changed?.should be_truthy
194
201
  milestone.changed.should == %w(project_id)
195
202
  end
196
203
  end
@@ -204,11 +211,11 @@ describe "Dirty" do
204
211
  validated_doc = validated_class.new
205
212
  validated_doc.name = "I'm a changin"
206
213
  validated_doc.save
207
- validated_doc.changed?.should be_true
214
+ validated_doc.changed?.should be_truthy
208
215
 
209
216
  validated_doc.required = 1
210
217
  validated_doc.save
211
- validated_doc.changed?.should be_false
218
+ validated_doc.changed?.should be_falsey
212
219
  end
213
220
  end
214
221
 
@@ -220,20 +227,26 @@ describe "Dirty" do
220
227
  doc.a = "d"
221
228
  doc.a_change.should == ["b","d"]
222
229
  end
223
- it "should reset changes when set back to the original value" do
224
- doc = @document.create(:a=>"b")
225
- doc.a = "c"
226
- doc.a = "b"
227
- doc.changed?.should be_false
228
- end
230
+
231
+ # TODO: ? Is this consistent with how ActiveRecord now works with changes?
232
+ # it "should reset changes when set back to the original value" do
233
+ # doc = @document.create(:a=>"b")
234
+ # doc.a = "c"
235
+ # doc.a = "b"
236
+ # doc.changed?.should be_falsey
237
+ # end
229
238
  end
230
239
 
231
240
  context "reset_attribute!" do
232
241
  it "should reset the attribute back to the previous value" do
233
242
  doc = @document.create(:a=>"b")
234
243
  doc.a = "c"
235
- doc.reset_a!
236
- doc.changed?.should be_false
244
+ if doc.respond_to?(:restore_a!)
245
+ doc.restore_a!
246
+ else
247
+ doc.reset_a!
248
+ end
249
+ doc.changed?.should be_falsey
237
250
  doc.a.should == "b"
238
251
  end
239
252
  it "should reset the attribute back to the original value after several changes" do
@@ -241,8 +254,12 @@ describe "Dirty" do
241
254
  doc.a = "c"
242
255
  doc.a = "d"
243
256
  doc.a = "e"
244
- doc.reset_a!
245
- doc.changed?.should be_false
257
+ if doc.respond_to?(:restore_a!)
258
+ doc.restore_a!
259
+ else
260
+ doc.reset_a!
261
+ end
262
+ doc.changed?.should be_falsey
246
263
  doc.a.should == "b"
247
264
  end
248
265
  end
@@ -263,6 +280,27 @@ describe "Dirty" do
263
280
  end
264
281
  end
265
282
 
283
+ context "Document having Array key with typecast option" do
284
+ before do
285
+ @author_id = BSON::ObjectId.new
286
+ @doc = Doc('Book') { key :author_ids, Array, typecast: "ObjectId" }
287
+ @doc.plugin MongoMapper::Plugins::Dirty
288
+ @book = @doc.create!(author_ids: [@author_id])
289
+ end
290
+
291
+ context "changed" do
292
+ it "should be empty if assigned the same array" do
293
+ @book.author_ids = [@author_id]
294
+ @book.changed.should be_empty
295
+ end
296
+
297
+ it "should be empty if assigned the same but before-typecasted array" do
298
+ @book.author_ids = [@author_id.to_s]
299
+ @book.changed.should be_empty
300
+ end
301
+ end
302
+ end
303
+
266
304
  context "Embedded documents" do
267
305
  before do
268
306
  @edoc = EDoc('Duck') { key :name, String }
@@ -275,21 +313,21 @@ describe "Dirty" do
275
313
 
276
314
  it "should track changes" do
277
315
  @duck.name = "hi"
278
- @duck.changed?.should be_true
316
+ @duck.changed?.should be_truthy
279
317
  end
280
318
 
281
319
  it "should clear changes when saved" do
282
320
  @duck.name = "hi"
283
- @duck.changed?.should be_true
321
+ @duck.changed?.should be_truthy
284
322
  @duck.save!
285
- @duck.changed?.should_not be_true
323
+ @duck.changed?.should_not be_truthy
286
324
  end
287
325
 
288
326
  it "should clear changes when the parent is saved" do
289
327
  @duck.name = "hi"
290
- @duck.changed?.should be_true
328
+ @duck.changed?.should be_truthy
291
329
  @doc.save!
292
- @duck.changed?.should_not be_true
330
+ @duck.changed?.should_not be_truthy
293
331
  end
294
332
 
295
333
  context "with nested embedded documents" do
@@ -302,14 +340,14 @@ describe "Dirty" do
302
340
 
303
341
  it "should track changes" do
304
342
  @dong.name = "hi"
305
- @dong.changed?.should be_true
343
+ @dong.changed?.should be_truthy
306
344
  end
307
345
 
308
346
  it "should clear changes when the root saves" do
309
347
  @dong.name = "hi"
310
- @dong.changed?.should be_true
348
+ @dong.changed?.should be_truthy
311
349
  @doc.save!
312
- @dong.changed?.should be_false
350
+ @dong.changed?.should be_falsey
313
351
  end
314
352
  end
315
353
  end