gpt4 book ai didi

ruby - ruby gems/模块的命名空间扩展的约定是什么?

转载 作者:行者123 更新时间:2023-12-04 17:04:22 27 4
gpt4 key购买 nike

我一生都找不到对此的任何简单解释。

我正在开发一个项目,它有自己的自定义代码,但也有一些对可用类的扩展/覆盖,虽然包含 gems。

实现此目的的正确文件夹结构和模块命名模式是什么?

例如,这里是我为第三方“parallel_tests”gem 的扩展组织代码的方式,我正在处理的库称为“ChemistyKit”:

lib/
chemistrykit/
parallel_tests/ # the gem name space i'm extending
rspec/
runner.rb

所以我基本上遵循相同的 gem 命名结构,低于 parallel_tests文件夹。

然后在那 runner.rb文件我有类似的东西:
module ChemistryKit
module ParallelTests
module RSpec
class Runner < ParallelTests::Test::Runner

但是,使用它会导致错误。我认为这是因为它实际上从未超过相关类,因为它的命名空间位于 ChemistryKit 下。这很令人困惑,因为在 this extension of the RSpec HTML formatter 之类的东西中,格式化程序在 gem 的顶级命名空间下使用。那是因为在这种情况下它创建了一个名称相似但不同的类吗?目的不是覆盖,而是扩展?

最佳答案

要完全替换 RSpec 中的 Runner 类,您需要执行以下操作

module RSpec
module Core
remove_const(:Runner)
class Runner < ParallelTests::Test::Runner
...
end
end
end

模块内部的代码使用基于名称的路径查找常量。因此,您在示例中定义的 Runner 类指的是常量 ChemistryKit::ParallelTests::RSpec::Runner .

您可以通过指定您的 RSpec 模块位于全局命名空间中来从您的模块之一中引用 RSpec Runner,如下例所示。
module ChemistryKit
module ParallelTests
module ::RSpec
module Core
class Runner < ParallelTests::Test::Runner

现在,即使您这样做,以这种方式修改类也存在另一个问题。因为你想替换 Class 你必须先删除它,否则你只会修改现有的类(如果你指定一个不同的父类(super class),你不能重新打开一个类,rspec runner 已经是 Object 的子类,你可以不改变)。这就是 remove_const在我的第一个例子中调用是为了。

然而,在上面的例子中,额外的模块实际上并没有做任何事情,只是让事情变得不那么清楚。修改现有 gem 的代码时,只需将所有代码都放在 rspec 子文件夹中(就像您所做的那样)但与原始模块名称完全相同。

请记住,以这种方式修改类很容易失败。例如,如果在需要时使用该类,则直到之后才会进行替换,这可能会导致不可预见的问题。这就是您链接的格式化程序示例采用不同方法的原因,该代码不会对 RSpec 进行猴子补丁,而是在运行时附加其新类。

关于ruby - ruby gems/模块的命名空间扩展的约定是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18164179/

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