getting text from file uploaded with paperclip - ruby-on-rails

I've got a very simple file upload for a text file using paperclip.
What I want to do is to get the first line of the text file and turn it into a hash I can search against in a database.
I don't think it makes much sense to save the file, then retrieve it, create the hash, and then save it again.
I can't seem to figure out how to get the text of the attached file before saving.
my controller is fairly simple at the moment
def create
#upload = Upload.new(params[:upload])
#upload.user_id=current_user.id
#get the first line of the uploaded file
if #upload.save
redirect_to #upload, :notice =>'Successfully uploaded file."
else
render :action => 'new'
end
end
Going through the documentation, I've seen that paperclip has a to_tempfile, which I assume I can read into a string, but i can't seem to find anywhere that shows me how to do that.

If params[:upload] is the file_field_tag in your form, then it's easier to bypass Paperclip and retrieve the first line of the file directly using Rails, just do this:
first_line = params[:upload].tempfile.readline

Related

When you upload multiple files using ActiveStorage, is it possible to determine what was just uploaded?

I have a model (let's call it Message) that's using Active Storage with has_many_attached to store multiple uploads through a Javascript routine. I'd like to know the URL of the uploads as soon as these are received and processed by the Update action in my controller. Ideally, the response would be in the form of a JSON string, containing the URL of the file that is just uploaded by the Javascript routine.
Other than having to loop through all the uploads, is there a way to obtain this information as they're uploaded?
I'm not using the DirectUpload javascript suggested in the Active Storage guide, in case you're wondering. The Javascript I'm using sends the files to a custom PATCH action /message/:id/new_upload (where :id is the ID of the Message record), with the BLOB file as its only parameter.
I've tried to use something like this:
def new_upload
#message.uploads.attach(params[:uploads])
respond_to do |format|
format.json {render json: { location: "The URL would go here"} }
end
end
But the attach line at the beginning doesn't return anything (obviously), all it is is doing is saving the attachments. Is there anything I can use to figure out what was just uploaded?
UPDATE
I've managed to make it "work" by doing something like this:
def new_upload
#message.uploads.attach(params[:uploads])
upload_url = rails_blob_url(#message.uploads.blobs.last)
respond_to do |format|
format.json {render json: { location: upload_url} }
end
end
However, this only works for one attachment (the last). Thankfully I only require to upload one file at a time, but I'd prefer to infer the URL by something other than checking the last upload.

Rails cloudinare not uploading image

I've just integrated cloudinary into my rails project and created a view to allow the user to upload an image file.
In my controller I have:
def update
#painting = Painting.find(params[:id])
if params[:image].present?
preloaded = Cloudinary::PreloadedFile.new(params[:image])
raise "Invalid upload signature" if !preloaded.valid?
#painting.image = preloaded.identifier
end
if #painting.update(painting_params)
redirect_to #painting
else
render 'edit'
end
end
In my view:
<%= cl_image_upload_tag(:image) %>
So once the user edits a painting, they can upload the image which will be stored in the #painting model and then it will be saved. After uploading the image, I check cloudinary and find that no image was uploaded. In addition the #painting model has a nil entry for the :image attribute.
Can't see what I'm doing wrong.
Please have a look at the developer tools at the view page, and check whether you have any reported errors there. Specifically, might be related to the jQuery library not being properly included.
You should try to have a look at the sample project. Specifically,
https://github.com/cloudinary/cloudinary_gem/blob/master/samples/photo_album/app/views/photos/new_direct.html.erb#L20

Collection of activerecord objects in pdf format to zip

I have a complicated problem with creating zip file containing collection of active record object in pdf format.
I have invoices controller and in this controller I have action show which looks like this:
def show
add_breadcrumb "Inovice details"
respond_to do |format|
format.html
format.pdf do
render :pdf => "file_name"
end
end
end
I generate pdf with wicked_pdf gem. And now my goal is to from selected collection get each of invoice generate pdf file from it and add it to the zip file. I don't have any idea where to start. Thanks in advance.
I just answered a very similar question here and included a test controller method that renders multiple multiple pdfs with wickedpdf and uses rubyzip to pack them together and send single archive.
generate ZIP from generated PDFs with wicked_pdf

Associating a file uploaded with Carrierwave_Direct with an object

I'm uploading files directly to S3 using the carrierwave_direct gem and everything is going smoothly. However, when amazon redirects back to the URL specfied in success_action_redirect, I'm not associating the uploaded file with the object.
My controller looks like
def edit
#excel_version = ExcelVersion.find(params[:id])
#uploader = #excel_version.excel_everest_macro
#uploader.success_action_redirect = edit_admin_excel_version_url
end
def update
#excel_version = ExcelVersion.find(params[:id])
#excel_version.assign_attributes(params[:excel_version])
#excel_version.save
end
And I have a hidden form field in my view that looks like
= form_for #excel_version do |form|
= form.hidden_field :key
So in my update action I just use #excel_version.assign_attributes(params[:excel_version])
and the key returned by Amazon makes it into the model just fine. However, the uploader mounted on the #excel_version object doesn't get url and I can't set up a link to then download the file.
Any suggestions on how I can use the S3 parameters returned to me to associate the file with the model as carrierwave would normally do?
Thanks!
P.S. another answer on here suggested reading the carrier_wave direct documentation on github, which I have and have found unhelpful in this respect.
To associate the image to the model what you can do is create a method in your controller which would use the params from amazon and create the image link
For example you can do -
def image_url
respond_to do |format|
format.json { render :json => { :filelink => "https://s3.amazonaws.com/#{params[:bucket]}/#{params[:key]}" } }
end
end
What this code will do is when amazon does a success redirect to image_url method it will use the parameters "bucket" and "key" to create a exact link to your image. (The params which are sent have both key and the bucket name)
Now you can put this image url in the hidden object on your view so that when the form is posted to the server the url also gets posted along with it. Which you can associate to your model.
Hope this helps. It worked for me.
So my problem was that I had the hidden_field :key field on the wrong form. I mistakenly put the field on the direct_upload_form_for #uploader form that uploads the file to S3.
Of course, you need the :key field on a form that the user returns to after posting the file to S3 (ie at the url passed in to the success_action_redirect method). It is there that S3 will return the key in the params and you can associate it with your model.
Thanks for all the helpful suggestions!

How to upload an image to S3 using paperclip gem

For the life of my I can't understand how the basic paperclip example works. There's only one line included in the controller, and that's
#user = User.create( params[:user] )
I simply don't understand how that's all that is needed to upload an image to s3. I've changed the example quite a bit because i wanted to use jquery file uploader rather than the default rails form helper, so I'm at the point where an image is being POSTed to my controller, but I can't figure out how I'm supposed to take the image from the params and assign it as an attachment. Here's what I'm seeing the logs:
Parameters: {"files"=>[#<ActionDispatch::Http::UploadedFile:0x132263b98 #tempfile=#<File:/var/folders/5d/6r3qnvmx0754lr5t13_y1vd80000gn/T/RackMultipart20120329-71039-1b1ewde-0>, #headers="Content-Disposition: form-data; name=\"files[]\"; filename=\"background.png\"\r\nContent-Type: image/png\r\n", #content_type="image/png", #original_filename="background.png">], "id"=>"385"}
My JS is very simple:
` $('#fileupload').fileupload({
dataType: 'json',
url: '/my_url',
done: function (e, data) {
console.log('done');
}
});`
What would be helpful for me to know is how I can strip the file data from the POSTed parameters given above and pass it to paperclip. I'm sure that I'll have to assign the attachment attribute a value of File.open(...), but I dont know what source of my file is.
I've spent a ridiculous amount of time trying to figure this out and I can't seem to get it. I've tried uploading directly to s3, but the chain of events was terribly confusing, so I want to get this simple pass-through example completed first. Thanks so much for any help you cna give!
You need a few more pieces and it will help if you can show the exact code you're using.
Paperclip can post to S3 by using:
http://rubydoc.info/gems/paperclip/Paperclip/Storage/S3
When your controller creates a User model, it is sending along all the params. This is called "mass assignment" (be sure to read about attr_accessible).
When your model receives the params, it uses the Paperclip AWS processor, which uploads it.
You need the AWS gem, a valid bucket on S3, and a config file.
Try this blog post and let us know if it helps you:
http://blog.trydionel.com/2009/11/08/using-paperclip-with-amazon-s3/
UPDATE 2013-04-03: Pleases see Chloe's comment below-- you may need an additional parameter, and the blog post may be outdated.
If you want to do it manually, approach it like this:
# In order to get contents of the POST request with the photo,
# you need to read contents of request
upload = params[:file].is_a(String)
file_name = upload ? params[:file] : params[:file].original_filename
extension = file_name.split('.').last
# We have to create a temp file which is going to be used by Paperclip for
# its upload
tmp_file = "#{Rails.root}/tmp/file.#{extension}"
file_id = 0
# Check if file with the name exists and generate unique path
while File.exists?(tmp_file) do
tmp_file_path = "#{Rails.root}/tmp/file#{file_id}.#{extension}"
id += 1
end
# Let's write the file from post request to unique location
File.open(tmp_file_path, 'wb') do |f|
if upload
f.write request.body.read
else
f.write params[:file].read
end
end
# Now that file is saved in temp location, we can use Paperclip to mimic one file
# upload
#photo = Photo.new :photo => File.open(tmp_file_path)
# We'll return javascript to say that the file is uploaded and put its thumbnail in
# HTML or whatever else you wanted to do with it
respond_to do |format|
if #photo.save
render :text => "Success"
else
render :text => #photo.errors
end
end
You can rewrite your create or whatever you use as the url to which you are POSTing the form.
This bit:
"files"=>[#<ActionDispatch::Http::UploadedFile:0x132263b98 #tempfile=# <File:/var/folders/5d/6r3qnvmx0754lr5t13_y1vd80000gn/T/RackMultipart20120329-71039-1b1ewde-0>
is the part (I think) that holds the file contents that are posted in the form.
In Rails, the User model will have a helper: has_attached_file
Passing the [:params] to the User.create method allows that helper to pick up the file contents, do any processing on them (eg resizing etc based on attributes supplied to the helper) and then push the image(s) to your storage (eg S3 or whatever - S3 credentials are passed to the helper).
Hopefully that explains the 'how does it do it?' question
re the jQuery bit.. not sure what the code should be there, but why not use the Rails form with :remote => true and handle the response in jquery?

Resources