I have an app that uses attachment_fu and everything works fine, except when I update an attribute of the picture model such as the title or description, attachment_fu goes and makes the thumbnails all over again, even though they are already created (happened on create). So im wondering if there is a way to skip atachment_fu when updating. thanks in advance for any help
This is an excellent question. Typical plugins that invoke before_ or after_ style filters can be skipped using the skip_before_filter (for example) construct. I don't know if attachment_fu supports this. It would be worth testing, though.
It looks like in the source of attachment_fu, the class is extended with (among other things):
So maybe if you tell it to skip the validation on certain actions, it'll skip the processing. I don't know if you can do:
validates_as_attachment, :only => :create
Most validates_ type calls support this, but looking at the source code, I don't know if attachment_fu would. Worth fiddling with and even monkeypatching attachment_fu if need be.
Another idea, and one that I use in my apps:
I have a model _just_ for images... i.e. in my case: Logo.
It only has the fields for images. Then, if I need the logo to be an avatar for a person object, I simply have something like:
class Person < ActiveRecord::Base belongs_to :avatar, :class_name => "Logo" ... end
Then, when I create or update the person, I can redo the logo only if it's got data... for example:
@logo = @person.build_logo(params[:logo]) unless params[:logo] [:uploaded_data] == "" @logo.valid? unless @logo.nil?
And for an update, I'd do:
@logo = @person.logo @logo.destroy unless @logo.nil? or params[:logo] [:uploaded_data].blank? @logo = @person.build_logo(params[:logo]) unless params[:logo] [:uploaded_data].blank? @logo.valid? unless @logo.nil?
That way, if you update the person model and supply a new logo, it'll destroy the old (which will delete the files as well as clear out the DB record), then build a new one, and validate it so you have validation checks.
At least this works for me.
(btw, I need the "unless @logo.nil?" because nil.valid? causes an exception)
Danimal, Thanks for your reply, I tried both of your examples and neither works. Attachment_fu's validates_as_attachment doesn't support :only => :create it just returns 'wrong number of args, 1 for 0'. and skip_before_filter :attachment_fu just let it keep working like normal. I'd really like to find a way around this, and not have to make another model for picture_details and update that for my titles and descriptions, but this would require digging through all my code and changing all calls for a pictures title or description. I'm gonna keep messing with finding a way around attachment_fu.
Probably your next step would be to contact Rick Olsen (writer of attachment_fu) and see what he suggests.
You could certainly modify his code without too much trouble and add in a hook so that the code is only called on a create, but he may have other suggestions or may be able to do it himself quickly and easily (as it's his code).
Let us know what you end up using. If you do end up patching Rick's code, it would be good to share that with the community for others who need it.
BTW, I originally started with the attachments within the models and then later abstracted it out to a separate Logo model. It took a little time to clean up, but not much, and I think it's much cleaner this way.
I can say: Person.find(X).logo to get the logo for Person X. I also can reuse the Logo model for all sorts of things that need an image attachment. And, I can subclass Logo for more specific logo types, i.e. I can make an Avatar < Logo and then do avatar-specific things.
Okay, so I decided it would just be better to make picture_details model and attach the pictures to that, it just took an hour or so to re-write my code. One problem I did have though, I have ratings on my pictures, and so for /popular i would just order my query by rating, so now (the simplest way I can think to do it) is a block for the pictures, and find the corresponding picture_detail and push the rating and picture id into an array, then sort the array by the rating. Anyone who has a better way of doing that I'd love to hear