Skip to content

Commit cf89c6a

Browse files
authored
Merge pull request #805 from estolfo/RUBY-1111-custom-grid-file-id
RUBY-1111 Support custom GridFS file IDs
2 parents 909d21d + 74abc87 commit cf89c6a

File tree

4 files changed

+159
-15
lines changed

4 files changed

+159
-15
lines changed

lib/mongo/grid/fs_bucket.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,7 @@ def download_to_stream_by_name(filename, io, opts = {})
337337
# @param [ String ] filename The filename of the file to upload.
338338
# @param [ Hash ] opts The options for the write stream.
339339
#
340+
# @option opts [ Object ] :file_id An optional unique file id. An ObjectId is generated otherwise.
340341
# @option opts [ Integer ] :chunk_size Override the default chunk size.
341342
# @option opts [ Hash ] :write The write concern.
342343
# @option opts [ Hash ] :metadata User data for the 'metadata' field of the files
@@ -366,12 +367,13 @@ def open_upload_stream(filename, opts = {})
366367
# document for the filename in the files collection.
367368
#
368369
# @example Upload a file to the GridFS bucket.
369-
# fs.upload_from_stream('a-file.txt')
370+
# fs.upload_from_stream('a-file.txt', file)
370371
#
371372
# @param [ String ] filename The filename of the file to upload.
372373
# @param [ IO ] io The source io stream to upload from.
373374
# @param [ Hash ] opts The options for the write stream.
374375
#
376+
# @option opts [ Object ] :file_id An optional unique file id. An ObjectId is generated otherwise.
375377
# @option opts [ Integer ] :chunk_size Override the default chunk size.
376378
# @option opts [ Hash ] :write The write concern.
377379
# @option opts [ Hash ] :metadata User data for the 'metadata' field of the files

lib/mongo/grid/stream/write.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Write
2727
# @since 2.1.0
2828
attr_reader :fs
2929

30-
# @return [ BSON::ObjectId ] file_id The id of the file being uploaded.
30+
# @return [ Object ] file_id The id of the file being uploaded.
3131
#
3232
# @since 2.1.0
3333
attr_reader :file_id
@@ -50,6 +50,7 @@ class Write
5050
# @param [ FSBucket ] fs The GridFS bucket object.
5151
# @param [ Hash ] options The write stream options.
5252
#
53+
# @option opts [ Object ] :file_id The file id. An ObjectId is generated otherwise.
5354
# @option opts [ Integer ] :chunk_size Override the default chunk size.
5455
# @option opts [ Hash ] :write The write concern.
5556
# @option opts [ Hash ] :metadata User data for the 'metadata' field of the files collection document.
@@ -63,7 +64,7 @@ def initialize(fs, options)
6364
@fs = fs
6465
@length = 0
6566
@n = 0
66-
@file_id = BSON::ObjectId.new
67+
@file_id = options[:file_id] || BSON::ObjectId.new
6768
@options = options
6869
@filename = @options[:filename]
6970
@open = true

spec/mongo/grid/fs_bucket_spec.rb

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,25 @@
462462
it 'removes the file from the db' do
463463
expect(from_db).to be_nil
464464
end
465+
466+
context 'when a custom file id is used' do
467+
468+
let(:custom_file_id) do
469+
fs.upload_from_stream(filename, file, file_id: 'Custom ID')
470+
end
471+
472+
before do
473+
fs.delete(custom_file_id)
474+
end
475+
476+
let(:from_db) do
477+
fs.find_one(:filename => filename)
478+
end
479+
480+
it 'removes the file from the db' do
481+
expect(from_db).to be_nil
482+
end
483+
end
465484
end
466485

467486
context 'when a read stream is opened' do
@@ -526,6 +545,51 @@
526545
expect(io.size).to eq(0)
527546
end
528547
end
548+
549+
context 'when a custom file id is provided' do
550+
551+
let(:file) do
552+
File.open(__FILE__)
553+
end
554+
555+
let!(:file_id) do
556+
fs.open_upload_stream(filename, file_id: 'Custom ID') do |stream|
557+
stream.write(file)
558+
end.file_id
559+
end
560+
561+
context 'when a block is provided' do
562+
563+
let!(:stream) do
564+
fs.open_download_stream(file_id) do |stream|
565+
io.write(stream.read)
566+
end
567+
end
568+
569+
it 'yields the stream to the block' do
570+
expect(io.size).to eq(file.size)
571+
end
572+
end
573+
574+
context 'when a block is not provided' do
575+
576+
let!(:stream) do
577+
fs.open_download_stream(file_id)
578+
end
579+
580+
it 'returns a Stream::Read object' do
581+
expect(stream).to be_a(Mongo::Grid::FSBucket::Stream::Read)
582+
end
583+
584+
it 'does not close the stream' do
585+
expect(stream.closed?).to be(false)
586+
end
587+
588+
it 'does not yield the stream to the block' do
589+
expect(io.size).to eq(0)
590+
end
591+
end
592+
end
529593
end
530594

