How to delete files selectively in Carrierwave when uploading multiple files? - ruby-on-rails

I'm uploading multiple files with Carrierwave gem as pointed out here: https://github.com/carrierwaveuploader/carrierwave#multiple-file-uploads
I can delete them all in one shot with no problem with user.remove_photos! being photos an array or json in the db; however, how do I delete selectively one or two out of the complete set of files previously uploaded?
#user.remove_photos! <--- removes all the photos
#user.save
#user.remove_photos[0]! <--- does not work
By the way, I'm using sqlite3 and in order to make it work you need to do the following tweaks:
rails g migration add_photos_to_users photos:string <-- note is string
and in your model definition, after mounting the uploader:
serialize :photos, JSON
both, not yet shown on the Readme, although the commit was already done by rusikf here: https://github.com/rusikf/carrierwave/commit/dedc9c341e34f2e0e57d47c3eec65347fef398bd

Related

Paperclip Get dirty file before update

Background:
I'm developing Rails Application and in some models I'm using paperclip gem to save attachments. In same models I'm using public_activity gem to track the model changes & I've prepared Restore functionality based on that to be able to Undo changes on that model with specific conditions.
Now using paperclip option :preserve_files => true it's simple to get the old file in case of delete, but in case of update, I don't know how.
Question:
public_activity gem is already using before_action callback and I can handle all dirty fields except Paperclip file update.
So how can I get the dirty updated file without changing my models or adding extra callbacks (because I'm using this achievement in multiple models and Undo functionality is generic).
Note:
I'm using File.exist?(paperclip_attachment.path) to check whether the file is still exist or no, and it returns false in case of update callback of public_activity (I think it is same as before_update callback).
I've did a simple way to get the dirty file with just edit Undo Functionality in public_activity update callback:
dirty_file_path = Dir.glob(File.join(File.dirname(paper_clip_attachment.path), '*.*')).max { |a,b| File.ctime(a) <=> File.ctime(b) }
paper_clip_attachment.path includes the path to the file, but the file itself is not yet created.
The code above just checks the container folder of the file paper_clip_attachment.path then checks the latest created file and save it's path to be used in Undo step.

Migrate from Paperclip to Carrierwave or Refile

I would like to migrate from Paperclip to Carrier Wave or Refile because of this. The solution written here is impressive, but strikes me as complex and perhaps brittle.
My Rails4 app has 100's of images in production that were uploaded with Paperclip. Files are stored on production server. I have looked for a complete set of steps to follow to migrate, but keep coming up empty.
Is there a set of steps one can follow that allows for migration without necessitating application code re-write?
Alternatively, is there another way to persist uploaded files in Paperclip when form validation fails?
What am I missing here?
UPDATE:
Tried the solution detailed here by https://stackoverflow.com/users/646389/galatians . My paperclip :path and :url interpolations make use of :id_partition. I don't see a way this can be reconciled with an uploaded Image that is staged, but not yet saved.
I migrated to Carrierwave. Here are the relevant stats:
Time to work on and fail at coding a solution for persistent files
across form reloading with Paperclip - 4 hours. See OP update for the issue I could not overcome.
Time to Migrate to carrierwave, adjust the relevant models, controllers, and forms, and test. - 2 hours. Not so bad.
This key info helped me adjust the paths correctly. Keeping the path identical was important to me for avoiding having to move images to a new location in production:
Carrierwave code for generating paperclip-like :path and :url info here.
Paperclip interpolation info here.
This link got me on the right track, although my default :path made use of :id_partition not :id.
UPDATE:
Migration breaks this paradigm:
#protocol.images.each do |i|
tmp=i.dup
tmp.avatar = File.open(i.avatar.current_path)
tmp.save!
#dest.images << tmp
end
See: Duplicating a record that contains a carrierwave avatar : Getting "can't convert nil into Integer" error
You don't need to do anything because the only data needed to get images is already stored in DB.

How to implement a user creating a file via form and then downloading it in rails?

I am building an online translation platform. When a job is done being translated and saved, I want the user to be able to download the translated version as a text file. It is currently saved in a string in the model called "target_text".
I know in ruby I can use this method:
File.open("translation.txt", 'w') {|f| f.write("my translated string") }
I am assuming I could tack the location for the file to be saved in front of the "translation.txt", but I am not sure what folder within my app I should specify?
Furthermore I want this file to be attached to the "job" object in the same way that paperclip can attach files, the difference being it's initiated server side. How should I go about this?
I have googled all over looking for an answer to this, and I want to make sure I do it in the cleanest way possible. I would really appreciate even directions to a good place to look to understand this concept.
I don't quite understand the question, but I hope this could help...
Instead of using
File.open("translation.txt", 'w') {|f| f.write("my translated string") }
try using the following
Tempfile.open(['translation', '.txt'], Rails.root.join('tmp')) do |file|
# this will create a temp file in RAILS_ROOT/tmp/ folder
# you can replace the 'translation' text part to any auto generated text for example
# Tempfile.open([#user.id.to_s, '_translation.txt'] will create
# RAILS_ROOT/tmp/1_translation.1fe2ed.txt
# the 1fe2ed is generated by Tempfile to avoid conflicting
begin
file << "my translated string"
# this creates the file
# add all the processing you need here... cause the next ensure block
# will close and delete this temp file... so that the tmp dir doesn't get big.
# you can for example add the file to paperclip attachment
#user.translation = file
# assuming that user has paperclip attachment called translation
ensure
# close and delete file
file.close
file.unlink
end
end
also check the Tempfile docs... this is the practice i've been using... not sure if it's the best or not.. but it didn't create any issues so far
(even with paperclip s3 storage)

Add fingerprint to old paperclip attachments

I use paperclip for the attachments on my models. I've recently added a fingerprint to the attachments, it works fine with the new attachments but it ws not added to the old ones, because of this I'm having trouble reprocessing attachments to add a new style, because paperclip tries to find the attachments with fingerprint and not all the attachments have one.
Is there a way to add the fingerprint to the old attachments?
This is the error I'm getting from the reprocessing on the old attachments:
Errno::ENOENT: No such file or directory - /tmp/paperclip-reprocess20140422-1036-nl9gxk
[edit]
Have you tried?
$ rake paperclip:refresh class=Model_Name_Goes_Here
[/edit]
if you don't have too many images. simplest way, I can think of is:
Dir.foreach('/path/to/dir/that/contains/old/images') do |item|
next if item == '.' or item == '..'
file = File.join(File.expand_path(File.dirname(__FILE__)), item)
thing.image = file
thing.save
end
you can run this script, using runner:
$ rails runner /path/to/script
Does something like this work for you?
After manually try and examine the error several times I found that the problem is not that the attachment had no fingerprint. The problem was that the fingerprint was nil. For some reason paperclip does not handle this case.
I manually gave every object an empty string as a fingerprint through the database (this saved me from renaming the file on disk) and then reprocess every one of theme.
That solved it!

Parsing rails uploaded temporary file more then once

I'm new to rails and I'm currently trying to parse an uploaded file to rails. However, after I "read" the file once I cannot read it again. From what I've read online it appears that rails immediately deletes the uploaded file. Is there a way to make the file persistent? My code is as follows
file_param = params[:sequence]
file_param.read.each do |l|
# do stuff
end
file_param.read.each do |l|
# do stuff again. this is not being called.
end
I've thought of using paperclip or some other storage gem, but I don't need to store the files, simply read their contents. Thanks!
Read it into an array, if you really need to go over it multiple times, or just save it.

Resources