Rails 3 Heroku app, FileUtils error server side - ruby-on-rails

I am attempting to code a very simple way for a user to add html files to my Heroku app. These files would be saved in ./log for rendering later. I have tested my code locally (in both development and production), but when I attempt to upload a file on my Heroku hosted repo I get internal server error 500.
controller upload.rb:
class UploadController < ApplicationController
def index
render :file => 'upload/uploadfile.haml'
end
def uploadFile
file_param = params[:upload][:datafile]
post = DataFile.save(file_param)
render :text => "File has been uploaded successfully"
end
end
model data_file.rb:
class DataFile < ActiveRecord::Base
def self.save(upload)
# Changed Default Destination: [__RAILS_DIR__/log]
name = "./log/" + upload.original_filename
# can haz data directory?
require 'FileUtils'
FileUtils.mkdir_p(File.dirname(name))
File.open(name, "wb") { |f| f.write(upload.read) }
end
end
view uploadfile.haml:
%h1 File Upload
= form_for :upload,:url=>{:action => 'uploadFile'},:html => { :multipart => true } do |f|
%p
%label{:for => "upload_file"} Select File
\:
\#{f.file_field 'datafile'}
= f.submit "Upload"
heroku logs:
2012-08-07T14:13:20+00:00 app[web.1]: Started POST "/uploadFile" for 69.29.117.99 at 2012-08-07 14:13:20 +0000
2012-08-07T14:13:20+00:00 app[web.1]: Processing by UploadController#uploadFile as HTML
2012-08-07T14:13:20+00:00 app[web.1]: Parameters: {"utf8"=>"✓", "authenticity_token"=>"1dAXkMulNR0d8S/l6QC8JnpSDtNBaHoyKJezgnheR10=", "upload"=>{"datafile"=>#>}, "commit"=>"Upload"}
2012-08-07T14:13:20+00:00 app[web.1]: Completed 500 Internal Server Error in 3ms
2012-08-07T14:13:20+00:00 app[web.1]:
2012-08-07T14:13:20+00:00 app[web.1]: LoadError (no such file to load -- FileUtils):
2012-08-07T14:13:20+00:00 app[web.1]: app/models/data_file.rb:7:in save'
2012-08-07T14:13:20+00:00 app[web.1]: app/controllers/upload_controller.rb:8:inuploadFile'
2012-08-07T14:13:20+00:00 app[web.1]:
2012-08-07T14:13:20+00:00 app[web.1]:
2012-08-07T14:13:20+00:00 app[web.1]: cache: [POST /uploadFile] invalidate, pass
heroku: http://upload-example.herokuapp.com/
github: https://github.com/halterj1/upload
Please no trying to convince me to use paperclip or carrierwave, that does not answer my question. Any help would be greatly appreciated, thanks in advance guys!

You should read this article on heroku: https://devcenter.heroku.com/articles/read-only-filesystem
edit:
As stated in article.
Your app is compiled into a slug for fast distribution across the dyno manifold. The filesystem for the slug is read-only, which means you cannot dynamically write to the filesystem for semi-permanent storage. The following types of behaviors are not supported:
Caching pages in the public directory
Saving uploaded assets to local disk (e.g. with attachment_fu or paperclip)
Writing full-text indexes with Ferret
Writing to a filesystem database like SQLite or GDBM
Accessing a git repo for an app like git-wiki
There are two directories that are writeable: ./tmp and ./log (under your application root). If you wish to drop a file temporarily for the duration of the request, you can write to a filename like #{RAILS_ROOT}/tmp/myfile_#{Process.pid}. There is no guarantee that this file will be there on subsequent requests (although it might be), so this should not be used for any kind of permanent storage.

Related

Saving a PDF to file

I have code to write a file to save a PDF and then upload it to s3. What I have works perfectly in dev. but not in production.
def upload_to_s3(pdf)
save_path = "#{Rails.root}/tmp/pdfs/invoice_#{#invoice.id}.pdf"
f = File.new(save_path, 'w:ASCII-8BIT')
f.write(pdf)
uploader = InvoiceUploader.new
File.open(save_path) { |file| uploader.store!(file) }
#invoice.update(pdf: uploader.url)
File.delete(save_path)
uploader.url
end
Stack Trace:
Rendered invoices/pdf.html.erb (6.5ms)
Completed 500 Internal Server Error in 1420ms (ActiveRecord: 34.6ms)
Errno::ENOENT (No such file or directory # rb_sysopen - /home/deploy/reputation/releases/20180401031049/tmp/pdfs/invoice_2.pdf):
app/controllers/api/v1/invoices_controller.rb:140:in `initialize'
[5e443877-e7fe-4848-847b-f5f6159e7db9]
app/controllers/api/v1/invoices_controller.rb:140:in `new'
[5e443877-e7fe-4848-847b-f5f6159e7db9]
app/controllers/api/v1/invoices_controller.rb:140:in `upload_to_s3'
[5e443877-e7fe-4848-847b-f5f6159e7db9]
app/controllers/api/v1/invoices_controller.rb:65:in `pdf'
The error message clearly states:
Errno::ENOENT (No such file or directory # rb_sysopen - /home/deploy/reputation/releases/20180401031049/tmp/pdfs/invoice_2.pdf): ...
Create the directory /home/deploy/reputation/releases/20180401031049/tmp/pdfs/ in production upfront. Since it’s dynamic (dependent on the release datetime,) it’s better to create it in your ruby code:
save_dir = "#{Rails.root}/tmp/pdfs/"
Dir.mkdir(save_dir)
save_path = ...

Can upload but not delete image on Heroku using Paperclip and AWS S3

S3 credentials are configured correctly for Paperclip:
# production.rb (same in development.rb)
config.paperclip_defaults = {
:storage => :s3,
:path => 'photos/:id/:style/:filename',
:s3_credentials => {
:bucket => ENV['aws_bucket'],
:access_key_id => ENV['aws_access_key'],
:secret_access_key => ENV['aws_secret_key']
}
}
I do see the environment variables set in the Heroku UI, and I can upload photos just fine.
However when I try to destroy the given model on production, I get this error in the log:
2016-01-14T15:48:48.079923+00:00 app[web.1]: Completed 500 Internal Server Error in 591ms (ActiveRecord: 60.3ms)
2016-01-14T15:48:48.082519+00:00 app[web.1]:
2016-01-14T15:48:48.082522+00:00 app[web.1]: AWS::Errors::MissingCredentialsError (
2016-01-14T15:48:48.082523+00:00 app[web.1]: Missing Credentials.
2016-01-14T15:48:48.082524+00:00 app[web.1]:
2016-01-14T15:48:48.082525+00:00 app[web.1]: Unable to find AWS credentials. You can configure your AWS credentials
2016-01-14T15:48:48.082526+00:00 app[web.1]: a few different ways:
2016-01-14T15:48:48.082526+00:00 app[web.1]:
2016-01-14T15:48:48.082527+00:00 app[web.1]: * Call AWS.config with :access_key_id and :secret_access_key
2016-01-14T15:48:48.082528+00:00 app[web.1]:
2016-01-14T15:48:48.082529+00:00 app[web.1]: * Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY to ENV
2016-01-14T15:48:48.082529+00:00 app[web.1]:
2016-01-14T15:48:48.082530+00:00 app[web.1]: * On EC2 you can run instances with an IAM instance profile and credentials
2016-01-14T15:48:48.082531+00:00 app[web.1]: will be auto loaded from the instance metadata service on those
2016-01-14T15:48:48.082531+00:00 app[web.1]: instances.
2016-01-14T15:48:48.082532+00:00 app[web.1]:
2016-01-14T15:48:48.082533+00:00 app[web.1]: * Call AWS.config with :credential_provider. A credential provider should
2016-01-14T15:48:48.082533+00:00 app[web.1]: either include AWS::Core::CredentialProviders::Provider or respond to
2016-01-14T15:48:48.082534+00:00 app[web.1]: the same public methods.
This all works just fine locally too (obviously using a different S3 bucket). What's the issue? Why am I getting AWS::Errors::MissingCredentialsError just on production even though uploads work fine?
You probably want to make sure you're on the aws-sdk gem v1 and not aws-sdk v2. Logs make it look like you're on v1 ("AWS::") -- if you're on aws-sdk v2, paperclip won't work. Don't think thoughtbot is going to support it going forward, I recommend you look into direct upload to s3 using jquery-file-uploader (https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails#pre-signed-post) -- Note that article does not show aws-sdk-v2 instructions. The answer linked below does use aws-sdk-v2:
Rails direct to S3 upload using aws-sdk gem and jQuery-File-Upload on heroku

Heroku can't find user but works in dev

I'm hitting a problem with my heroku deployment. Here is the log:
2014-04-29T16:41:59.782999+00:00 app[web.1]: Started GET "/lines/33/edit" for 94.174.113.168 at 2014-04-29 16:41:59 +0000
2014-04-29T16:41:59.782933+00:00 app[web.1]: Started GET "/lines/33/edit" for 94.174.113.168 at 2014-04-29 16:41:59 +0000
2014-04-29T16:41:59.804819+00:00 app[web.1]:
2014-04-29T16:41:59.804823+00:00 app[web.1]: ActiveRecord::RecordNotFound (Couldn't find User with id=0):
2014-04-29T16:41:59.804826+00:00 app[web.1]: app/views/lines/_history.html.erb:7:in `block in _app_views_lines__history_html_erb__3033746240219592358_69949428301200'
2014-04-29T16:41:59.804824+00:00 app[web.1]: config/initializers/paper_trail.rb:4:in `user'
2014-04-29T16:41:59.804854+00:00 app[web.1]: app/views/lines/_history.html.erb:4:in `_app_views_lines__history_html_erb__3033746240219592358_69949428301200'
2014-04-29T16:41:59.804828+00:00 app[web.1]: app/views/lines/_history.html.erb:4:in `each'
2014-04-29T16:41:59.804856+00:00 app[web.1]: app/views/lines/edit.html.erb:16:in `_app_views_lines_edit_html_erb__4129892984524241027_69949427894700'
2014-04-29T16:41:59.804869+00:00 app[web.1]: app/views/lines/_history.html.erb:4:in `each'
2014-04-29T16:41:59.804871+00:00 app[web.1]: app/views/lines/_history.html.erb:4:in `_app_views_lines__history_html_erb__3033746240219592358_69949428301200'
2014-04-29T16:41:59.804872+00:00 app[web.1]: app/views/lines/edit.html.erb:16:in `_app_views_lines_edit_html_erb__4129892984524241027_69949427894700'
2014-04-29T16:41:59.804875+00:00 app[web.1]:
2014-04-29T16:41:59.804874+00:00 app[web.1]:
2014-04-29T16:41:59.804857+00:00 app[web.1]:
2014-04-29T16:41:59.804858+00:00 app[web.1]:
2014-04-29T16:41:59.804864+00:00 app[web.1]:
2014-04-29T16:41:59.804865+00:00 app[web.1]: ActiveRecord::RecordNotFound (Couldn't find User with id=0):
2014-04-29T16:41:59.804866+00:00 app[web.1]: config/initializers/paper_trail.rb:4:in `user'
2014-04-29T16:41:59.804868+00:00 app[web.1]: app/views/lines/_history.html.erb:7:in `block in _app_views_lines__history_html_erb__3033746240219592358_69949428301200'
The offending initializer is as follows:
module PaperTrail
class Version < ActiveRecord::Base
def user
User.find self.whodunnit.to_i
end
def nextversion
self.next
end
end
end
Which is getting called in the _history view with the following:
<%= gravatar_for version.user %><%= link_to version.user.username, user_path(version.user) %>
This works fine in development and appears to work fine in production on most edit pages but on one I am encountering this error. I wanted to check the version in the console but it seems I can't access paper_trail Versions in the console at all, I can only assume this is because I don't have a Version model, only a table and a controller.
How can I fix this?
You are getting following error
ActiveRecord::RecordNotFound (Couldn't find User with id=0)
on the following method
def user
puts "Value of whodunnit is -----------> #{self.whodunnit}"
User.find self.whodunnit.to_i
end
which is called in
<%= gravatar_for version.user %><%= link_to version.user.username, user_path(version.user) %>
because self.whodunnit.to_i is returning 0. That means, whodunnit is either "" or nil or 0. Please set the correct value of whodunnit attribute. Also, you can check the current value of whodunnit by adding a logger or puts statement in PaperTrail::Version# user method.
You probably did not ran your seed.rb file (heroku run rake db:seed) to create the user or you just are looking for an user that is not defined anymore (like deleted for example).
When you delete a user that had id=0 the next user will have id=1.
Just for sure, o recommend that you enter on your console (heroku run console) and try to find it by yourself (Client.find(0)) or try to list all of them (Client.all) to see if the user with id=0 is defined.
Hope it helps

Heroku delete my uploaded files, why?

if I load the file in my app on Heroku, everything works, but when I tried again to reload the application, it gives me the following error:
2013-01-25T08:48:31+00:00 app[web.1]: app/controllers/main_controller.rb:20:in `index'
2013-01-25T08:48:31+00:00 app[web.1]:
2013-01-25T08:48:31+00:00 app[web.1]:
2013-01-25T08:48:31+00:00 app[web.1]: Errno::ENOENT (No such file or directory - /app/config/cases/casesID6.yml):
2013-01-25T08:48:31+00:00 app[web.1]: app/controllers/main_controller.rb:20:in `read'
LOCALLY IT WORK FINE !
main controller:
# importo yaml di configurazione
require 'yaml'
if Survey.exists?(1)
#idOfSurvey = Survey.find {|s| s['active_state'] == true}['id']
nameOfSurvey = "casesID"+String(#idOfSurvey)+".yml"
#survey = YAML::load(ERB.new(IO.read(File.join(Rails.root, 'config/cases', nameOfSurvey))).result)
else
render :action => 'noYaml' and return
end
upload controller :
#inserisco il nuovo questionario
survey = Survey.new
if Survey.exists?(1)
n = String(Integer(Survey.maximum("Id"))+1)
survey.name = "casesID#{n}"
else
survey.name = "casesID1"
end
File.open(Rails.root.join('config/cases', survey.name+".yml"), 'wb+') do |file|
file.write(uploaded_io.read)
end
survey.save()
I believe that my file uploaded to Heroku, may be cleared by the platform for issues of memory, for example, or because it saves them as temporary, is this possible? solutions!
I repeat, everything works fine locally :(
Whilst you can write to the Heroku filesystem once you scale, restart or push a new version of your code then the file will be gone.
You need to use a persistant file store such as Amazon S3, Rackspace or such like - read more at https://devcenter.heroku.com/articles/dynos#ephemeral-filesystem and use a gem like CarrierWave or Paperclip which make connecting to S3 super simple.

Rails 3.2 Carrierwave precompile error

I got a class AvatarUploader < Carrierwave::Uploader::Base which store User avatars in public/uploads dir:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :main do
process :resize_to_limit => [128, 128]
end
And I want to start application in production mode with assets precompilation enabled. Everything but avatars work fine. When I visit any User profile I get:
Started GET "/users/1" for 127.0.0.1 at 2012-05-03 17:45:24 +0300
Processing by Users::UsersController#show as HTML
Parameters: {"id"=>"1"}
Rendered users/users/show.html.erb within layouts/application (2.5ms)
Completed 500 Internal Server Error in 16ms
ActionView::Template::Error ( isn't precompiled):
87: <%= image_tag #user.avatar_url(:main).to_s %>
app/views/users/users/show.html.erb:87:in `_app_views_users_users_show_html_erb___538221278131396366_28399560'
Maybe there is a way to turn off precompilation for avatars(because they could be re-uploaded when app is running on production). Please provide any suggestions how to fix this issue. Thanks.
When image_tag receives a blank string, it tries to get a resource
from the asset pipeline and returns
"isn't precompiled"
https://github.com/rails/rails/issues/3080
Print #user.avatar_url(:main).to_s to double check

Resources