how to remove existing style dimensions in paperclip - ruby-on-rails

I know you can add new styles to paper clip and then use process! method to force paperclip to fill in the missing styles. But what if you want to ditch the old styles that you are not using any more.
For example I have styles iphone and ipad, and I changed my mind and would instead like :large and :medium with slightly different dimensions instead of :iphone and :ipad.
In particular I'm hosting my images on s3 since my app is on heroku. I would like to remove all the folders on s3 pertaining to :iphone and :ipad styles. Is there a rake task for removing select styles?

If you are referring to removing invalid files, try:
rake paperclip:clean # Cleans out invalid attachments.
You can view all paperclip tasks in your console by typing:
rake -T paperclip

run in your terminal
rake -T paperclip
you can see like this
...
rake paperclip:clean # Cleans out invalid attachments.
rake paperclip:refresh # Refreshes both metadata and thumbnails.
rake paperclip:refresh:metadata # Regenerates content_type/size metadata for a given CLASS (and optional ATTACHMENT).
rake paperclip:refresh:missing_styles # Regenerates missing thumbnail styles for all classes using Paperclip.
rake paperclip:refresh:thumbnails # Regenerates thumbnails for a given CLASS (and optional ATTACHMENT and STYLES splitted by comma).
...
for refreshing your thumbnail try this
rake paperclip:refresh:thumbnails class= Xyz # xyz replace with your class name
for removing
rake paperclip:clean # Cleans out invalid attachments.

You can use the Attachment#clear method.
If you wanted to delete the thumb and display styles, you could run something like:
YourModel.find_each do |ym|
ym.attachment.clear(:display, :thumb)
ym.save!
end

You will have to write a script to accomplish this, but paperclip does have a s3_object convenience method that makes this easy:
obj = User.first.avatar.s3_object(:unwanted_style)
obj.delete if obj.exists?
You could place something like this within a loop for any objects you want to operate on.
Sources:
Paperclip::Storage::S3 documentation
aws-sdk Object documentaion

Related

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.

Defining where Paperclip stores the attachment locally when running Spec tests

I'm using AmazonS3 to store Paperclip attachments on all non-test environments.
For test specifically I use a local path/url setup to avoid interacting with S3 remotely
Paperclip::Attachment.default_options[:path] =
":rails_root/public/system/:rails_env/:class/:attachment/:id_partition/:filename"
Paperclip::Attachment.default_options[:url] =
"/system/:rails_env/:class/:attachment/:id_partition/:filename"
I define my attachment as follows in the model
has_attached_file :source_file, use_timestamp: false
In my Production code I need to access the file using Model.source_file.url because .url returns the remote fully qualified Amazon S3 path to the file. This generally works fine for non-test environments.
However on my test environment I can't use .url because Paperclip creates and stores the file under the path defined by :path above. So I need to use .path. If I use .url I get the error -
Errno::ENOENT:
No such file or directory # rb_sysopen - /system/test/imports/source_files/000/000/030/sample.txt
which makes sense because paperclip didn't store the file there...
How do I get paperclip on my test environment to store/create my file under the :url path so I can use .url correctly?
Edit: If it helps, in test I create the attachment from a locally stored fixture file
factory :import do
source_file { File.new(Rails.root + "spec/fixtures/files/sample.tsv") }
end
Edit2: Setting :path and :url to be the same path in the initializer might seem like a quick fix, but I'm working on a larger app with several contributors, so I don't the have the luxury to do that or break any one else's specs. Plus it looks like Thoughtbot themselves recommend this setup, so there should be a "proper" way to get it working as is.
Thanks!
Have you tried using s3proxy in your test environment to simulate S3 instead of directly have paperclip write to local files?

How to delete files selectively in Carrierwave when uploading multiple files?

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

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!

New paperclip fingerprint after modifying style?

It looks like Paperclip generates a fingerprint for an attachment only when the original style is changed. I want to keep the original style unchanged but crop one of my other styles (let's call it "listing"). Is there a way to force Paperclip to regenerate a fingerprint if the "listing" style is cropped but the "original" style is not?
I found generate_fingerprint no longer works with the latest Paperclip (4.1.1) but the refresh rake task does: e.g. rake paperclip:refresh CLASS=Dog.
In my case, I wanted the fingerprint to be created automatically when I ran the the migration that added the fingerprint, so I dug into the code and found you can call reprocess! on the attachment and that'll also do the trick.
I recently added an image_fingerprint column to an existing model that has Paperclip images attached.
I forced Paperclip to generate fingerprints for the existing images with the generate_fingerprint method on Paperclip::Attachment:
class Dog
has_attached_file :image
...
end
Dog.all.each do |dog|
dog.image_fingerprint = dog.image.generate_fingerprint(dog.image)
...
end

Resources