Help on using paperclip plugin - ruby-on-rails

I've just installed this plugin, created the migrations, added everything I needed to make it work(I didn't install ImageMagick yet).
The problem is when I get the upload control parameter to save it in my controller, I get something like this:
#<File:C:\Users\Brian\AppData\Local\Temp\RackMultipart.2560.6677>
instead of a simple string, like
C:\Users\Brian\AppData\Local\Temp\RackMultipart.2560.6677
And if I try to read it I get the following exception:
TypeError backtrace must be Array of
String
What am I doing wrong? How do I read it or simply get rid of the # and <> symbols?

Paperclip defaults to storing uploads in the file system, not the database. Uploads are stored in the public/system directory. Have you checked there?
Robin

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.

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!

carrierwave: point to existing image

In my rails app, I'm using Carrierwave to upload images on Amazon S3. I'd like to point to existing Amazon S3 images without having to re-upload the image. For example, if I have an existing Amazon S3 image at http://test.s3.amazonaws.com/image/path/0001/image.jpg, can I update an image's path to point to this image? I don't want to use the remote upload option because I really just want to use the same exact image that's already there (but save it in my record's "path" attribute).
In the console, I've tried:
image.update_attributes(:path=> "http://test.s3.amazonaws.com/image/path/0001/image.jpg")
but this fails to override the image's path.
Chiming in, better late than never! Caveat: This is for rails 4, and I am testing on rails 4.1 only at the moment.
This is harder than it should be, methinks! The reason this was absolutely crucial to me was that I am attaching 100MB+ MP3 files, which I cannot receive on my host, due to CloudFlare SSL limitations (and common sense). Fortunately, AWS supports preauthorized uploads, and I got carrierwave to do the right thing for me:
Step 1: get carrierwave to tell me where it would store a file if it could:
m.raw_write_attribute('file','file.mp3');
url = m.file.url
signed = aws_presigned_url(url)
raw_write_attribute does not save anything, it just bypasses carrierwave when setting the value. This makes the object act as if it read 'file.mp3' out of the database. Then you can ask Carrierwave "where the file lives". I then upload the file directly from the client to S3. When that's done, I make another API call to Rails, which performs the following code:
m.raw_write_attribute('file','file.mp3');
m.update_attribute('file','file.mp3');
These two paired get around Carrierwave. The first makes carrierwave think that the 'file' column is set to 'file.mp3', the second explicitly tells rails to persist 'file.mp3' to the DB. Because of the raw_write_attribute call, Carrierwave allows the second through un-changed.
In my case update_column and update_columns worked great:
model.update_columns file_1: 'filename.txt'
Update column is with comma:
model.update_column :file_1, 'filename.txt'
This will not run any callback and set column to filename.txt.
When I do model.file_1.url I get the right S3 URL.
I am a bit late to the party, but you can use Active Record's raw_write_attribute method something like:
#image.raw_write_attribute(:path, "http://test.s3.amazonaws.com/image/path/0001/image.jpg")
I found that you can actually do this, for example if your mount_uploader is :path, then:
image.remote_path_url = "http://test.s3.amazonaws.com/image/path/0001/image.jpg"
image.save

paperclip problem when re-generating thumbs

I'm trying to re-create all thumbs. I'm not sure why is saying the key does not exist. I have AWS-S3 configured properly and it's working well (I can upload pictures with no problems.)
>> Attachment.all.each {|x|x.attachment.reprocess!}
AWS::S3::NoSuchKey: The specified key does not exist.
/app/d999782b-a789-4763-ac86-e8c65fa781eb/home/.bundle/gems/ruby/1.8/gems/aws-s3- 0.6.2/lib/aws/s3/error.rb:38:in `raise'
/app/d999782b-a789-4763-ac86-e8c65fa781eb/home/.bundle/gems/ruby/1.8/gems/aws-s3-0.6.2/lib/aws/s3/base.rb:72:in `request'
/app/d999782b-a789-4763-ac86-e8c65fa781eb/home/.bundle/gems/ruby/1.8/gems/aws-s3-0.6.2/lib/aws/s3/base.rb:88:in `get'
/app/d999782b-a789-4763-ac86-e8c65fa781eb/home/.bundle/gems/ruby/1.8/gems/aws-s3-0.6.2/lib/aws/s3/object.rb:134:in `value'
When I tried to do the same to a single object seems to do it well, so the problem seems to be related to generating with a collection.
>> Attachment.last.attachment.reprocess!
=> true
UPDATE: I'm pretty sure it's related to the fact that there are uploaded files such as .htm that should be valid image files. Any idea how to skip them?
Though I am not sure, but I hope this might help you.
Attachment.all.each { |x| x.attachment.reprocess! if ['.jpeg','.jpg','.png','.gif'].include?(File.extname(file_name))}
where file_name => Name of the uploaded file
Best of Luck
Not sure where you've put your key for the AWS-S3, but you may have to specify that you want to run this under the production environment.
heroku rake paperclip:refresh CLASS=Attachment RAILS_ENV=production
I don't know how your validations are set up but is it possible that some attachment objects can have a blank attachment? If so, try:
Attachment.all.each { |x| x.attachment.reprocess! rescue nil }
This error can also refer to when an object(key) no longer exists on S3 but you have a record pointing to it in your database. This only happens if someone has made changes to the S3 bucket that don't mesh with what you have in your DB.
If that's the case you can use the ".exists?" method on the attachment to check if that key exists on Amazon's server's first, not that this will issue a read request.
This would change your reprocess command to something like this:
Attachment.all.each { |x| x.attachment.reprocess! if x.attachment.exists? }
Have you considered using:
rake paperclip:refresh
Instead?

Importing old data with Rails and Paperclip

I'm using paperclip for attachments in my application. I'm writing an import script for a bunch of old data, but I don't know how to create paperclip objects from files on disk. My first guess is to create mock CGI multipart objects, but that seems like a bit of a crude solution, and my initial attempt failed, I think because I didn't get the to_tempfile method right.
Is there a Right Way to do this? It seems like something that should be fairly easy.
I know that I've done the same thing, and I believe that I just created a File object from the path to each file, and assigned it to the image attribute. Paperclip will run on that file:
thing.image = File.new("/path/to/file.png")
thing.save
This works great for local files but it doesn't work as well for remote files. I have an app that uses paperclip for uploading images. Those images are getting stored on amazon s3. Anyway, I had some old data that I needed to import so I tried the following:
thing.image = open('http://www.someurl.com/path/to/image.jpg')
thing.save
If the file is small (say, less than 10K) then openuri returns a stringio object and my file would get stored on s3 as stringio.txt
If the file is larger than around 10K, then openuri returns a TempFile object. But the filename on s3 ends up being unique, but not really relating to the original filename of image.jpg
I was able to fix the problem by doing the following:
remote_photo = open('http://www.someurl.com/path/to/image.jpg')
def remote_photo.original_filename;base_uri.path.split('/').last; end
thing.image = remote_photo
thing.save

Resources