Rails upload excel file, validate and save - ruby-on-rails

I am working on a rails engine that uploads a excel file, validates it and if there is no error than it will save it to database.
Now when ever a user mounts the engine and than go to the route provided by engine. He will have a form to upload the excel file. There are two buttons on page, i.e, upload and validate.
Once a user choose the file and when he click on upload i want that file only gets uploaded and don't get saved in db. Once i get the message the file is uploaded successfully, than i will validate the file. If it is a valid excel file with valid data than it will be saved into db. Now i am not getting how to go about it. I have seen this Railscasts video on uploading csv and excel file but here he is performing validation and save operation with import action but i want validation and save operation when user clicks on validate action. This Questions seems similar to my problem but i am not getting how do i access that uploaded file. I don't want that file to be saved in database. I mean when a user click on upload button that file gets only uploaded not saved. Than i will validate that file and save it's content to db.
This may seem very easy and simple questions for some experts but i am very new to rails and i am not sure how to go about it.
Someone please help me with a sample code, so that i can understand the workflow. Also note that both upload and validate actions are on same page. So when a file gets uploaded it needs to be stored somewhere temporarily, this is the first problem i am facing. I can do all the task if someone can tell me workflow with a sample code about uploading excel file. I am only having problem here that as both upload and validate action are on same page, so after upload request it needs to be on that page so that i can validate that file.
Any help would be appreciated, I am very beginner at rails and really confused here.

Two options:
Write code to upload the file and save to DB with a validated column set to false. Then the 'validate' button will locate the unvalidated file, validate it and set validated to true. You could have a periodic job deleting unvalidated files of a certain age. If you do this, use a helper gem like Paperclip.
Forego file upload frameworks and just manually save uploaded files to Tempfile.new 'spreadsheet'. This guide takes you through how to do that. Save that filename to session and use it to validate at a later point. When you're finally ready to persist to DB, again, consider using a helper gem.

Related

Remove unused files from ActiveStorage+DirectUpload

Consider the following example:
I have a form that includes a multiple files input;
The input file uses ActiveStorage and DirectUpload to upload files automatically as soon as they are included;
After adding some files they are uploaded automatically;
I never click the submit button so those files are never used nor accessible anywhere;
Does Rails support some built-in mechanism for removing these files or is something we have to implement ourselves?
Seems rather trivial to perform a DoS by continuously uploading files until something breaks.
Update 1
Forgot to mention that the example I'm following uses a 3rd party library (Dropzone in this case) and follow the example from the official documentation.
According to the documentation after a file upload we inject a hidden input field with the id of the uploaded blob.
I think the answer of Chiperific is good, since DirectUpload is executed in the submit there is little time for the requests to fail.
I mention requests because as far as i understand it, the process is like this:
The user selects a file from his computer and fills the rest form.
DirectUpload uploads the file to the storage.
The backend receives the body and updates the attachment and either creates or updates a model.
So, what happens if the file upload is successful but model validation is not? you would end up with a file in the storage without his corresponding model or with dirty one.
More information here: https://github.com/rails/rails/issues/31985
The answer then is no, rails does not have a mechanism of removing this files automatically. I guess you could check if the model creation/update was successful and remove the file manually if not.
I think your premise is incorrect.
The input file uses ActiveStorage and DirectUpload to upload files automatically as soon as they are included;
According to the docs:
Active Storage, with its included JavaScript library, supports uploading directly from the client to the cloud.
and
That's it! Uploads begin upon form submission.
So the point of Direct Storage seems to be to bypass some Rails ActiveStorage things and go straight to the service. BUT, it still doesn't happen until the form is submitted.
The example on the non-edge docs shows the user clicking "Submit" before the files are actually uploaded.

Rails, Audit Log in View

I have a Model called file.rb that handles a files data table. This was done so that I can upload excel files from a file index.html.erb, and have the file name stored, see who uploaded the file, when it was created, etc(just tracking the files). These Excel files have many rows and each row have a bottle object with many attributes. During the create method, after save, I send the uploaded file to another model `bottle.rb'.
The bottle.rb model handles opening the Excel file and importing the information from the Excel file into the bottles data table.
I would like to be able to create an audit log with a message telling me success or failure of an uploaded excel file. Once the file passes the validations, I would like to see how many updates and new inserts to the bottles table. And be able to see this in the view where I upload the Excel file. I appreciate any helpful tips! I made an activity feed but for the entire application, but I am unsure how to go about to do this task.

Rails s3_direct_upload without file field

My website generates a file in javascript (audio recording) and I then want it to be uploaded to Amazon S3.
I first managed to get the uploading part working by sending the generated file to my server, where it is uploaded. However I would like now to upload the file directly to S3, without going through my server.
So I started to use the s3_direct_upload gem, which works great when using a file_field. However my file is generated by the javascript and :
- The value of a file field has to be set by the user for security reasons
- I do not want the user to have to interact with the upload
I tried to play with the S3Uploader class and to directly add data, without any success for now, it seems that I do not use the correct method.
Does anyone has any idea on how to achieve S3 direct upload without a file field ?
Thanks
Never mind, I found out that the S3Uploader class used by the s3_direct_upload gem has the same methods as the jQuery-File-Upload from which it is derived.
So one can call $("#s3_uploader").fileupload('send', {files: [f]});
And the f File will be uploaded to S3 directly

Seeding Carrierwave from external process

In it's simplest form...
I'm using Carrierwave in an app to auto-upload images that exist on external sites so as to put as little load on them as possible. The first time I want to display an image I trigger Carrierwave to do the uploading.
The db is seeded with an image url written in a background Java process. Then in Ruby I assign the seed url to "remote_image_url" and save! to get the upload and versioning to happen. This all works fine.
However I have to store a field in the db that tells whether the upload has been triggered so that I don't trigger it every time the image is displayed. How can I tell if the "image" has been uploaded? The "image" field is actually an Uploader, is there a method that will tell me if it has been triggered?
Carrierwave downloads the remote file as soon as you assign it via model.remote_image_url=, and it moves the file to its final location (local storage, S3, etc) as soon as you call model.save. This happens synchronously, so if model.save has completed, and there hasn't been an error, your file has been stored.
To put it another way: If you just loaded a model from the database, and model.image? is true, then model.image.url should be a working URL.

Can I somehow reinstate the file name on a 'file' type input if the page post fails?

Often some validation factor with nothing to with the file will cause a server side validation error, and reload the page. The previously chosen filename is always missing, and the poor user has to select the file again. This is especially frustrating when they fix the other error and click Submit again, thinking all will be all right.
Can I not somehow persist the file name in my model and set it on the 'file' input when the page loads?
Every form submission requires complete file upload, so to not make user poor, you should store file on server even when validation fails. When you do it, you have list of already uploaded files on the server ready for next, proper form submission. You can also present box with already uploaded files in view.
For security reasons, manipulating file upload field is not possible.

Resources