Shrine: backgrounding documentation update - location of plugin: backgrounding

Created on 19 Oct 2017  路  5Comments  路  Source: shrinerb/shrine

This one is a bit mystifying. I removed my namespaces from the job to take it out of the equation, but still see the same error. Is the structure of shrine compatible with namespaced usage? What am I missing here?

Error

NoMethodError:
  undefined method `promote' for Shrine::Attacher:Class
# ./app/jobs/shrine_promote_job.rb:6:in `perform'
# /Users/kross/.rvm/gems/ruby-2.4.1@af/gems/sidekiq-5.0.5/lib/sidekiq/testing.rb:301:in `execute_job'

Uploaders

module Af
  module Uploader
    class PdfUploader < ::Shrine
      plugin :determine_mime_type
      plugin :validation_helpers

      Attacher.validate do
        validate_extension_inclusion %w(pdf)
        validate_max_size 15.megabytes, message: 'is too large (max is 15 MB)'
        validate_mime_type_inclusion ['application/pdf']
      end
    end
  end
end
module Af
  module Uploader
    class BackgroundPdfUploader < PdfUploader
      plugin :backgrounding
      Attacher.promote { |data| ShrinePromoteJob.perform_async(data) }
      Attacher.delete { |data| ShrineDeleteJob.perform_async(data) }
    end
  end
end

Job

class ShrinePromoteJob
  include ::Sidekiq::Worker
  def perform(data)
    Shrine::Attacher.promote(data)
  end
end

Usage

module Af
  module Commerce
    class Agreement < ActiveRecord::Base
      if Af.dev?
        # in dev, do everything in the foreground to ease seeding
        include Af::Uploader::PdfUploader::Attachment.new(:document)
      else
        # in every other environment, background the work
        include Af::Uploader::BackgroundPdfUploader::Attachment.new(:document)
      end
    end
  end
end

Most helpful comment

Figured it out.

The plugin provides Attacher.promote and Attacher.delete methods, which allow you to hook up to promoting and deleting and spawn background jobs, by passing a block.

Shrine.plugin :backgrounding
Shrine::Attacher.promote { |data| PromoteJob.perform_async(data) }
Shrine::Attacher.delete { |data| DeleteJob.perform_async(data) }
If you don't want to apply backgrounding for all uploaders, you can declare the hooks only for specific uploaders.

class MyUploader < Shrine
Attacher.promote { |data| PromoteJob.perform_async(data) }
Attacher.delete { |data| DeleteJob.perform_async(data) }
end

It might be worth noting in this section, that the Shrine.plugin :backgrounding must be done in the initializer, even though you select the specific uploaders to do the:

  Attacher.promote { |data| PromoteJob.perform_async(data) }
  Attacher.delete { |data| DeleteJob.perform_async(data) }

The current doc is technically correct, but this is a bit of a gotcha/hard to spot.

All 5 comments

Note, the same results occur with explicit root Shrine namespace usage from the job:

  class ShrinePromoteJob
    include ::Sidekiq::Worker
    def perform(data)
      ::Shrine::Attacher.promote(data)
    end
  end

I also tried collapsing the BackgroudPdfUploader so it had no other hierarchy:

module Af
  module Uploader
    class BackgroundPdfUploader < ::Shrine
      plugin :determine_mime_type
      plugin :validation_helpers
      Attacher.validate do
        validate_extension_inclusion %w(pdf)
        validate_max_size 15.megabytes, message: 'is too large (max is 15 MB)'
        validate_mime_type_inclusion ['application/pdf']
      end

      plugin :backgrounding

      Attacher.promote { |data| ShrinePromoteJob.perform_async(data) }
      Attacher.delete { |data| ShrineDeleteJob.perform_async(data) }
    end
  end
end

Same error.

If I move the backgrounding setup to the initializer, it all works, so it appears it has be turned on or off for the entire system.

Figured it out.

The plugin provides Attacher.promote and Attacher.delete methods, which allow you to hook up to promoting and deleting and spawn background jobs, by passing a block.

Shrine.plugin :backgrounding
Shrine::Attacher.promote { |data| PromoteJob.perform_async(data) }
Shrine::Attacher.delete { |data| DeleteJob.perform_async(data) }
If you don't want to apply backgrounding for all uploaders, you can declare the hooks only for specific uploaders.

class MyUploader < Shrine
Attacher.promote { |data| PromoteJob.perform_async(data) }
Attacher.delete { |data| DeleteJob.perform_async(data) }
end

It might be worth noting in this section, that the Shrine.plugin :backgrounding must be done in the initializer, even though you select the specific uploaders to do the:

  Attacher.promote { |data| PromoteJob.perform_async(data) }
  Attacher.delete { |data| DeleteJob.perform_async(data) }

The current doc is technically correct, but this is a bit of a gotcha/hard to spot.

Glad that you figured it out by yourself. Ok, I'll see how I can make the backgrounding documentation a bit clearer.

Was this page helpful?
0 / 5 - 0 ratings