Shrine: ActiveRecord callbacks not working with direct s3 upload through Uppy

Created on 20 Aug 2019  Â·  2Comments  Â·  Source: shrinerb/shrine

Brief Description

When creating an AR object with image_data taken from Uppy the activerecord plugin does not run callbacks. It's impossible to run processing or backgrounding plugins.

The reason behind it is probably the attacher which changed? method always returns false. Even with assign being called manually.

Expected behavior

After saving a record with attachment data from Uppy the activerecord, processing and backgrounding plugins would work as expected.

Actual behavior

The activerecord callbacks are in fact run, but they quit at the beginning because of attacher.changed? being false which prevents them from doing any action. The processing plugin does not work - process block is never called. The backgrounding plugin does not work - promote block is never called.

Simplest self-contained example code to demonstrate issue

_config/initializers/shrine.rb_

# frozen_string_literal: true

require 'shrine'
require 'shrine/storage/s3'

s3_options =
  {}.tap do |hash|
    hash[:access_key_id] = ENV['AWS_S3_ACCESS_KEY_ID']
    hash[:secret_access_key] = ENV['AWS_S3_SECRET_ACCESS_KEY']
    hash[:bucket] = ENV['AWS_S3_BUCKET']
    hash[:region] = ENV['AWS_S3_REGION']
  end

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'cache', **s3_options),
  store: Shrine::Storage::S3.new(prefix: 'uploads', **s3_options)
}

Shrine.plugin :instrumentation
Shrine.plugin :determine_mime_type
Shrine.plugin :presign_endpoint,
  presign_options: lambda { |request|
    filename = request.params['filename']
    type     = request.params['type']

    {
      content_disposition: "inline; filename=\"#{filename}\"",
      content_type: type,
      content_length_range: 0..(10 * 1024 * 1024), # limit upload size to 10 MB
      success_action_status: '201'
    }
  }

_app/uploaders/image_uploader.rb_

# frozen_string_literal: true

require 'image_processing/mini_magick'

class ImageUploader < Shrine
  plugin :activerecord
  plugin :processing
  plugin :versions
  plugin :store_dimensions
  plugin :delete_raw

  process(:cache) do |io, context|
    binding.pry
  end

  process(:store) do |io, context|
    binding.pry
  end

  def process(io, context)
    binding.pry
  end
end

_app/models/image.rb_

class Image < ApplicationRecord
  include ImageUploader[:image]

  belongs_to :owner, polymorphic: true
end

and the operation itself:

      # data contains image_data with uppy json
      profile_image = owner.profile_image || ProfileImage.new(owner: owner)
      data.delete(:id) if profile_image.persisted?
      profile_image.tap do |pi|
        pi.assign_attributes(data)
        pi.save!
      end

System configuration

Ruby version: 2.6.3
Shrine version: 2.19.3

Most helpful comment

Hi Mateusz, sorry for not replying to your earlier email.

Are you assigning to the image_data column attribute directly? You should be assigning the image attribute. Shrine doesn't detect changes to the image_data attribute, it's only intended as a backdoor when you want to bypass Shrine.

All 2 comments

Hi Mateusz, sorry for not replying to your earlier email.

Are you assigning to the image_data column attribute directly? You should be assigning the image attribute. Shrine doesn't detect changes to the image_data attribute, it's only intended as a backdoor when you want to bypass Shrine.

Hi Janko

Thank you so so much!
I spent more time on that that I’d like to admit and I knew it must’ve been something silly :)

As you’ve already seen, I started an issue on GitHub.
I’ll post a comment shortly that it solves the issue and you can close it.

Maybe it’s a good idea to put that little trick in the documentation somewhere because it slipped my attention.

Thank you very much again,

All the best,
Mateusz

On 20 Aug 2019, 12:53 +0200, Janko Marohnić notifications@github.com, wrote:

Hi Mateusz, sorry for not replying to your earlier email.
Are you assigning to the image_data column attribute directly? You should be assigning the image attribute. Shrine doesn't detect changes to the image_data attribute, it's only intended as a backdoor when you want to bypass Shrine.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

uurcank picture uurcank  Â·  10Comments

musaffa picture musaffa  Â·  7Comments

tayagi-aim picture tayagi-aim  Â·  5Comments

printercu picture printercu  Â·  10Comments

technodrome picture technodrome  Â·  4Comments