paperclip callbacks or simple processor? - ruby-on-rails

I wanted to run the callback after_post_process but it doesn't seem to work in Rails 3.0.1 using Paperclip 2.3.8. It gives an error:
undefined method `_post_process_callbacks' for #<Class:0x102d55ea0>
I want to call the Panda API after the file has been uploaded. I would have created my own processor for this, but as Panda handles the processing, and it can upload the files as well, and queue itself for an undetermined duration I thought a callback would do fine. But the callbacks don't seem to work in Rails3.
after_post_process :panda_create
def panda_create
video = Panda::Video.create(:source_url => mp3.url.gsub(/[?]\d*/,''), :profiles => "f4475446032025d7216226ad8987f8e9", :path_format => "blah/1234")
end
I tried require and include for paperclip in my model but it didn't seem to matter.
Anyideas?

Solution...
I put the callback after the paperclip has_attached in the given model and it works beautifully. I was just so used to always putting the callback at the top of all models that this didn't occur to me til later.

Moving the has_attached_file attribute above the validates_presence_of and validates_attachment
in your model still needs to be done it seems. I just ran into the same problem in my Rails 4/Ruby 2 implementation of PaperClip and putting it above fixed it.

I ran into this problem because the name of my paperclip image property did not match the name I was validating against.
as_attached_file :image
validates_attachment_content_type: :not_image

Related

Using Carrierwave on a Devise Model

I'm trying to use carrierwave to add profile images to a user model that's handled by devise.
I've used carrierwave before with no problems but this time, when I go to start the rails server, I get the error:
/var/lib/gems/1.9.1/gems/carrierwave-0.10.0/lib/carrierwave/mount.rb:46:in `uploader_option': undefined method `validate_integrity' for :ImageUploader:Symbol (NoMethodError)
There's very little information about this out there but I did read that you could ignore some errors using :ignore_integrity_errors. After trying a few times (and getting a lot of syntax errors) I finally settled on passing that in like so:
mount_uploader :profile_image, :ImageUploader, :options => {:ignore__integrity_errors => true}
I still think my syntax is incorrect because the NoMethodError persists. Any help at all on this matter would be much appreciated!
EDIT
I reverted to the commit before I started working with carrierwave, started my server, and tried again. In my browser I'm now getting the error:
uninitialized constant CarrierWave
on this line
class ImageUploader < CarrierWave::Uploader::Base
and this error apparently happens when the routes are loaded. I'm really confused about this, I have the gem in my Gemfile and I ran bundle install.
There are a couple of things going on here. First, the reason you're seeing the uninitialized constant CarrierWave error is probably just a consequence of not having restarted the server or something silly like that. If you've properly included it in the Gemfile and bundled, you should be fine.
To your original issue, though, there are three problems. The first is that you're passing a symbol as the uploader, and you need to pass the class. So you should pass ImageUploader, not :ImageUploader. The second issue is that you must pass the options hash directly to the uploader, not inside a parent hash with an options key. The third problem is that you've included an additional underscore in the ignore_integrity_errors symbol. So you should be using this:
mount_uploader :profile_image, :ImageUploader, ignore_integrity_errors: true
It would help to know what version to rails you are using. I've had this issue before but a server restart helped out.
Also, it looks like others had this issue. Maybe try doing what some of the users did here: https://github.com/carrierwaveuploader/carrierwave/issues/399

Paperclip type validation always giving error

I recently updated to Paperclip 4 (4.1.1 to be specific) where it is necessary to validate files with validates_attachment. I tried it 3 ways, as the GitHub docs suggest:
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
and the 2 ways suggested in this thread.
All the cases give me an ActiveRecord::RecordInvalid exception saying the image's content type is invalid.
I create the image using this line of code in a Grape API:
image = ActionDispatch::Http::UploadedFile.new(params[:data])
The data it receives comes from Android using Apache HttpClient's MultipartEntityBuilder
It prints the command it runs to check the mime type which is like file -b --mime-type '/path/to/file but when I run it, it gives me image/jpeg
The class only has 2 other lines:
has_attached_file :image
attr_accessible :image
And ideas why does it constantly fail?
I went into the same issue than you (even tried the other ways the thread suggests), and Rachel is right about the version. Paperclip 4 has some issue with spoofing. Changing it to 3.5 solved my problem.
Btw, if you still want to make it work, it seems to be the issue discussed here ( with a workaround given )
You might want to try doing some testing to eliminate the variables of what's going wrong here: can you try a different version of Paperclip, ~3.5? Paperclip 4 still has some bugs to be worked out (I have noticed this in my own project, it thought my normal upload had a spoofed content type).
Or: can you try creating the image a different way, just to test? The validation code you provided looks correct.

Paperclip - Running a method after the file is saved?

