gpt4 book ai didi

ruby-on-rails - 在 Rails 项目中不断自动加载的问题(偶尔工作)

转载 作者:太空宇宙 更新时间:2023-11-03 16:13:01 24 4
gpt4 key购买 nike

我正在处理一个 Rails 项目,不太了解 Rails 自动加载在我的特定情况下是如何工作的。我阅读了一些有关 Rails 的自动加载及其陷阱的文章,但这些文章并没有真正帮助我

我正在为任务(练习)构建一个处理器。每个任务在 Tasks::<TaskName>::Processor 中都有其自定义处理器类混合在模块中 Tasks::Processor包含任务处理器的共享代码。处理器包含类 Get (用于处理 GET 请求)位于 Tasks::<TaskName>::Processor::Get混入 Tasks::Processor::Get包含通用 Get的代码。

我稍微简化了代码以便更容易理解并删除了所有业务逻辑,但它仍然足以重现问题。

所以问题是:

当我运行 Tasks::TaskOne::Processor.new.get 时它工作正常,但如果我运行 Tasks::TaskTwo::Processor.new.get之后它会抛出一个错误:NoMethodError: undefined method `new' for Tasks::Processor::Get:Module。反之亦然:如果我先运行 TaskTwo 的处理器代码,那么它工作正常,但 TaskOne 的处理器将抛出错误。它只是找不到 Get 的具体实现,而是找到通用模块并尝试实例化它,这显然是不可能的。

这是代码和结构。

共享代码:

app/models/tasks/processor.rb:

module Tasks

# generic Processor (mixed in by custom processors)
module Processor
# ...
end
end

app/models/tasks/processor/get.rb:

module Tasks
module Processor

# generic Get
module Get
# ...
end
end
end

TaskOne的代码:

app/models/tasks/task_one/processor.rb:

module Tasks
module TaskOne

# processor for task_one
class Processor
include Tasks::Processor # mix in generic task processor

def get
Get.new.call
end
end
end
end

app/models/tasks/task_one/processor/get.rb:

module Tasks
module TaskOne
class Processor

# task_one's processor's custom Get
class Get
include Tasks::Processor::Get # mix in generic Get

def call
puts "in task_one's Processor's Get"
end
end
end
end
end

TaskTwo 的代码几乎相同:

app/models/tasks/task_two/processor.rb:

module Tasks
module TaskTwo

# processor for task_two
class Processor
include Tasks::Processor # mix in generic task processor

def get
Get.new.call
end
end
end
end

app/models/tasks/task_two/processor/get.rb:

module Tasks
module TaskTwo
class Processor

# task_two's processor's custom Get
class Get
include Tasks::Processor::Get # mix in generic Get

def call
puts "in task_two's Processor's Get"
end
end
end
end
end

这很可能与 Rails 的自动加载有关,因为当我使用纯 ruby​​ 并手动要求所有文件并尝试运行代码时,问题并没有发生。你能解释一下为什么它会这样工作并告诉我避免这个问题的最好方法是什么吗?似乎 Rails 不喜欢我有一个同名的类和一个模块,这会让人感到困惑,但我认为这应该不是问题,因为它们位于不同的命名空间中。我本可以将通用类命名为不同的东西,但我真的很想了解为什么对特定实现和通用实现使用相同的类名只适用于第一个要加载的东西而不适用于下一个。非常感谢您的帮助!

附言我的 Ruby 版本是 2.5.1,Rails 版本是 5.2.1

最佳答案

我昨天确实在阅读有关自动加载的内容。您的问题与此处概述的问题相同:

https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#when-constants-aren-t-missed

基本上,无论何时编写 Get.new.call,都需要更加具体。它不知道在可能的 Get 树中使用哪个 Get。第一次调用它时,它不必加载多个 Get 类,因此它实际上找到了正确的类。在那个调用之后,你现在已经自动加载了更多的类,现在事情开始变得危险了。您需要使 Get 更具体,和/或使用 require_dependency 强制加载正确的类。但是考虑到您的情况,我认为 require_dependency 只会让它每次都失败,因为您现在已经加载了所有类。

关于ruby-on-rails - 在 Rails 项目中不断自动加载的问题(偶尔工作),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56308340/

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