How can I use rubyzip to attach files in a zip archive to an ActiveStorage object Rails 5
Asked Answered
S

1

8

I have a model with one attachment that uses ActiveStorage:

class ProofreadDocument < ApplicationRecord

  has_one_attached :file

end

I am working on a rake task to attach files to a proofread_document. The files are compressed into a zip archive.

I understand that I can attach the files as follows from reading the ActiveStorage docs:

@proofread_document.file.attach(io: File.open('/path/to/file'), filename: 'file.pdf')

I have the following in my rake task:

    Zip::File.open(args.path_to_directory) do |zipfile|
          zipfile.each do |file|
            proofread_document = ProofreadDocument.new()
            proofread_document.file.attach(io: file.get_input_stream.read, filename: file.name)
            proofread_document.save
          end
     end

This produces the following error:

NoMethodError: undefined method `read' for #<String:0x007f8d894d95e0>

I need to read the contents of each file one at at time to attach them to the proofread_document instance. How can I do this?

Sarilda answered 2/10, 2018 at 10:10 Comment(4)
Do you need to do any processing on the zip file? If not why can't you just attach it directly in your first step, without bothering with any of the rake task?Reardon
I don't want to attach the zip file. I want to attach each file in the zip to a different instance of ProofreadDocument.Sarilda
Did you try to remove read from file.get_input_stream.read?Buccinator
Yes and I get a different error.Sarilda
S
9

I was able to succeed by wrapping the input stream in a StringIO object as follows:

self.file.attach(io: StringIO.new(zip_entry.get_input_stream.read), filename: zip_entry.name, content_type: MS_WORD_CONTENT_TYPE)
Sarilda answered 12/10, 2018 at 4:56 Comment(2)
Can you update to include your FULL code example here? it looks like you have a different variable name in this section than your question usesBohr
It's such a pity that attach tries to call #size on zip_entry.get_input_stream when trying that directly for io. If size could be passed to attach separately, it would just work directly with io: zip_entry.get_input_stream. Thanks for this hack though! :)Micky

© 2022 - 2024 — McMap. All rights reserved.