gnuside-carrierwave-mongoid 0.6.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ module Carrierwave
2
+ module Mongoid
3
+ VERSION = "0.6.6"
4
+ end
5
+ end
@@ -0,0 +1,114 @@
1
+ # encoding: utf-8
2
+
3
+ module CarrierWave
4
+ module Storage
5
+
6
+ ##
7
+ # The GridFS store uses MongoDB's GridStore file storage system to store files
8
+ #
9
+ # When you already have a Mongo connection object (for example through Mongoid)
10
+ # you can also reuse this connection:
11
+ #
12
+ # CarrierWave.configure do |config|
13
+ # config.storage = :grid_fs
14
+ # config.grid_fs_access_url = "/system/uploads"
15
+ # end
16
+ #
17
+ # In the above example your documents url will look like:
18
+ #
19
+ # http://your-app.com/system/uploads/:document-identifier-here
20
+ #
21
+ class GridFS < Abstract
22
+
23
+ class File
24
+ attr_reader :path
25
+ attr_reader :uploader
26
+ attr_reader :grid_file
27
+
28
+ def initialize(uploader, path)
29
+ @path = path
30
+ @uploader = uploader
31
+ @grid_file = nil
32
+ end
33
+
34
+ def url
35
+ unless @uploader.grid_fs_access_url
36
+ nil
37
+ else
38
+ ::File.join(@uploader.grid_fs_access_url, path)
39
+ end
40
+ end
41
+
42
+ def grid_file(&block)
43
+ @grid_file ||= grid[path]
44
+ end
45
+
46
+ def write(file)
47
+ grid[@uploader.store_path] = file
48
+ ensure
49
+ @grid_file = nil
50
+ end
51
+
52
+ def read
53
+ grid_file.data if grid_file
54
+ end
55
+
56
+ %w( delete content_type length ).each do |method|
57
+ class_eval <<-__, __FILE__, __LINE__
58
+ def #{ method }
59
+ grid_file.#{ method } if grid_file
60
+ end
61
+ __
62
+ end
63
+
64
+ alias :content_length :length
65
+ alias :file_length :length
66
+ alias :size :length
67
+
68
+ protected
69
+ class << File
70
+ attr_accessor :grid
71
+ end
72
+
73
+ self.grid = ::Mongoid::GridFS
74
+
75
+ def grid
76
+ self.class.grid
77
+ end
78
+ end # File
79
+
80
+ ##
81
+ # Store the file in MongoDB's GridFS GridStore
82
+ #
83
+ # === Parameters
84
+ #
85
+ # [file (CarrierWave::SanitizedFile)] the file to store
86
+ #
87
+ # === Returns
88
+ #
89
+ # [CarrierWave::SanitizedFile] a sanitized file
90
+ #
91
+ def store!(file)
92
+ stored = CarrierWave::Storage::GridFS::File.new(uploader, uploader.store_path)
93
+ stored.write(file)
94
+ stored
95
+ end
96
+
97
+ ##
98
+ # Retrieve the file from MongoDB's GridFS GridStore
99
+ #
100
+ # === Parameters
101
+ #
102
+ # [identifier (String)] the filename of the file
103
+ #
104
+ # === Returns
105
+ #
106
+ # [CarrierWave::Storage::GridFS::File] a sanitized file
107
+ #
108
+ def retrieve!(identifier)
109
+ CarrierWave::Storage::GridFS::File.new(uploader, uploader.store_path(identifier))
110
+ end
111
+
112
+ end # GridFS
113
+ end # Storage
114
+ end # CarrierWave
@@ -0,0 +1 @@
1
+ require 'carrierwave/mongoid'
@@ -0,0 +1 @@
1
+ this is stuff
@@ -0,0 +1 @@
1
+ bork bork bork Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
@@ -0,0 +1 @@
1
+ this is stuff
@@ -0,0 +1 @@
1
+ bork bork bork Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Binary file
@@ -0,0 +1 @@
1
+ this is stuff
@@ -0,0 +1 @@
1
+ this is stuff
@@ -0,0 +1,879 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+
4
+ require 'carrierwave/mongoid'
5
+
6
+ def reset_mongo_class(uploader = MongoUploader)
7
+ define_mongo_class('MongoUser') do
8
+ include Mongoid::Document
9
+ store_in :collection => 'users'
10
+ field :folder, :default => ''
11
+ mount_uploader :image, uploader
12
+ end
13
+ end
14
+
15
+ def define_mongo_class(class_name, &block)
16
+ Object.send(:remove_const, class_name) rescue nil
17
+ klass = Object.const_set(class_name, Class.new)
18
+ klass.class_eval(&block)
19
+ klass
20
+ end
21
+
22
+ class MongoUploader < CarrierWave::Uploader::Base; end
23
+ class AnotherMongoUploader < CarrierWave::Uploader::Base; end
24
+
25
+ class IntegrityErrorUploader < CarrierWave::Uploader::Base
26
+ process :monkey
27
+ def monkey
28
+ raise CarrierWave::IntegrityError
29
+ end
30
+ def extension_white_list
31
+ %w(jpg)
32
+ end
33
+ end
34
+
35
+ class ProcessingErrorUploader < CarrierWave::Uploader::Base
36
+ process :monkey
37
+ def monkey
38
+ raise CarrierWave::ProcessingError
39
+ end
40
+ def extension_white_list
41
+ %w(jpg)
42
+ end
43
+ end
44
+
45
+
46
+ describe CarrierWave::Mongoid do
47
+
48
+ after do
49
+ MongoUser.collection.drop if MongoUser.count > 0
50
+ end
51
+
52
+ describe '#image' do
53
+
54
+ context "when nothing is assigned" do
55
+
56
+ before do
57
+ mongo_user_klass = reset_mongo_class
58
+ @document = mongo_user_klass.new
59
+ end
60
+
61
+ it "returns a blank uploader" do
62
+ @document.image.should be_blank
63
+ end
64
+
65
+ end
66
+
67
+ context "when an empty string is assigned" do
68
+
69
+ before do
70
+ mongo_user_klass = reset_mongo_class
71
+ @document = mongo_user_klass.new(:image => "")
72
+ @document.save
73
+ end
74
+
75
+ it "returns a blank uploader" do
76
+ @saved_doc = MongoUser.first
77
+ @saved_doc.image.should be_blank
78
+ end
79
+
80
+ end
81
+
82
+ context "when a filename is saved in the database" do
83
+
84
+ before do
85
+ mongo_user_klass = reset_mongo_class
86
+ @document = mongo_user_klass.new
87
+ # should retrieve a file from the storage if a value is stored in the database
88
+ @document[:image] = "test.jpg" # NOT @document.image = 'text.jpg'
89
+ @document.save
90
+ @doc = MongoUser.first
91
+ end
92
+
93
+ it "returns an uploader" do
94
+ @doc.image.should be_an_instance_of(MongoUploader)
95
+ end
96
+
97
+ it "sets the path to the store directory" do
98
+ @doc.image.current_path.should == public_path('uploads/test.jpg')
99
+ end
100
+
101
+ it "should return valid JSON when to_json is called when image is nil" do
102
+ @doc[:image] = nil
103
+ hash = JSON.parse(@doc.to_json)
104
+ hash.keys.should include("image")
105
+ hash["image"].keys.should include("url")
106
+ hash["image"]["url"].should be_nil
107
+ end
108
+
109
+ it "should return valid JSON when to_json is called when image is present" do
110
+ @doc[:image] = 'test.jpeg'
111
+ @doc.save!
112
+ @doc.reload
113
+
114
+ JSON.parse(@doc.to_json)["image"].should == {"url" => "/uploads/test.jpeg"}
115
+ end
116
+
117
+ it "should return valid JSON when to_json is called on a collection containing uploader from a model" do
118
+ @doc[:image] = 'test.jpeg'
119
+ @doc.save!
120
+ @doc.reload
121
+
122
+ JSON.parse({:data => @doc.image}.to_json).should == {"data"=>{"image"=>{"url"=>"/uploads/test.jpeg"}}}
123
+ end
124
+
125
+ it "should respect options[:only] when passed to to_json for the serializable hash" do
126
+ @doc[:image] = 'test.jpeg'
127
+ @doc.save!
128
+ @doc.reload
129
+ JSON.parse(@doc.to_json({:only => [:_id]})).should == {"_id" => @doc.id.as_json}
130
+ end
131
+
132
+ it "should respect options[:except] when passed to to_json for the serializable hash" do
133
+ @doc[:image] = 'test.jpeg'
134
+ @doc.save!
135
+ @doc.reload
136
+
137
+ JSON.parse(@doc.to_json({:except => [:_id, :image]})).should == {"folder" => ""}
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+
144
+ describe '#image=' do
145
+
146
+ before do
147
+ mongo_user_klass = reset_mongo_class
148
+ @doc = mongo_user_klass.new
149
+ end
150
+
151
+ context "when nil is assigned" do
152
+
153
+ it "does not set the value" do
154
+ @doc.image = nil
155
+ @doc.image.should be_blank
156
+ end
157
+
158
+ end
159
+
160
+ context "when an empty string is assigned" do
161
+
162
+ it "does not set the value" do
163
+ @doc.image = ''
164
+ @doc.image.should be_blank
165
+ end
166
+
167
+ end
168
+
169
+ context "when a file is assigned" do
170
+
171
+ it "should cache a file" do
172
+ @doc.image = stub_file('test.jpeg')
173
+ @doc.image.should be_an_instance_of(MongoUploader)
174
+ end
175
+
176
+ it "should write nothing to the database, to prevent overriden filenames to fail because of unassigned attributes" do
177
+ @doc[:image].should be_nil
178
+ end
179
+
180
+ it "should copy a file into into the cache directory" do
181
+ @doc.image = stub_file('test.jpeg')
182
+ @doc.image.current_path.should =~ /^#{public_path('uploads\/tmp')}/
183
+ end
184
+
185
+ end
186
+
187
+ context 'when validating integrity' do
188
+ before do
189
+ mongo_user_klass = reset_mongo_class(IntegrityErrorUploader)
190
+ @doc = mongo_user_klass.new
191
+ @doc.image = stub_file('test.jpg')
192
+ end
193
+
194
+ it "should make the document invalid when an integrity error occurs" do
195
+ @doc.should_not be_valid
196
+ end
197
+
198
+ it "should use I18n for integrity error messages" do
199
+ @doc.valid?
200
+ @doc.errors[:image].should == ['is not of an allowed file type']
201
+
202
+ change_locale_and_store_translations(:pt, :mongoid => {
203
+ :errors => {
204
+ :messages => {
205
+ :carrierwave_integrity_error => 'tipo de imagem não permitido.'
206
+ }
207
+ }
208
+ }) do
209
+ @doc.should_not be_valid
210
+ @doc.errors[:image].should == ['tipo de imagem não permitido.']
211
+ end
212
+ end
213
+ end
214
+
215
+ context 'when validating processing' do
216
+ before do
217
+ mongo_user_klass = reset_mongo_class(ProcessingErrorUploader)
218
+ @doc = mongo_user_klass.new
219
+ @doc.image = stub_file('test.jpg')
220
+ end
221
+
222
+ it "should make the document invalid when a processing error occurs" do
223
+ @doc.should_not be_valid
224
+ end
225
+
226
+ it "should use I18n for processing error messages" do
227
+ @doc.valid?
228
+ @doc.errors[:image].should == ['failed to be processed']
229
+
230
+ change_locale_and_store_translations(:pt, :mongoid => {
231
+ :errors => {
232
+ :messages => {
233
+ :carrierwave_processing_error => 'falha ao processar imagem.'
234
+ }
235
+ }
236
+ }) do
237
+ @doc.should_not be_valid
238
+ @doc.errors[:image].should == ['falha ao processar imagem.']
239
+ end
240
+ end
241
+ end
242
+
243
+ end
244
+
245
+ describe "#save" do
246
+
247
+ it "after it was initialized with params" do
248
+ doc = reset_mongo_class.new(:image => stub_file('test.jpg'))
249
+ doc.save.should be_true
250
+ doc.image.should be_an_instance_of(MongoUploader)
251
+ doc.image.current_path.should == public_path('uploads/test.jpg')
252
+ end
253
+
254
+ before do
255
+ mongo_user_klass = reset_mongo_class
256
+ @doc = mongo_user_klass.new
257
+ end
258
+
259
+ context "when no file is assigned" do
260
+
261
+ it "image is blank" do
262
+ @doc.save.should be_true
263
+ @doc.image.should be_blank
264
+ end
265
+
266
+ end
267
+
268
+ context "when a file is assigned" do
269
+
270
+ it "copies the file to the upload directory" do
271
+ @doc.image = stub_file('test.jpg')
272
+ @doc.save.should be_true
273
+ @doc.image.should be_an_instance_of(MongoUploader)
274
+ @doc.image.current_path.should == public_path('uploads/test.jpg')
275
+ end
276
+
277
+ it "saves the filename in the database" do
278
+ @doc.image = stub_file('test.jpg')
279
+ @doc.save.should be_true
280
+ @doc[:image].should == 'test.jpg'
281
+ @doc.image_identifier.should == 'test.jpg'
282
+ end
283
+
284
+ context "when remove_image? is true" do
285
+
286
+ it "removes the image" do
287
+ @doc.image = stub_file('test.jpeg')
288
+ @doc.save
289
+ @doc.remove_image = true
290
+ @doc.save.should be_true
291
+ @doc.reload
292
+ @doc.image.should be_blank
293
+ @doc.image_identifier.should == ''
294
+ end
295
+
296
+ end
297
+
298
+ it "should mark image as changed when saving a new image" do
299
+ @doc.image_changed?.should be_false
300
+ @doc.image = stub_file("test.jpeg")
301
+ @doc.image_changed?.should be_true
302
+ @doc.save
303
+ @doc.reload
304
+ @doc.image_changed?.should be_false
305
+ @doc.image = stub_file("test.jpg")
306
+ @doc.image_changed?.should be_true
307
+ end
308
+
309
+ end
310
+
311
+ end
312
+
313
+ describe '#update' do
314
+
315
+ before do
316
+ mongo_user_klass = reset_mongo_class
317
+ @doc = mongo_user_klass.new
318
+ @doc.image = stub_file('test.jpeg')
319
+ @doc.save
320
+ @doc.reload
321
+ end
322
+
323
+ it "replaced it by a file with the same name" do
324
+ @doc.image = stub_file('test.jpeg')
325
+ @doc.save
326
+ @doc.reload
327
+ @doc[:image].should == 'test.jpeg'
328
+ @doc.image_identifier.should == 'test.jpeg'
329
+ end
330
+
331
+ end
332
+
333
+ describe '#destroy' do
334
+
335
+ before do
336
+ mongo_user_klass = reset_mongo_class
337
+ @doc = mongo_user_klass.new
338
+ end
339
+
340
+ describe "when file assigned" do
341
+
342
+ it "removes the file from the filesystem" do
343
+ @doc.image = stub_file('test.jpeg')
344
+ @doc.save.should be_true
345
+ File.exist?(public_path('uploads/test.jpeg')).should be_true
346
+ @doc.image.should be_an_instance_of(MongoUploader)
347
+ @doc.image.current_path.should == public_path('uploads/test.jpeg')
348
+ @doc.destroy
349
+ File.exist?(public_path('uploads/test.jpeg')).should be_false
350
+ end
351
+
352
+ end
353
+
354
+ describe "when file is not assigned" do
355
+
356
+ it "deletes the instance of MongoUser after save" do
357
+ @doc.save
358
+ MongoUser.count.should eql(1)
359
+ @doc.destroy
360
+ end
361
+
362
+ it "deletes the instance of MongoUser after save and then re-looking up the instance" do
363
+ @doc.save
364
+ MongoUser.count.should eql(1)
365
+ @doc = MongoUser.first
366
+ @doc.destroy
367
+ end
368
+
369
+ end
370
+
371
+ end
372
+
373
+ describe '#mount_uploader removing old files' do
374
+
375
+ before do
376
+ @uploader = Class.new(MongoUploader)
377
+ @class = reset_mongo_class(@uploader)
378
+ @class.field :foo
379
+ @doc = @class.new
380
+ @doc.image = stub_file('old.jpeg')
381
+ @doc.save.should be_true
382
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
383
+ end
384
+
385
+ after do
386
+ FileUtils.rm_rf(file_path("uploads"))
387
+ end
388
+
389
+ describe 'normally' do
390
+
391
+ it "should remove old file if old file had a different path" do
392
+ @doc.image = stub_file('new.jpeg')
393
+ @doc.save.should be_true
394
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
395
+ File.exists?(public_path('uploads/old.jpeg')).should be_false
396
+ end
397
+
398
+ it "should not remove old file if old file had a different path but config is false" do
399
+ @uploader.stub(:remove_previously_stored_files_after_update).and_return(false)
400
+ @doc.image = stub_file('new.jpeg')
401
+ @doc.save.should be_true
402
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
403
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
404
+ end
405
+
406
+ it "should not remove file if old file had the same path" do
407
+ @doc.image = stub_file('old.jpeg')
408
+ @doc.save.should be_true
409
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
410
+ end
411
+
412
+ it "should not remove file if validations fail on save" do
413
+ @class.validate { |r| r.errors.add :textfile, "FAIL!" }
414
+ @doc.image = stub_file('new.jpeg')
415
+ @doc.save.should be_false
416
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
417
+ end
418
+ end
419
+
420
+ describe 'with an overriden filename' do
421
+ before do
422
+ @uploader.class_eval do
423
+ def filename
424
+ model.foo + File.extname(super)
425
+ end
426
+ end
427
+
428
+ @doc.image = stub_file('old.jpeg')
429
+ @doc.foo = "test"
430
+ @doc.save.should be_true
431
+ File.exists?(public_path('uploads/test.jpeg')).should be_true
432
+ @doc.image.read.should == "this is stuff"
433
+ end
434
+
435
+ it "should not remove file if old file had the same dynamic path" do
436
+ @doc.image = stub_file('test.jpeg')
437
+ @doc.save.should be_true
438
+ File.exists?(public_path('uploads/test.jpeg')).should be_true
439
+ end
440
+
441
+ it "should remove old file if old file had a different dynamic path" do
442
+ @doc.foo = "new"
443
+ @doc.image = stub_file('test.jpeg')
444
+ @doc.save.should be_true
445
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
446
+ File.exists?(public_path('uploads/test.jpeg')).should be_false
447
+ end
448
+ end
449
+
450
+ shared_examples "embedded documents" do
451
+ it "should remove old file if old file had a different path" do
452
+ @embedded_doc.image = stub_file('new.jpeg')
453
+ @embedded_doc.save.should be_true
454
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
455
+ File.exists?(public_path('uploads/old.jpeg')).should be_false
456
+ end
457
+
458
+ it "should not remove old file if old file had a different path but config is false" do
459
+ @embedded_doc.image.stub(:remove_previously_stored_files_after_update).and_return(false)
460
+ @embedded_doc.image = stub_file('new.jpeg')
461
+ @embedded_doc.save.should be_true
462
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
463
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
464
+ end
465
+
466
+ it "should not remove file if old file had the same path" do
467
+ @embedded_doc.image = stub_file('old.jpeg')
468
+ @embedded_doc.save.should be_true
469
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
470
+ end
471
+
472
+ it "should not remove file if validations fail on save" do
473
+ @embedded_doc_class.validate { |r| r.errors.add :textfile, "FAIL!" }
474
+ @embedded_doc.image = stub_file('new.jpeg')
475
+ @embedded_doc.save.should be_false
476
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
477
+ end
478
+
479
+ it "should not touch parent's dirty attributes" do
480
+ @class.field :title
481
+ @doc.title = "Title"
482
+ @embedded_doc.image = stub_file('new.jpeg')
483
+ @embedded_doc.save.should be_true
484
+ @doc.title.should == "Title"
485
+ end
486
+ end
487
+
488
+ shared_examples "double embedded documents" do
489
+ it "should remove old file if old file had a different path" do
490
+ @double_embedded_doc.image = stub_file('new.jpeg')
491
+ @double_embedded_doc.save.should be_true
492
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
493
+ File.exists?(public_path('uploads/old.jpeg')).should be_false
494
+ end
495
+
496
+ it "should not remove old file if old file had a different path but config is false" do
497
+ @double_embedded_doc.image.stub(:remove_previously_stored_files_after_update).and_return(false)
498
+ @double_embedded_doc.image = stub_file('new.jpeg')
499
+ @double_embedded_doc.save.should be_true
500
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
501
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
502
+ end
503
+
504
+ it "should not remove file if old file had the same path" do
505
+ @double_embedded_doc.image = stub_file('old.jpeg')
506
+ @double_embedded_doc.save.should be_true
507
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
508
+ end
509
+
510
+ it "should not remove file if validations fail on save" do
511
+ @double_embedded_doc_class.validate { |r| r.errors.add :textfile, "FAIL!" }
512
+ @double_embedded_doc.image = stub_file('new.jpeg')
513
+ @double_embedded_doc.save.should be_false
514
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
515
+ end
516
+
517
+ end
518
+
519
+ describe 'with document embedded as embeds_one' do
520
+ before do
521
+ @embedded_doc_class = define_mongo_class('MongoLocation') do
522
+ include Mongoid::Document
523
+ mount_uploader :image, @uploader
524
+ embedded_in :mongo_user
525
+ end
526
+
527
+ @class.class_eval do
528
+ embeds_one :mongo_location
529
+ end
530
+
531
+ @doc = @class.new
532
+ @embedded_doc = @doc.build_mongo_location
533
+ @embedded_doc.image = stub_file('old.jpeg')
534
+ @embedded_doc.save.should be_true
535
+ end
536
+
537
+ include_examples "embedded documents"
538
+ end
539
+
540
+ describe 'with document embedded as embeds_one and parent document not matched the default scope' do
541
+ before do
542
+ @embedded_doc_class = define_mongo_class('MongoLocation') do
543
+ include Mongoid::Document
544
+ mount_uploader :image, @uploader
545
+ embedded_in :mongo_user
546
+ end
547
+
548
+ @class.class_eval do
549
+ embeds_one :mongo_location
550
+ default_scope where(:always_false => false)
551
+ end
552
+
553
+ @doc = @class.new
554
+ @embedded_doc = @doc.build_mongo_location
555
+ @embedded_doc.image = stub_file('old.jpeg')
556
+ @embedded_doc.save.should be_true
557
+ end
558
+
559
+ include_examples "embedded documents"
560
+ end
561
+
562
+ describe 'with embedded documents' do
563
+ before do
564
+ @embedded_doc_class = define_mongo_class('MongoLocation') do
565
+ include Mongoid::Document
566
+ mount_uploader :image, @uploader
567
+ embedded_in :mongo_user
568
+ end
569
+
570
+ @class.class_eval do
571
+ embeds_many :mongo_locations, cascade_callbacks: true
572
+ accepts_nested_attributes_for :mongo_locations
573
+ end
574
+
575
+ @doc = @class.new
576
+ @embedded_doc = @doc.mongo_locations.build
577
+ @embedded_doc.image = stub_file('old.jpeg')
578
+ @embedded_doc.save.should be_true
579
+ end
580
+
581
+ include_examples "embedded documents"
582
+
583
+ it "attaches a new file to an existing document that had no file at first" do
584
+ doc = @class.new
585
+ doc.mongo_locations.build
586
+ doc.save.should be_true
587
+ doc.reload
588
+
589
+ doc.mongo_locations.first.image = stub_file('test.jpeg')
590
+ doc.save.should be_true
591
+ doc.reload
592
+
593
+ doc.mongo_locations.first[:image].should == 'test.jpeg'
594
+ end
595
+
596
+ it "changes the file" do
597
+ @doc.update_attributes mongo_locations_attributes: { '0' => { _id: @embedded_doc._id, image: stub_file('test.jpeg') } }
598
+ @doc.reload
599
+ @doc.mongo_locations.first[:image].should == 'test.jpeg'
600
+ end
601
+
602
+ it "removes a file" do
603
+ @doc.update_attributes mongo_locations_attributes: { '0' => { _id: @embedded_doc._id, remove_image: "1" } }
604
+ @doc.reload
605
+ @doc.mongo_locations.first[:image].should_not be_present
606
+ end
607
+
608
+ describe 'with double embedded documents' do
609
+
610
+ before do
611
+ @double_embedded_doc_class = define_mongo_class('MongoItem') do
612
+ include Mongoid::Document
613
+ mount_uploader :image, @uploader
614
+ embedded_in :mongo_location
615
+ end
616
+
617
+ @embedded_doc_class.class_eval do
618
+ embeds_many :mongo_items
619
+ end
620
+
621
+ @doc = @class.new
622
+ @embedded_doc = @doc.mongo_locations.build
623
+ @embedded_doc.image = stub_file('old.jpeg')
624
+ @embedded_doc.save.should be_true
625
+
626
+ @double_embedded_doc = @embedded_doc.mongo_items.build
627
+ @double_embedded_doc.image = stub_file('old.jpeg')
628
+ @double_embedded_doc.save.should be_true
629
+ end
630
+
631
+ include_examples "double embedded documents"
632
+ end
633
+ end
634
+
635
+ describe 'with embedded documents and parent document not matched the default scope' do
636
+ before do
637
+ @embedded_doc_class = define_mongo_class('MongoLocation') do
638
+ include Mongoid::Document
639
+ mount_uploader :image, @uploader
640
+ embedded_in :mongo_user
641
+ end
642
+
643
+ @class.class_eval do
644
+ embeds_many :mongo_locations
645
+ default_scope where(:always_false => false)
646
+ end
647
+
648
+ @doc = @class.new
649
+ @embedded_doc = @doc.mongo_locations.build
650
+ @embedded_doc.image = stub_file('old.jpeg')
651
+ @embedded_doc.save.should be_true
652
+ end
653
+
654
+ include_examples "embedded documents"
655
+
656
+ describe 'with double embedded documents' do
657
+
658
+ before do
659
+ @double_embedded_doc_class = define_mongo_class('MongoItem') do
660
+ include Mongoid::Document
661
+ mount_uploader :image, @uploader
662
+ embedded_in :mongo_location
663
+ end
664
+
665
+ @embedded_doc_class.class_eval do
666
+ embeds_many :mongo_items
667
+ end
668
+
669
+ @doc = @class.new
670
+ @embedded_doc = @doc.mongo_locations.build
671
+ @embedded_doc.image = stub_file('old.jpeg')
672
+ @embedded_doc.save.should be_true
673
+
674
+ @double_embedded_doc = @embedded_doc.mongo_items.build
675
+ @double_embedded_doc.image = stub_file('old.jpeg')
676
+ @double_embedded_doc.save.should be_true
677
+ end
678
+
679
+ include_examples "double embedded documents"
680
+ end
681
+ end
682
+
683
+ describe 'with embedded documents and nested attributes' do
684
+ before do
685
+ @embedded_doc_class = define_mongo_class('MongoLocation') do
686
+ include Mongoid::Document
687
+ mount_uploader :image, @uploader
688
+ embedded_in :mongo_user
689
+ end
690
+
691
+ @class.class_eval do
692
+ embeds_many :mongo_locations, cascade_callbacks: true
693
+ accepts_nested_attributes_for :mongo_locations
694
+ end
695
+
696
+ @doc = @class.new(mongo_locations_attributes: [{image: stub_file("old.jpeg")}])
697
+ @doc.save.should be_true
698
+ @embedded_doc = @doc.mongo_locations.first
699
+ end
700
+
701
+ it "should set the image on a save" do
702
+ @doc.reload
703
+ @doc.mongo_locations.first.image.path.should match(/old\.jpeg$/)
704
+ @embedded_doc.image.path.should match(/old\.jpeg$/)
705
+ end
706
+
707
+ it "should update the image on update_attributes" do
708
+ @doc.update_attributes(mongo_locations_attributes: [{id: @embedded_doc.id, image: stub_file("new.jpeg")}]).should be_true
709
+ @doc.reload
710
+ @doc.mongo_locations.first.image.path.should match(/new\.jpeg$/)
711
+ @embedded_doc.image.path.should match(/new\.jpeg$/)
712
+ end
713
+ end
714
+ end
715
+
716
+ describe '#mount_uploader removing old files with versions' do
717
+
718
+ before do
719
+ @uploader = Class.new(MongoUploader)
720
+ @uploader.version :thumb
721
+ @class = reset_mongo_class(@uploader)
722
+ @doc = @class.new
723
+ @doc.image = stub_file('old.jpeg')
724
+ @doc.save.should be_true
725
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
726
+ File.exists?(public_path('uploads/thumb_old.jpeg')).should be_true
727
+ end
728
+
729
+ after do
730
+ FileUtils.rm_rf(file_path("uploads"))
731
+ end
732
+
733
+ it "should remove old file if old file had a different path" do
734
+ @doc.image = stub_file('new.jpeg')
735
+ @doc.save.should be_true
736
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
737
+ File.exists?(public_path('uploads/thumb_new.jpeg')).should be_true
738
+ File.exists?(public_path('uploads/old.jpeg')).should be_false
739
+ File.exists?(public_path('uploads/thumb_old.jpeg')).should be_false
740
+ end
741
+
742
+ it "should not remove file if old file had the same path" do
743
+ @doc.image = stub_file('old.jpeg')
744
+ @doc.save.should be_true
745
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
746
+ File.exists?(public_path('uploads/thumb_old.jpeg')).should be_true
747
+ end
748
+ end
749
+
750
+ describe '#mount_uploader removing old files with multiple uploaders' do
751
+
752
+ before do
753
+ @uploader = Class.new(MongoUploader)
754
+ @class = reset_mongo_class(@uploader)
755
+ @uploader1 = Class.new(CarrierWave::Uploader::Base)
756
+ @class.mount_uploader(:textfile, @uploader1)
757
+ @doc = @class.new
758
+ @doc.image = stub_file('old.jpeg')
759
+ @doc.textfile = stub_file('old.txt')
760
+ @doc.save.should be_true
761
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
762
+ File.exists?(public_path('uploads/old.txt')).should be_true
763
+ end
764
+
765
+ after do
766
+ FileUtils.rm_rf(file_path("uploads"))
767
+ end
768
+
769
+ it "should remove old file1 and file2 if old file1 and file2 had a different paths" do
770
+ @doc.image = stub_file('new.jpeg')
771
+ @doc.textfile = stub_file('new.txt')
772
+ @doc.save.should be_true
773
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
774
+ File.exists?(public_path('uploads/old.jpeg')).should be_false
775
+ File.exists?(public_path('uploads/new.txt')).should be_true
776
+ File.exists?(public_path('uploads/old.txt')).should be_false
777
+ end
778
+
779
+ it "should remove old file1 but not file2 if old file1 had a different path but old file2 has the same path" do
780
+ @doc.image = stub_file('new.jpeg')
781
+ @doc.textfile = stub_file('old.txt')
782
+ @doc.save.should be_true
783
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
784
+ File.exists?(public_path('uploads/old.jpeg')).should be_false
785
+ File.exists?(public_path('uploads/old.txt')).should be_true
786
+ end
787
+
788
+ it "should not remove file1 or file2 if file1 and file2 have the same paths" do
789
+ @doc.image = stub_file('old.jpeg')
790
+ @doc.textfile = stub_file('old.txt')
791
+ @doc.save.should be_true
792
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
793
+ File.exists?(public_path('uploads/old.txt')).should be_true
794
+ end
795
+ end
796
+
797
+ describe '#mount_uploader removing old files with with mount_on' do
798
+
799
+ before do
800
+ @class = reset_mongo_class
801
+ @uploader1 = Class.new(CarrierWave::Uploader::Base)
802
+ @class.mount_uploader(:avatar, @uploader1, :mount_on => :another_image)
803
+ @doc = @class.new
804
+ @doc.avatar = stub_file('old.jpeg')
805
+ @doc.save.should be_true
806
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
807
+ end
808
+
809
+ after do
810
+ FileUtils.rm_rf(file_path("uploads"))
811
+ end
812
+
813
+ it "should remove old file if old file had a different path" do
814
+ @doc.avatar = stub_file('new.jpeg')
815
+ @doc.save.should be_true
816
+ File.exists?(public_path('uploads/new.jpeg')).should be_true
817
+ File.exists?(public_path('uploads/old.jpeg')).should be_false
818
+ end
819
+
820
+ it "should not remove file if old file had the same path" do
821
+ @doc.avatar = stub_file('old.jpeg')
822
+ @doc.save.should be_true
823
+ File.exists?(public_path('uploads/old.jpeg')).should be_true
824
+ end
825
+ end
826
+
827
+ # Mongoid::Paranoia support is only part of Mongoid 3.x. It was removed from
828
+ # Mongoid 4.x.
829
+ if defined?(Mongoid::Paranoia)
830
+ describe "with paranoia enabled" do
831
+ before do
832
+ @class = reset_mongo_class
833
+ @class.collection.drop
834
+ @class.class_eval do
835
+ include Mongoid::Paranoia
836
+ end
837
+
838
+ @doc = @class.new(image: stub_file("old.jpeg"))
839
+ @doc.save.should be_true
840
+ end
841
+
842
+ it "should not remove underlying image after #destroy" do
843
+ @doc.destroy.should be_true
844
+ @class.count.should eql(0)
845
+ @class.deleted.count.should eql(1)
846
+ File.exist?(public_path('uploads/old.jpeg')).should be_true
847
+ end
848
+
849
+ it "should remove underlying image after #destroy!" do
850
+ @doc.destroy!.should be_true
851
+ @class.count.should eql(0)
852
+ @class.deleted.count.should eql(0)
853
+ File.exist?(public_path('uploads/old.jpeg')).should be_false
854
+ end
855
+ end
856
+ end
857
+
858
+ context "JSON serialization with multiple uploaders" do
859
+ before do
860
+ @class = reset_mongo_class
861
+ @class.send(:mount_uploader, :textfile,AnotherMongoUploader)
862
+ @event = @class.new
863
+ @event.image = stub_file('old.jpeg')
864
+ @event.textfile = stub_file('old.txt')
865
+ end
866
+
867
+ it "serializes the correct values" do
868
+ @event.serializable_hash["image"]["url"].should match(/old\.jpeg$/)
869
+ @event.serializable_hash["textfile"]["url"].should match(/old\.txt$/)
870
+ end
871
+
872
+ it "should have JSON for each uploader" do
873
+ parsed = JSON.parse(@event.to_json)
874
+ parsed["image"]["url"].should match(/old\.jpeg$/)
875
+ parsed["textfile"]["url"].should match(/old\.txt$/)
876
+ end
877
+ end
878
+
879
+ end