Class: Export::ZipStreamer
- Inherits:
-
Object
- Object
- Export::ZipStreamer
- Defined in:
- lib/export/zip_streamer.rb
Instance Method Summary collapse
- #build_entry_name(entry, used_names, file_name:, entry_id:) ⇒ Object private
- #reserve_name(name, used_names) ⇒ Object private
-
#stream(entries:, zip_streamer:, file_path:, file_name:, entry_id:, logger_prefix: 'ZipStreamer', on_entry: nil, after_stream: nil) ⇒ Object
Streams entries into a zip archive.
- #stream_file(entry, sink, file_path:, entry_id:) ⇒ Object private
- #write_error_fallback(zip) ⇒ Object private
Instance Method Details
#build_entry_name(entry, used_names, file_name:, entry_id:) ⇒ Object (private)
63 64 65 66 67 68 69 70 71 72 |
# File 'lib/export/zip_streamer.rb', line 63 def build_entry_name(entry, used_names, file_name:, entry_id:) base = file_name.call(entry).presence || "file_#{entry_id.call(entry)}" candidate = Zaru.sanitize!(base) return reserve_name(candidate, used_names) if used_names[candidate].nil? ext = File.extname(candidate) stem = File.basename(candidate, ext) disambiguated = "#{stem}-#{entry_id.call(entry)}#{ext}" reserve_name(Zaru.sanitize!(disambiguated), used_names) end |
#reserve_name(name, used_names) ⇒ Object (private)
74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/export/zip_streamer.rb', line 74 def reserve_name(name, used_names) final = name suffix = 1 ext = File.extname(name) stem = File.basename(name, ext) while used_names[final] suffix += 1 final = "#{stem}-#{suffix}#{ext}" end used_names[final] = true final end |
#stream(entries:, zip_streamer:, file_path:, file_name:, entry_id:, logger_prefix: 'ZipStreamer', on_entry: nil, after_stream: nil) ⇒ Object
Streams entries into a zip archive.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/export/zip_streamer.rb', line 30 def stream(entries:, zip_streamer:, file_path:, file_name:, entry_id:, logger_prefix: 'ZipStreamer', on_entry: nil, after_stream: nil) zip_streamer.call do |zip| written = false used_names = {} results = [] entries.each do |entry| begin name = build_entry_name( entry, used_names, file_name: file_name, entry_id: entry_id ) zip.write_deflated_file(name) do |sink| stream_file(entry, sink, file_path: file_path, entry_id: entry_id) end on_entry&.call(entry, name, results) written = true rescue StandardError => e Rails.logger.warn( "#{logger_prefix}: failed to stream entry #{entry_id.call(entry)}: #{e.class} #{e.}" ) end end after_stream&.call(zip, results, written) write_error_fallback(zip) unless written end end |
#stream_file(entry, sink, file_path:, entry_id:) ⇒ Object (private)
89 90 91 92 93 94 |
# File 'lib/export/zip_streamer.rb', line 89 def stream_file(entry, sink, file_path:, entry_id:) path = file_path.call(entry) raise "File missing for entry #{entry_id.call(entry)}" if path.blank? || !File.exist?(path) File.open(path, 'rb') { |io| IO.copy_stream(io, sink) } end |
#write_error_fallback(zip) ⇒ Object (private)
96 97 98 99 100 |
# File 'lib/export/zip_streamer.rb', line 96 def write_error_fallback(zip) zip.write_deflated_file('errors.txt') do |sink| sink.write("No files could be streamed for this package.\n") end end |