3

I have a callback defined in my video uploader class of carrierwave
after :store, :my_method
and I have three versions of the files. original,standard,low

my_method executes when each version is processed ie, three times, I just need the callback to execute once.

Ojash
  • 1,234
  • 8
  • 20

2 Answers2

13

I know this is a very late response but I was just having the same problem lately so I decided to post how I solved this "problem" since it seems it isn't documented on carrierwave's github page (or I wasn't able to find it anyway).

Ok, regarding the after :store, :my_method callback if you place it in the "main body" of your uploader class, then it's going to be executed every single time a file is stored, so in your case I think it even executes not only for your 3 versions but for your original file as well.

Let's say the following code defines your carrierwave uploader:

class PhotoUploader < CarrierWave::Uploader::Base
  after :store, :my_method

  version :original do
    process :resize_to_limit => [1280,960]
  end

  version :standard, from_version: :original do
    process :resize_to_limit => [640,480]
  end

  version :low, from_version: :standard do
    process :resize_to_limit => [320,240]
  end

  protected
    def my_method
      puts self.version_name
    end
end

That way, the after :store is going to be executed for every file stored, but if you only want it to be executed, let's say, for the :low version, all you have to do is to move that line inside your version definition. Like this:

class PhotoUploader < CarrierWave::Uploader::Base

  version :original do
    process :resize_to_limit => [1280,960]
  end

  version :standard, from_version: :original do
    process :resize_to_limit => [640,480]
  end

  version :low, from_version: :standard do
    process :resize_to_limit => [320,240]
    after :store, :my_method
  end

  protected
    def my_method
      puts self.version_name
    end
end

I tested it on my code and it works... I know it's been a long time since you posted this question and probably you arrived at the same solution as me. So I decided to answer it for future reference for anyone getting the same problem.

Abraham Milano
  • 164
  • 2
  • 12
0

I needed just the same thing, and I found out that the original version (which is called nil inside carrierwave) is always processed last. I couldn't find out why in the source files, and it feels counter-intuitive when looking at the code, but simple puts with version_name reveals that it is so.

You could use this fact for your problem:

after :store, :my_method

def my_method(_file = nil)
  return if version_name

  # do something only once, after all versions are stored
end


I used carrierwave_backgrounder gem and its process_in_background feature along with gem's optional <uploader_name>_processing column, which gave me a possibility to use the after_update callback on the model like this:

# some_model.rb
class SomeModel < ActiveRecord::Base
  mount_uploader :image, ImageUploader
  
  after_update do
    if image_processing_changed? && image_processing == false
      # do your stuff e.g. check if the image was actually uploaded to cloud.
      # S3 client from `fog-aws` gem has a handy head_object method to do that.
    end
  end
end

I first thought I can't rely on this callback, because I only process_in_background, not storing as well, but later I found out that even though the processing takes place in background and isn't supposed to store in background, it does include storing as a part of the recreate_versions method, and as the whole process is already happening in background, storing happens in background (though synchronously), too, and it's safe to rely on this callback.

Here's the chain of involved methods calls: process_in_background, ProcessAsset, recreate_versions!, setting image_processing flag to false.

carrierwave 1.3.1 carrierwave_backgrounder 0.4.2

victorpolko
  • 359
  • 3
  • 4