Paperclip: copy_to_local_file called upon every update (of unrelated attributes) - ruby-on-rails

I'm using paperclip 4.1.0 with Amazon S3.
I was wondering why requests were so slow and found that "copy_to_local_file" is called whenever I am updating attributes of a model with an attachment, even if it's just one attribute unrelated to the attachment (in my case, a cache_count, which means that every time someone votes an instance up, the attachment is downloaded locally!).
I understand it is used in case a rollback is required, but it seems overkill when the attribute isn't directly related to the attachment.
Am I using paperclip in the wrong way or is it something that could be improved ?
Thanks for your help

Just my 2 cents:
the attachment gets downloaded locally only after ActiveRecord::Base#save is called.
Would calling the 'base#save' in a cron on a daily basis instead help with the load?
Otherwise, either remove the calling of method copy_to_local_file if possible
or editing the source of paperclip's method of copy_to_local_file(style, local_dest_path) to exclude the downloading of attachment.

This was an issue with paperclip, it's fixed on the master branch!

Related

Paperclip before upload callback

I am working on a rails application that uses Timecop gem for "time traveling" and I have a problem... When I try to upload a file on Amazon S3 using Paperclip, S3 returns me
<Error><Code>RequestTimeTooSkewed</Code><Message>The difference between the request time and the current time is too large.</Message>
I think a "before_upload" callback on paperclip will help me to reset time to the real time, perform upload and travel back in the past... There is such a callback? What I found till now was just after_ callbacks :(
try doing it in the before_post_process callback, though I'm not sure how to dynamically add that hook without modifying your code specifically for testing. I would see if you could reset the time before you create your model, that would probably be the simplest.

Best practice for file upload before object is created?

I got a form that has several steps and the first one is to upload an image (via carrierwave) which is supposed to happen in the background. So the server is receiving a file for an object that doesn't exist yet. So I'm wondering what's the best practice for this case?
I thought of two approaches:
Make the image file a model that is created and returning the image ID upon upload completed.
Create the object, having validations disabled and only the image saved returning the object ID and update it afterwards with validations on.
I'm leaning towards no. 1 but maybe one of you guys have an even better idea? Not happy creating a new model just for the image.
carrierwave is a quality gem that will help you with your purposes. It doesn't require you to create a new model for image, rather you simply add an image field to one of your DB tables in schema.rb.
Relevant Tutorial

Rails uploads for new object

When creating a new record (rails default new action), the object id is nil b/c it's unpersisted in the db.
When uploading objects, they're usually tied to an id (using paperclip).
When my user clicks on new, and I want to provide a dropzone.js area for ajax upload, how do I tie that image/file to the post object when it has no id?
If they discard or exit the browser, I would have orphaned temp images/files...
I'm having trouble connecting the dots between an object upload for a new record.
Can someone help me work out the controller logic for this? I can do it pretty easily in a separate action after the object is created, but not before.
I made a Gem to solve this kind of problem.
It works on top of paperclip and is not intrusive. To enable the functionality, you need to replace paperclip's has_attached_file with has_attached_upload.
Using Rails Pallet gem...
First, you need to upload the file to your server performing POST /uploads with file attribute. The response will give you an identifier related to that file.
Then, sending the identifier, you can update your own record. The gem will copy the file to your record after that.
This way, you can upload files before persisting your record.
You can see a full example on gem's README

Conditional/delayed mailing with resque?

I got an application that creates loads of PDF documents which, sometimes take some time to create, hence I moved all the PDF creation to a resque background job. However, some PDFs need also to be sent out by mail which now is a problem because I don't know how to tell the mailer to wait for the PDFs to be created.
Before I had this:
#contract.create_invoice
ContractMailer.send_invoice(#contract).deliver
Now I have this:
Resque.enqueue(InvoiceCreator, #contract)
ContractMailer.send_invoice(#contract).deliver
So ContractMailer always fails because the pdf is not yet created. Anyone has an idea how to solve this elegantly?
Thanks!

AJAX file upload on creation of an object in rails with paperclip

I have a head aching problem that I can't seem to find an easy solution to.
I have a couple of models, each with an image attachment, that belongs to a user. I have made a very nice ajax file upload and image cropping form, but there is a problem. Everything works fine when I am editing objects that is already in the database but when I upload a file as I create a new object it doesn't. The thing is, to be able to upload and save the image, the object already has to be in the database. I have found two possible solutions to this problem but none of them will work properly.
The first one is to create the object in the database in the new action and redirect to edit action. The pros is that it is a very simple fix. The cons is that the objects will show up in the list with previously created ones even if the user canceled or never submitted the form, which is very confusing.
The second possible solution is to lift out the attachment fields of the model to a separate model. On creation I would then only need to create an attachment object. If the user canceled it would leave the attachment orphaned, but that is probably okay as the orphans could be cleared periodically. The problem with this is that I can't find a way to prevent users from hijacking the orphaned images, or any other image for that sake. Unless I cant solve this problem I'm stuck.
I'm all out of ideas and would really need some help on this one.
Thanks, godisemo
EDIT:
I was probably unclear. In my form it is possible to upload an image. The image is uploaded instantly to the server with javascript, before the form is submitted. The reason is that I want to allow the users to crop the image. This is no problem wen working with existing objects but it is when creating new ones, as I tried to explain earlier.
I've never had to have the model already in the db for paperclip to work.
One thing you can try though is the following. I don't know what your model is called but let's say User has an image. Make your new form so that all of your user fields are passed in the params[:user] var, but then make your image upload file separate from params[:user], say params[:my_image].
Then in your controller validate and save the user, then after user.save, attach the image.
I solved the problem now, with a completly different approach. Instead of thinking databases, objects and models I solved it using file system and temporary files. When the image is uploaded it is processed by paperclip, I then move the generated images to a folder where I have control over them.
I based my solution on a really great article which you can find here, http://ryantownsend.co.uk/articles/storing-paperclip-file-uploads-when-validation-fails.html

Resources