diff --git a/lib/backgrounder/orm/activemodel.rb b/lib/backgrounder/orm/activemodel.rb index f463db12..faa89ea5 100644 --- a/lib/backgrounder/orm/activemodel.rb +++ b/lib/backgrounder/orm/activemodel.rb @@ -9,7 +9,7 @@ module ActiveModel private - def _define_shared_backgrounder_methods(mod, column, worker) + def _define_shared_backgrounder_methods(mod, column, worker, callback) before_save :"set_#{column}_processing", :if => :"enqueue_#{column}_background_job?" send _supported_callback, :"enqueue_#{column}_background_job", :if => :"enqueue_#{column}_background_job?" diff --git a/lib/backgrounder/orm/base.rb b/lib/backgrounder/orm/base.rb index 2ba01c88..d718c149 100644 --- a/lib/backgrounder/orm/base.rb +++ b/lib/backgrounder/orm/base.rb @@ -23,12 +23,17 @@ module Base # @user.process_avatar = true # @user.save # - # You can also pass in your own workers using the second argument in case you need other things done - # during processing. + # You can also pass in your own worker or callback which will be fired after processing and storage of attachement. # # class User < ActiveRecord::Base # mount_uploader :avatar, AvatarUploader - # process_in_background :avatar, CustomWorker + # process_in_background :avatar, worker: CustomWorker, after_store: :do_something_cool + # + # private + # + # def do_something_cool + # ... + # end # end # # In addition you can also add a column to the database appended by _processing with a type of boolean @@ -38,13 +43,15 @@ module Base # add_column :users, :avatar_processing, :boolean # end # - def process_in_background(column, worker=::CarrierWave::Workers::ProcessAsset) + def process_in_background(column, options={}) attr_accessor :"process_#{column}_upload" + worker = options[:worker] || ::CarrierWave::Workers::ProcessAsset + mod = Module.new include mod - _define_shared_backgrounder_methods(mod, column, worker) + _define_shared_backgrounder_methods(mod, column, worker, options[:after_store]) end ## @@ -69,9 +76,11 @@ def process_in_background(column, worker=::CarrierWave::Workers::ProcessAsset) # store_in_background :avatar, CustomWorker # end # - def store_in_background(column, worker=::CarrierWave::Workers::StoreAsset) + def store_in_background(column, options={}) attr_accessor :"process_#{column}_upload" + worker = options[:worker] || ::CarrierWave::Workers::StoreAsset + mod = Module.new include mod mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -91,12 +100,12 @@ def store_#{column}! RUBY - _define_shared_backgrounder_methods(mod, column, worker) + _define_shared_backgrounder_methods(mod, column, worker, options[:after_store]) end private - def _define_shared_backgrounder_methods(mod, column, worker) + def _define_shared_backgrounder_methods(mod, column, worker, callback) mod.class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{column}_updated?; true; end @@ -109,7 +118,7 @@ def enqueue_#{column}_background_job? end def enqueue_#{column}_background_job - CarrierWave::Backgrounder.enqueue_for_backend(#{worker}, self.class.name, id.to_s, #{column}.mounted_as) + CarrierWave::Backgrounder.enqueue_for_backend(#{worker}, self.class.name, id.to_s, #{column}.mounted_as, callback) end RUBY end diff --git a/lib/backgrounder/orm/data_mapper.rb b/lib/backgrounder/orm/data_mapper.rb index 39436369..bd15cebd 100644 --- a/lib/backgrounder/orm/data_mapper.rb +++ b/lib/backgrounder/orm/data_mapper.rb @@ -5,7 +5,7 @@ module ORM module DataMapper include CarrierWave::Backgrounder::ORM::Base - def process_in_background(column, worker=::CarrierWave::Workers::ProcessAsset) + def process_in_background(column, options={}) super class_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -16,7 +16,7 @@ def set_#{column}_processing RUBY end - def store_in_background(column, worker=::CarrierWave::Workers::StoreAsset) + def store_in_background(column, options={}) super class_eval <<-RUBY, __FILE__, __LINE__ + 1 @@ -33,7 +33,7 @@ def write_#{column}_identifier private - def _define_shared_backgrounder_methods(mod, column, worker) + def _define_shared_backgrounder_methods(mod, column, worker, callback) before :save, :"set_#{column}_changed" after :save, :"enqueue_#{column}_background_job" @@ -44,7 +44,7 @@ def _define_shared_backgrounder_methods(mod, column, worker) def enqueue_#{column}_background_job if enqueue_#{column}_background_job? - CarrierWave::Backgrounder.enqueue_for_backend(#{worker}, self.class.name, id, #{column}.mounted_as) + CarrierWave::Backgrounder.enqueue_for_backend(#{worker}, self.class.name, id, #{column}.mounted_as, callback) @#{column}_changed = false end end diff --git a/lib/backgrounder/support/backends.rb b/lib/backgrounder/support/backends.rb index 369f97d7..4256f68a 100644 --- a/lib/backgrounder/support/backends.rb +++ b/lib/backgrounder/support/backends.rb @@ -16,8 +16,8 @@ def backend(queue_name=nil, args={}) @backend = queue_name end - def enqueue_for_backend(worker, class_name, subject_id, mounted_as) - self.send :"enqueue_#{backend}", worker, class_name, subject_id, mounted_as + def enqueue_for_backend(worker, class_name, subject_id, mounted_as, callback=nil) + self.send :"enqueue_#{backend}", worker, class_name, subject_id, mounted_as, callback end private @@ -61,8 +61,8 @@ def enqueue_qu(worker, *args) end def enqueue_qc(worker, *args) - class_name, subject_id, mounted_as = args - ::QC.enqueue "#{worker.name}.perform", class_name, subject_id, mounted_as.to_s + class_name, subject_id, mounted_as, callback = args + ::QC.enqueue "#{worker.name}.perform", class_name, subject_id, mounted_as.to_s, callback end def enqueue_immediate(worker, *args) diff --git a/lib/backgrounder/workers/base.rb b/lib/backgrounder/workers/base.rb index cadba7fb..9b0f1ec0 100644 --- a/lib/backgrounder/workers/base.rb +++ b/lib/backgrounder/workers/base.rb @@ -1,6 +1,6 @@ module CarrierWave module Workers - class Base < Struct.new(:klass, :id, :column) + class Base < Struct.new(:klass, :id, :column, :callback) def self.perform(*args) new(*args).perform @@ -21,8 +21,8 @@ def not_found_errors end end - def set_args(klass, id, column) - self.klass, self.id, self.column = klass, id, column + def set_args(klass, id, column, callback=nil) + self.klass, self.id, self.column, self.callback = klass, id, column, callback end def constantized_resource diff --git a/lib/backgrounder/workers/process_asset.rb b/lib/backgrounder/workers/process_asset.rb index 389ef019..40eff543 100644 --- a/lib/backgrounder/workers/process_asset.rb +++ b/lib/backgrounder/workers/process_asset.rb @@ -11,6 +11,7 @@ def perform(*args) record.send(:"process_#{column}_upload=", true) if record.send(:"#{column}").recreate_versions! && record.respond_to?(:"#{column}_processing") record.update_attribute :"#{column}_processing", false + record.send(callback) if callback end end end diff --git a/lib/backgrounder/workers/store_asset.rb b/lib/backgrounder/workers/store_asset.rb index df93b8fd..0c373d10 100644 --- a/lib/backgrounder/workers/store_asset.rb +++ b/lib/backgrounder/workers/store_asset.rb @@ -15,6 +15,7 @@ def perform(*args) record.send :"#{column}_processing=", false if record.respond_to?(:"#{column}_processing") File.open(cache_path) { |f| record.send :"#{column}=", f } if record.save! + record.send(callback) if callback FileUtils.rm_r(tmp_directory, :force => true) end end diff --git a/spec/backgrounder/support/backends_spec.rb b/spec/backgrounder/support/backends_spec.rb index 8b367156..e02b0c17 100644 --- a/spec/backgrounder/support/backends_spec.rb +++ b/spec/backgrounder/support/backends_spec.rb @@ -81,7 +81,7 @@ def self.perform(*args); new(*args).perform; end end context 'resque' do - let(:args) { [MockWorker, 'FakeClass', 1, :image] } + let(:args) { [MockWorker, 'FakeClass', 1, :image, nil] } before do Resque.expects(:enqueue).with(*args) @@ -101,7 +101,7 @@ def self.perform(*args); new(*args).perform; end end context 'sidekiq' do - let(:args) { ['FakeClass', 1, :image] } + let(:args) { ['FakeClass', 1, :image, :callback] } it 'invokes client_push on the class with passed args' do MockSidekiqWorker.expects(:client_push).with({ 'class' => MockSidekiqWorker, 'args' => args }) @@ -153,20 +153,20 @@ def self.perform(*args); new(*args).perform; end end context 'sucker_punch' do - let(:args) { [MockWorker, 'FakeClass', 1, :image] } + let(:args) { [MockWorker, 'FakeClass', 1, :image, :callback] } let(:job) { mock('job') } it 'invokes a new worker' do MockWorker.expects(:new).returns(worker) worker.expects(:async).returns(job) - job.expects(:perform).with('FakeClass', 1, :image) + job.expects(:perform).with('FakeClass', 1, :image, :callback) mock_module.backend :sucker_punch mock_module.enqueue_for_backend(*args) end end context 'qu' do - let(:args) { [MockWorker, 'FakeClass', 1, :image] } + let(:args) { [MockWorker, 'FakeClass', 1, :image, :callback] } before do Qu.expects(:enqueue).with(*args) end @@ -186,19 +186,19 @@ def self.perform(*args); new(*args).perform; end context 'qc' do it 'calls enqueue with the passed args' do - QC.expects(:enqueue).with("MockWorker.perform", 'FakeClass', 1, 'image') + QC.expects(:enqueue).with("MockWorker.perform", 'FakeClass', 1, 'image', :callback) mock_module.backend :qc - mock_module.enqueue_for_backend(MockWorker, 'FakeClass', 1, :image) + mock_module.enqueue_for_backend(MockWorker, 'FakeClass', 1, :image, :callback) end end context 'immediate' do it 'instantiates a worker passing the args and calls perform' do worker = mock('Worker') - MockWorker.expects(:new).with('FakeClass', 1, :image).returns(worker) + MockWorker.expects(:new).with('FakeClass', 1, :image, :callback).returns(worker) worker.expects(:perform) mock_module.backend :immediate - mock_module.enqueue_for_backend(MockWorker, 'FakeClass', 1, :image) + mock_module.enqueue_for_backend(MockWorker, 'FakeClass', 1, :image, :callback) end end diff --git a/spec/backgrounder/workers/process_asset_spec.rb b/spec/backgrounder/workers/process_asset_spec.rb index 7d8c23c8..567818a3 100644 --- a/spec/backgrounder/workers/process_asset_spec.rb +++ b/spec/backgrounder/workers/process_asset_spec.rb @@ -5,7 +5,7 @@ describe CarrierWave::Workers::ProcessAsset do let(:worker_class) { CarrierWave::Workers::ProcessAsset } let(:user) { mock('User') } - let!(:worker) { worker_class.new(user, '22', :image) } + let!(:worker) { worker_class.new(user, '22', :image, :callback_method) } describe ".perform" do it 'creates a new instance and calls perform' do @@ -28,6 +28,7 @@ end it 'processes versions with image_processing column' do + user.expects(:callback_method).once user.expects(:respond_to?).with(:image_processing).once.returns(true) user.expects(:update_attribute).with(:image_processing, false).once worker.perform diff --git a/spec/backgrounder/workers/store_asset_spec.rb b/spec/backgrounder/workers/store_asset_spec.rb index 395ac346..7fc41b76 100644 --- a/spec/backgrounder/workers/store_asset_spec.rb +++ b/spec/backgrounder/workers/store_asset_spec.rb @@ -6,7 +6,7 @@ let(:fixtures_path) { File.expand_path('../fixtures/images', __FILE__) } let(:worker_class) { CarrierWave::Workers::StoreAsset } let(:user) { mock('User') } - let!(:worker) { worker_class.new(user, '22', :image) } + let!(:worker) { worker_class.new(user, '22', :image, :callback_method) } describe ".perform" do it 'creates a new instance and calls perform' do @@ -34,6 +34,7 @@ it 'removes tmp directory on success' do FileUtils.expects(:rm_r).with(fixtures_path, :force => true).once user.expects(:save!).once.returns(true) + user.expects(:callback_method).once worker.perform end diff --git a/spec/support/mock_worker.rb b/spec/support/mock_worker.rb index af526830..7961f80f 100644 --- a/spec/support/mock_worker.rb +++ b/spec/support/mock_worker.rb @@ -1,4 +1,4 @@ -class MockWorker < Struct.new(:klass, :id, :column) +class MockWorker < Struct.new(:klass, :id, :column, :callback) def self.perform(*args) new(*args).perform end @@ -7,8 +7,8 @@ def perform(*args) set_args(*args) unless args.empty? end - def set_args(klass, id, column) - self.klass, self.id, self.column = klass, id, column + def set_args(klass, id, column, callback=nil) + self.klass, self.id, self.column, self.callback = klass, id, column, callback end end