2

I have this working locally, storing the template files in #{Rails.root}/tmp, using system "cd tmp/template; zip -r ../#{@filename} *" to zip up the files, sending the .docx (zip archive) to S3 and then to the browser. The problem is that Heroku is not finding the files. Before I create the xml file, I am copying the template directory from another location (system "cp -R support/ser_template tmp/"). I understand Heroku's read-only filesystem but I can't have #{Process.pid}'s littering my filenames (Word requires the xml file to be named document.xml).

Is there anyway I can store the template files on Amazon and still use Heroku's system zip utility? RubyZip does not create proper docx archives.

Edit: here is the code:

require 'aws/s3'

class WordDocument
  include ConnectS3

  def initialize(content)
    connect_s3
    @pid = Process.pid
    @filename = "SER_" + Time.now.strftime("%Y%m%d-%H%M%S") + '.docx'
    system "cp -R #{Rails.root}/support/ser_template #{temp_path}"
    xml = File.open(xml_path, 'w')
    xml.puts content
    xml.close
    system "cd #{temp_path}; zip -r #{@filename} *"
    docx = File.open(temp_path + "/" + @filename, 'r')
    AWS::S3::S3Object.store(s3_path, docx, @s3_credentials["bucket"], :use_virtual_directories => true)
    AWS::S3::S3Object.grant_torrent_access_to s3_path, @s3_credentials["bucket"]
  end

  def temp_path
    "#{Rails.root}/tmp/#{@pid}_ser"
  end

  def xml_path
    temp_path + "/word/document.xml"
  end

  def path
    "https://s3.amazonaws.com/" + @s3_credentials["bucket"] + s3_path
  end

  def s3_path
    '/section_editor_reports/' + @filename
  end
end
Reed G. Law
  • 3,897
  • 1
  • 41
  • 78

1 Answers1

3

Can't you just a create directory within #{Rails.root}/tmp called, say, #{Process.pid}_docx/something_nice/? Copy (or symlink) what you need into:

#{Rails.root}/tmp/#{Process.pid}_docx/something_nice/

Then

system "cd #{Rails.root}/tmp/#{Process.pid}_docx/; zip -r x.zip something_nice"

And then you have:

#{Rails.root}/tmp/#{Process.pid}_docx/x.zip

With a nice pretty internal structure that doesn't include your PID.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • I still get `Errno::ENOENT` `No such file or directory - /app/tmp/1_ser/word/document.xml` – Reed G. Law Jun 21 '11 at 13:01
  • Heroku. I've now tried it on 3 different stacks (bamboo 1.8.7, bamboo 1.9.2, and Cedar). I get `No such file or directory` on all but bamboo 1.9.2 where I get `Permission denied - /app/tmp/1_ser/word/document.xml` – Reed G. Law Jun 21 '11 at 17:42
  • @Reed: Are you creating the directory in one process but trying to access it in another? Is it the copying or the zipping that complains? – mu is too short Jun 21 '11 at 18:06
  • I'm creating and zipping the files in one process (a user requests a Word export and an xml template is generated from a view using `render_to_string`). I'm getting the error on this line: `xml = File.open(xml_path, 'w')` – Reed G. Law Jun 21 '11 at 18:23
  • @Reed: Have you checked the permissions on the directory you made or what your umask is on Heroku? – mu is too short Jun 21 '11 at 19:49
  • `umask` in the console returns `nil`. The permissions on the `tmp` directory are `drwx------ 4 u14017 14017 4.0K Jun 28 18:44 tmp\ ` – Reed G. Law Jun 28 '11 at 22:48
  • @Reed: What about the permissions on the files and directories that you just copied over? You might want to use `cpio` to copy the files but that's another issue. – mu is too short Jun 28 '11 at 23:12
  • They are `dr-xr-x--- 5 root 24129 4.0K Jun 28 18:08 ser_template` and I tried `xml = File.open("#{Rails.root}/tmp/1_ser/word/document.xml", 'w')` on the console but got permission denied. – Reed G. Law Jun 29 '11 at 00:21
  • @Reed: Can you [`File.chmod`](http://www.ruby-doc.org/core/classes/File.html#M000010) the directories and files? 0755 for the directories and 0644 for the files should be good. – mu is too short Jun 29 '11 at 00:38
  • I had this error - Heroku likes to add 'app/' to the temp path which is incorrect. You want './tmp' not './app/tmp'. Here's a fix: `rails_root = Rails.root.to_s.gsub('/app','')` – Chris Nolet Jun 02 '12 at 19:17