【问题标题】:Unable to load classes/modules with Zeitwerk on Ruby project无法在 Ruby 项目上使用 Zeitwerk 加载类/模块
【发布时间】:2023-01-19 23:17:31
【问题描述】:

我已经构建了一个 Ruby 项目,我想从使用大量 require_relative 语句切换到更智能的自动加载器,如 Zeitwerk

项目中有很多文件/文件夹,因此我只会展示其中的一些文件/文件夹,以免让我的问题因不必要的细节而变得过于臃肿。您可以在Github 上找到整个项目。

回购的结构如下

chess/
  bin/
    chess
  lib/ 
    chess.rb
    chess/
      board.rb 
      serialize.rb
      coordinates.rb 
      pieces/
      (other files and folders)
  (other files)

bin/chess 是可执行文件,包含

#!/usr/bin/env ruby
require "zeitwerk"

loader = Zeitwerk::Loader.for_gem
loader.setup

Chess.new.start  # method that starts the whole game

lib/chess.rb 包含运行游戏逻辑的class Chess

lib/ 内的所有其他文件都在Zeitwerk file structure 之后。

因此,lib/chess/serialize.rb包含

class Chess 
  module Serialize 
    ... 
  end 
end 

lib/chess/pieces/piece.rb包含

class Chess 
  module Pieces 
    module Piece 
    ... 
    end 
  end 
end

当我尝试运行脚本时,使用bin/chess(或cd进入bin/文件夹并运行./chess),终端返回

uninitialized constant Chess (NameError)

Zeitwerk 似乎没有加载这些文件。我阅读了他们所有的文档,但无法发现问题所在。

编辑: 正如其中一个答案所指出的,我删除了 bin/chess 中的 for_gem 调用

loader = Zeitwerk::Loader.new
loader.tag = File.basename(__FILE__, ".rb")
loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
loader.push_dir("#{__dir__}/../lib")
loader.setup

但是,现在 Chess 命名空间内的所有类/模块都已加载,而位于更深目录中的所有类/模块,如 lib/chess/display/chess_display.rb(即 Chess::Display::ChessDisplay)都不会加载。

【问题讨论】:

    标签: ruby autoload zeitwerk


    【解决方案1】:

    根据自述文件,for_gem 对应于:

    # lib/my_gem.rb
    
    require "zeitwerk"
    loader = Zeitwerk::Loader.new
    loader.tag = File.basename(__FILE__, ".rb")
    loader.inflector = Zeitwerk::GemInflector.new(__FILE__)
    loader.push_dir(__dir__)
    

    请注意 push_dir(__dir__) 并且它应该从 lib/ 目录中调用。您正在从 bin/ 目录中的文件调用它。

    我没有像这样使用过 zeitwork,但我想你可能想要:

    1. 直接要求lib/chess.rb并在该文件中执行Zeitwork::Loader.for_gem
    2. 跳过for_gem并使用上面的sn-p,但将__dir__调整为../lib

    【讨论】:

    • 我已经用 loader.push_dir("#{__dir__}/../lib/") 调整了那个 sn-p,但是现在我得到了错误 uninitialized constant Chess::ChessDisplay (NameError)。基本上位于lib/chess 的模块被加载,而位于嵌套目录(如lib/chess/display/)中的所有模块都没有被加载。
    • 我也试过你提出的第一种方法,但我得到了完全相同的错误。
    猜你喜欢
    • 1970-01-01
    • 2018-01-27
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多