Callback for Active Storage file upload

我的梦境 提交于 2020-07-09 03:08:06

问题


Is there a callback for active storage files on a model

after_update or after_save is getting called when a field on the model is changed. However when you update (or rather upload a new file) no callback seems to be called?

context:

class Person < ApplicationRecord
  #name :string
  has_one_attached :id_document

  after_update :call_some_service

  def call_some_service
    #do something
  end
end

When a new id_document is uploaded after_update is not called however when the name of the person is changed the after_update callback is executed


回答1:


For now, it seems like there is no callback for this case.

What you could do is create a model to handle the creation of an active storage attachment which is what is created when you attach a file to your person model.

So create a new model

class ActiveStorageAttachment < ActiveRecord::Base
  after_update :after_update

  private
  def after_update
    if record_type == 'Person'
      record.do_something
    end
  end
end

You normally have created the model table already in your database so no need for a migration, just create this model




回答2:


The answer from @Uleb got me 90% of the way, but for completion sake I will post my final solution.

The issue I had was that I was not able to monkey patch the class (not sure why, even requiring the class as per @user10692737 did not help)

So I copied the source code (https://github.com/rails/rails/blob/fc5dd0b85189811062c85520fd70de8389b55aeb/activestorage/app/models/active_storage/attachment.rb#L20)

and modified it to include the callback

require "active_support/core_ext/module/delegation"

# Attachments associate records with blobs. Usually that's a one record-many blobs relationship,
# but it is possible to associate many different records with the same blob. If you're doing that,
# you'll want to declare with <tt>has_one/many_attached :thingy, dependent: false</tt>, so that destroying
# any one record won't destroy the blob as well. (Then you'll need to do your own garbage collecting, though).
class ActiveStorage::Attachment < ActiveRecord::Base
  self.table_name = "active_storage_attachments"

  belongs_to :record, polymorphic: true, touch: true
  belongs_to :blob, class_name: "ActiveStorage::Blob"

  delegate_missing_to :blob

  #CUSTOMIZED AT THE END:
  after_create_commit :analyze_blob_later, :identify_blob, :do_something

  # Synchronously purges the blob (deletes it from the configured service) and destroys the attachment.
  def purge
    blob.purge
    destroy
  end

  # Destroys the attachment and asynchronously purges the blob (deletes it from the configured service).
  def purge_later
    blob.purge_later
    destroy
  end


  private
    def identify_blob
      blob.identify
    end

    def analyze_blob_later
      blob.analyze_later unless blob.analyzed?
    end

    #CUSTOMIZED:
    def do_something

    end
end

Not sure its the best method, and will update if I find a better solution




回答3:


Erm i would just comment but since this is not possible without rep..

Uelb's answer works but you need to fix the error in comments and add it as an initializer instead of model. Eg:

require 'active_storage/attachment'

class ActiveStorage::Attachment
  before_save :do_something

  def do_something
    puts 'yeah!'
  end
end



回答4:


In my case tracking attachment timestamp worked

class Person < ApplicationRecord
  has_one_attached :id_document

  after_save do    
    if id_document.attached? && (Time.now  - id_document.attachment.created_at)<5
      Rails.logger.info "id_document change detected"
    end
  end
end


来源:https://stackoverflow.com/questions/53226228/callback-for-active-storage-file-upload

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!