猴子补丁 ActiveStorage::Attachment 迷路了

Monkey patching ActiveStorage::Attachment gets lost

所以我决定添加一个 url attr_accessor 到 ActiveStorage::Attachment 个对象。

开发 中,补丁会保留一段时间,直到看起来 "have been lost"。这意味着它工作了几分钟,然后就不再工作了。然后我需要重新启动服务器才能再次应用补丁。我相信我没有正确打补丁,我需要这方面的建议。


这是我尝试过的:

lib/ext/active_storage/attachment.rb

第一次尝试:

module ActiveStorageUrl
  extend ActiveSupport::Concern

  included do
    attr_accessor :url
  end
end

ActiveStorage::Attachment.send :include, ActiveStorageUrl

第二次尝试

class ActiveStorage::Attachment < ActiveRecord::Base
  attr_accessor :url
end

顺便说一下,在这两种情况下它都加载了这个:

config/initializers/monkey_patches.rb

require 'ext/active_storage/attachment'

所以当它工作时我没有错误消息,但过了一会儿补丁 "diseapear"(缺少更好的术语),我得到以下错误,告诉我我的 attr_accessor 不存在了。 Rails 必须重新加载 ActiveStorage 类 而我的补丁丢失了。

Module::DelegationError in Products#images
url delegated to blob, but blob is nil

似乎与delegate_missing_to有关,例如

delegate_missing_to :blob

https://github.com/rails/rails/blob/master/activestorage/app/models/active_storage/attachment.rb#L14

要去where it's defined

无论如何,这可能与 attr_accessor 的工作方式有关,我会尝试:

def url
  @url
end

def url=(url)
  @url = url
end

而不是 attr_accessor(实际上是一个 C 函数)。

否则,解决这个问题的一个非常非常 hacky 的方法是检查 ActiveStorage::Attachment.instance_methods.include?(:url) 和 monkey patch / include / prepend when not present.

我将 ActiveStorage::AttachmentMonkeyPatch 放在了 /app/models/active_storage/
如果附件已更改,我添加了一个回调以得到通知。它一直运行良好。

也许这就是问题所在。

您可能正在丢失您的猴子补丁,因为代码被重新加载并且您的 ext/active_storage/attachment 不再需要。

您可以告诉 Rails 到 运行 启动时的回调,以及每次重新加载代码时的回调。

Rails.configuration.to_prepare do
  require 'ext/active_storage/attachment'
end