Active Storage文件上载的回调



模型上是否有活动存储文件的回调

当模型上的字段发生更改时,将调用after_updateafter_save。但是,当您更新(或者更确切地说上传一个新文件(时,似乎不会调用回调?

上下文:

class Person < ApplicationRecord
#name :string
has_one_attached :id_document
after_update :call_some_service
def call_some_service
#do something
end
end

当上传新的id_document时,不调用after_update,但当人员的name发生变化时,执行after_update回调

目前,似乎没有针对这种情况的回调。

您可以创建一个模型来处理活动存储附件的创建,该附件是在将文件附加到个人模型时创建的。

所以创建一个新的模型

class ActiveStorageAttachment < ActiveRecord::Base
after_update :after_update
private
def after_update
if record_type == 'Person'
record.do_something
end
end
end

您通常已经在数据库中创建了模型表,因此不需要迁移,只需创建此模型

在我的案例中,跟踪附件时间戳有效

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

Erm我只想发表评论,但由于没有代表,这是不可能的。

Uelb的答案有效,但您需要修复注释中的错误,并将其作为初始值设定项而不是模型添加。例如:

require 'active_storage/attachment'
class ActiveStorage::Attachment
before_save :do_something
def do_something
puts 'yeah!'
end
end

这些都没有切中要害,但你可以通过关注这篇博客文章来实现你想要的目标https://redgreen.no/2021/01/25/active-storage-callbacks.html

我可以修改那里的代码来处理附件,而不是像这样的斑点

Rails.configuration.to_prepare do
module ActiveStorage::Attachment::Callbacks
# Gives us some convenient shortcuts, like `prepended`
extend ActiveSupport::Concern
# When prepended into a class, define our callback
prepended do
after_commit :attachment_changed, on: %i[create update]
end
# callback method
def attachment_changed
record.after_attachment_update(self) if record.respond_to? :after_attachment_update
end
end
# After defining the module, call on ActiveStorage::Blob to prepend it in.
ActiveStorage::Attachment.prepend ActiveStorage::Attachment::Callbacks
end

@Uleb的回答让我完成了90%的工作,但为了完成任务,我会发布我的最终解决方案。

我遇到的问题是,我无法对该类进行猴子补丁(不确定为什么,即使按照@user10692737要求该类也无济于事(

所以我复制了源代码(https://github.com/rails/rails/blob/fc5dd0b85189811062c85520fd70de8389b55aeb/activestorage/app/models/active_storage/attachment.rb#L20)

并将其修改为包含回调

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

不确定这是最好的方法,如果我找到更好的解决方案,会更新

我所做的是在我的记录上添加一个回调:

after_touch :check_after_touch_data

如果添加、编辑或删除了ActiveStorage对象,就会调用此函数。我使用此回调来检查是否发生了更改。

最新更新