Search code examples
ruby-on-railspaperclipbefore-filter

Paperclip's Post Processing starts before virtual attributes get values?


I'm using Paperclip gem in my new project for storing images. There's also simple custom Paperclip processor I wrote to crop images according to crop parameters, stored in my model's virtual attributes.

So client transfers form with model's actual db fields and crop_x, crop_y, crop_w, crop_h attributes, controller creates new instance based on "params" --- that's going well -- I checked it, but then some weird things are taking place.

here's my model:

class Jewel < ActiveRecord::Base
has_many :line_items
belongs_to :material

******* some code *********

before_save :debugmeBS

validates :category_id, :presence => true

attr_accessor   :crop_x, :crop_y, :crop_w, :crop_h
attr_accessible :name, :category_id, :price, :crop_x, :crop_y, 
:crop_w, :crop_h, :image

after_update :reprocess_image, :if => :need_to_crop?

has_attached_file :image, :styles => { :full => "900x", :smallthumb => "80x80>" }, 
:processors => [:cropper, :thumbnail]

before_post_process :debugmePP

def need_to_crop?
    # debugger
    !crop_x.blank? && !crop_y.blank? &&!crop_w.blank? &&!crop_h.blank?
end

private 
    def debugmeBS
        debugger
        x=2

    end

    def debugmePP
        debugger
        x=3

    end
 end

Debugger placed in my custom processor shows that crop_x, crop_y and others virtual attributes are blank (by invoking "need_to_crop?" method) meanwhile other not-virtual ones are set properly. To track-down error I placed two "before_"-events: before_save and Paperclip's before_post_process. Turns out that before_post_process is invoked before before_save and on the moment all my "crop_" attributes are nil, but on the moment of before_save fire, those are properly set up.
so the question is why? and how to set my virtual attributes to be accessed by Paperclip processor? Thank you


Solution

  • I hit the same thing as well. Looking at the code for Paperclip (see callbacks.rb, attachment.rb, and paperclip.rb under lib/paperclip/), it seems the before_post_process and before__post_process callbacks are invoked when the file is assigned to the attribute. My guess is that this is happening before the other attributes on the model are set.

    UPDATE: I asked on the GitHub Issues for the Paperclip project, and what I wrote above was confirmed. The timing of the processing does depend on when the attribute is assigned. Since attributes are assigned alphabetically, depending on the name of the , it can be assigned before any of the other attributes.

    For a workaround, you can do:

    def create
      avatar = params[:resource].delete(:avatar)
      resource = Resource.new(params[:resource]
      resource.avatar = avatar
      resource save
    end
    

    source: https://github.com/thoughtbot/paperclip/issues/1279