7

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?

chell
  • 7,646
  • 16
  • 74
  • 140
  • 1
    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? – Mark Oct 02 '18 at 10:15
  • 1
    I don't want to attach the zip file. I want to attach each file in the zip to a different instance of ProofreadDocument. – chell Oct 02 '18 at 10:40
  • Did you try to remove `read` from `file.get_input_stream.read`? – kangkyu Oct 05 '18 at 16:26
  • Yes and I get a different error. – chell Oct 08 '18 at 03:25

1 Answers1

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)
chell
  • 7,646
  • 16
  • 74
  • 140
  • 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 uses – Blair Anderson Feb 06 '19 at 23:39
  • 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! :) – Gabor Lengyel Jul 11 '19 at 19:02