gpt4 book ai didi

ruby - 在没有 `autoload` 的情况下在 Ruby 中自动加载类

转载 作者:数据小太阳 更新时间:2023-10-29 06:30:21 25 4
gpt4 key购买 nike

我爱the autoload functionality of Ruby ;然而,它是 going away in future versions of Ruby因为它从来都不是线程安全的。

所以现在我想假装它已经消失并在没有它的情况下编写我的代码,方法是自己实现延迟加载机制。我想以最简单的方式实现它(我现在不关心线程安全)。 Ruby 应该允许我们这样做。

让我们从扩充一个类开始const_missing:

class Dummy
def self.const_missing(const)
puts "const_missing(#{const.inspect})"
super(const)
end
end

当我们尝试引用“Dummy”下缺少的常量时,Ruby 将调用此特殊方法,例如,如果我们尝试引用“Dummy::Hello”,它将调用 const_missing符号:你好。这正是我们所需要的,所以让我们更进一步:

class Dummy
def self.const_missing(const)
if :OAuth == const
require 'dummy/oauth'
const_get(const) # warning: possible endless loop!
else
super(const)
end
end
end

现在如果我们引用“Dummy::OAuth”,它将需要“dummy/oauth.rb”文件,该文件应该定义“Dummy::OAuth”常量。当我们调用 const_get 时可能会出现无限循环(因为它可以在内部调用 const_missing),但防止这种情况超出了这个问题的范围。

最大的问题是,如果在顶级命名空间中存在名为“OAuth”的模块,整个解决方案就会崩溃。引用“Dummy::OAuth”将跳过其 const_missing 并从顶层返回“OAuth”。大多数 Ruby 实现也会对此发出警告:

warning: toplevel constant OAuth referenced by Dummy::OAuth

This was reported as a problem way back in 2003但我找不到证据表明 Ruby 核心团队曾经关注过这个问题。今天,大多数流行的 Ruby 实现都具有相同的行为。

问题是 const_missing 被悄悄跳过,取而代之的是顶级命名空间中的常量。如果使用 Ruby 的 autoload 功能声明“Dummy::OAuth”,则不会发生这种情况。有什么想法可以解决这个问题吗?

最佳答案

这是前段时间在 Rails 票证中提出的,当我调查它时,似乎没有办法绕过它。问题在于 Ruby 会在调用 const_missing 之前搜索祖先,并且由于所有类都以 Object 作为祖先,因此总会找到任何顶级常量。如果您可以将自己限制为仅使用模块进行命名空间,那么它将起作用,因为它们没有 Object 作为祖先,例如:

>> class A; end
>> class B; end
>> B::A
(irb):3: warning: toplevel constant A referenced by B::A

>> B.ancestors
=> [B, Object, Kernel, BasicObject]

>> module C; end
>> module D; end
>> D::C
NameError: uninitialized constant D::C

>> D.ancestors
=> [D]

关于ruby - 在没有 `autoload` 的情况下在 Ruby 中自动加载类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9053720/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com