好的,我正在开发一个 Rails gem,我希望它覆盖 sprocket 中的特定方法。
我要重写的方法是:链轮::Base.digest这样我就可以在编译应用程序的资产时根据我的 gem 版本来确定指纹。
我该怎么做呢?
在我的 gem 中,我创建一个文件 lib/sprockets/base.rb 并放置以下代码:
class Sprockets::Base
def digest
@digest = digest_class.new.update(MyGem::VERSION)
@digest.dup
end
end
当我跑步时bundle exec rake assets:precompile
I get:
undefined method 'logger=' for #<Sprockets::Environment:0x1315b040>
因此,在我看来,整个类似乎都以某种方式被重写(这失去了该方法以及其他方法),而不仅仅是重写一个方法。
如果我将该代码片段直接包含到使用这两个 gem 的应用程序的 rakefile 中,那么一切都会完美运行。
以这种方式覆盖整个 Ruby 类是不可能的,但我认为它is可能会阻止原始类加载...如果它使用自动加载。我很好奇,所以我查看了https://github.com/sstephenson/sprockets/blob/master/lib/sprockets.rb,是的,Sprockets 正在使用自动加载。
autoload :Base, "sprockets/base"
重要的是,那doesn't加载代码。它只是告诉 Ruby,如果/当遇到名为“Sprockets::Base”的未定义常量时,从指定文件加载它。您的补丁在任何地方调用之前定义了 Sprockets::Base,从而阻止加载原始文件。
当您将补丁移至 Rakefile 时,Rails 中的某些内容已经引用了 Sprockets::Base,从而加载了原始代码。然后将你的补丁干净地贴在上面。
我从未真正使用过自动加载,所以我不确定应该如何处理这样的情况。但我敢打赌,这会起作用:
Sprockets::Base
class Sprockets::Base
def digest
...
通过首先引用该类,您应该强制 Ruby 加载原始类。然后您就可以安全地进行重写其方法之一的工作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)