531595
describe '#download_to_stream' do
@@ -858,6 +922,21 @@
858922
it 'creates an ObjectId for the file' do
859923
expect(stream.file_id).to be_a(BSON::ObjectId)
860924
end
925+
926+
context 'when a custom file ID is provided' do
927+
928+
let(:stream) do
929+
fs.open_upload_stream(filename, file_id: 'Custom ID')
930+
end
931+
932+
it 'returns a Stream::Write object' do
933+
expect(stream).to be_a(Mongo::Grid::FSBucket::Stream::Write)
934+
end
935+
936+
it 'creates an ObjectId for the file' do
937+
expect(stream.file_id).to eq('Custom ID')
938+
end
939+
end
861940
end
862941

863942
context 'when a block is provided' do
@@ -958,6 +1037,17 @@
9581037
fs.open_upload_stream(filename, stream_options)
9591038
end
9601039

1040+
context 'when a custom file id is provided' do
1041+
1042+
let(:stream_options) do
1043+
{ file_id: 'Custom ID' }
1044+
end
1045+
1046+
it 'sets the file id on the stream' do
1047+
expect(stream.file_id).to eq('Custom ID')
1048+
end
1049+
end
1050+
9611051
context 'when a write option is specified' do
9621052

9631053
let(:stream_options) do

spec/mongo/grid/stream/write_spec.rb

Lines changed: 63 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383

8484
let(:extra_options) do
8585
{
86-
write: { w: (WRITE_CONCERN[:w] + 1) }
86+
write: { w: (WRITE_CONCERN[:w] + 1) }
8787
}
8888
end
8989

@@ -174,6 +174,19 @@
174174
expect(stream.send(:file_info).document[:aliases]).to eq(options[:aliases])
175175
end
176176
end
177+
178+
context 'when provided a file_id option' do
179+
180+
let(:options) do
181+
{
182+
file_id: 'Custom ID'
183+
}
184+
end
185+
186+
it 'assigns the stream the file id' do
187+
expect(stream.file_id).to eq(options[:file_id])
188+
end
189+
end
177190
end
178191
end
179192

@@ -285,25 +298,63 @@
285298

286299
context 'when provided an io stream' do
287300

288-
before do
289-
stream.write(file)
290-
stream.close
291-
end
301+
context 'when no file id is specified' do
292302

293-
it 'writes the contents of the stream' do
294-
expect(file_from_db.data.size).to eq(file.size)
295-
end
303+
before do
304+
stream.write(file)
305+
stream.close
306+
end
296307

297-
it 'updates the length written' do
298-
expect(stream.send(:file_info).document['length']).to eq(file.size)
308+
it 'writes the contents of the stream' do
309+
expect(file_from_db.data.size).to eq(file.size)
310+
end
311+
312+
it 'updates the length written' do
313+
expect(stream.send(:file_info).document['length']).to eq(file.size)
314+
end
315+
316+
it 'updates the position (n)' do
317+
expect(stream.instance_variable_get(:@n)).to eq(1)
318+
end
299319
end
300320

301-
it 'updates the position (n)' do
302-
expect(stream.instance_variable_get(:@n)).to eq(1)
321+
context 'when a custom file id is provided' do
322+
323+
let(:extra_options) do
324+
{
325+
file_id: 'Custom ID'
326+
}
327+
end
328+
329+
let!(:id) do
330+
stream.write(file)
331+
stream.close
332+
end
333+
334+
it 'writes the contents of the stream' do
335+
expect(file_from_db.data.size).to eq(file.size)
336+
end
337+
338+
it 'updates the length written' do
339+
expect(stream.send(:file_info).document['length']).to eq(file.size)
340+
end
341+
342+
it 'updates the position (n)' do
343+
expect(stream.instance_variable_get(:@n)).to eq(1)
344+
end
345+
346+
it 'uses the custom file id' do
347+
expect(id).to eq(options[:file_id])
348+
end
303349
end
304350

305351
context 'when the user file contains no data' do
306352

353+
before do
354+
stream.write(file)
355+
stream.close
356+
end
357+
307358
let(:file) do
308359
StringIO.new('')
309360
end

0 commit comments

Comments
 (0)