I'm working on a project that needs to accept file uploads. After the file is uploaded, I'm doing some processing - extracting information from the file. I eventually plan to run this in a background worker, but it's currently running inline.
I've tried making use of both after_create and after_save to process the file, but it seems my method is ran before the save method from Paperclip - so my tests fail with "No such file or directory".
Is there any way to trigger the save method early, or to somehow run my method after the file has been saved to the file system?
You can't read paperclip file in a callback as it's not saved to filesystem yet (or butt). Why, I'm not exactly sure.
EDIT: Reason is that paperclip writes out the file via after_save callback. That callback happens after after_create
However you can get the file payload for your processing. For example:
class Foo < ActiveRecord::Base
has_attached_file :csv
after_create :process_csv
def process_csv
CSV.parse(self.csv.queued_for_write[:original].read)
# .. do stuff
end
end
I had to do this 2 minutes ago. Hope this helps.
Adding this answer for visibility. A previous comment by #Jonmichael Chambers in this thread solved the problem for me.
Change the callback from after_save/after_create to after_commit
I think the problem might be related to the order of callbacks.
As discussed in other answers, the attachment file is indeed physically saved to disk in an after_save callback defined in Paperclip which is added to the model class at the point of has_attached_file call.
So you must ensure that your own after_save callbacks (that want to deal with the uploaded file) are defined after the has_attached_line.
Note: the after_create callback indeed cannot be used at all as it is called before after_save.
Take a look at the Paperclip post processing events callbacks. You should be able to call after_post_process to do your extra file info extraction.

Paperclip directory pluralization problem

I've had a system thats been running fine for ages using Rails 3 & Paperclip 2.3.6 for members images.
class Image < ActiveRecord::Base
belongs_to :business
has_attached_file :data, :styles => {:normal => ["665x443#", :jpg],:thumb => ["104x50#", :jpg]}, :convert_options => {:all => "-channel RGB -strip -quality 80"}
end
Now for some reason the route for the images has changed to /system/data/ instead of previous /system/datas/
I cant figure out whats happened. All of the images still reside in /system/datas/ and a member uploaded some new images and Paperclip has put them in /system/data/
Anyone have any ideas whats happened? I cant figure it out. Thanks.
EDIT: Ok, I had a test box still on Rails 3.0.3. My Release version was on 3.0.7. If I roll back to Rails 3.0.3 it's working again - the path /system/data/ becomes /system/datas/ again.
Rails 3.0.5 introduced some additional inflections which meant 'datas' was no longer used as the plural of 'data', which broke the directory naming for Paperclip!
According to the paperclip documentation you can specify a path for saving images in your model using the :path option and providing a path.
You can find the documentation here.

Preventing Paperclip from deleting/overwriting attachments on update

I'm having a hard time figuring out how to prevent Paperclip from deleting the old version of an attachment (image).
I have a model, Site, which has an attachment, logo. I would like to keep the old logos around since I will be keeping track of changes to the model and would like to view the history of logos.
I'm keeping track of the changes in another model, which has a reference to file paths. My problem is that when updating a site with a new logo, Paperclip will flush the old logo first.
It surprises me that there's not an option you can switch to prevent Paperclip from flushing the old attachment before creating the new one.
Any ideas?
There's a new option that tells paperclip to preserve old attachments:
https://github.com/thoughtbot/paperclip/commit/65e8d4f6de50732d8e1b
https://github.com/thoughtbot/paperclip/issues/60
Simple to use:
has_attached_file => :attachment,
:styles => { :thumb => 100x100! },
:preserve_files => true
It's not documented yet and took some digging to find so I wanted to share it here.
Because attachments are defined at the class level, Paperclip interpolates the symbols in your strings using it's own interpolation library. You can create your own interpolations using this library.
I would add a field to the model called attachment_version or something similar, and then increment this version number each time the file is changed. Then, create an interpolation for it in an initializer file:
Paperclip.interpolates :version do |attachment, style|
attachment.instance.attachment_version
end
Now you can use :version in your strings:
class Model < ActiveRecord::Base
has_attached_file :something, :path => " :rails_root/public/somethings/etc/:version.:extension"
end
See the wiki documentation for more information.
[Update]
After some digging around (see the comments to this answer), I've come to the conclusion that Paperclip will still delete the old attachment due to code that's called in Paperclip::Atachment#attach. Probably the best way to deal with this is to create a new storage engine based on Paperclip::Storage::Filesystem and overwrite #flush_deletes. Note that there is no way in that method to tell if a file is being queued for deletion because of the model it belongs to being deleted or a new file is being uploaded in its place.
lib/paperclip_monkey_patch.rb:
module Paperclip
class Attachment
def clear
# nop
#raise "hell"
# op
instance_write(:file_name, nil)
instance_write(:content_type, nil)
instance_write(:file_size, nil)
instance_write(:updated_at, nil)
end
end
end
Then add this line at the top of any file that deleted attachments:
require 'paperclip_monkey_patch'
Thanks to Ruby Forum
I had a similar issue with Paperclip attachments at when working on a Rails blog last summer.
There is a patch that addresses this. I wasn't able to get it working for myself, but it's worth a shot!
http://github.com/alainravet/paperclip/tree/keep_old_files

Resources