Ruby 模块常量设置和读取

Ruby Module Constant Set and Read

我正在开发一个包含标准方法以及 CLI (Thor) 和 API (Sinatra) 的模块。我创建了一个包含继承 Sinatra::Base:

的 class 的子模块
module Monteverde
  module Activity
    def self.version
      "1.0.1"
    end

    class API < Sinatra::Base
      set :port, 22340
      get "/version" do
        Monteverde::Activity.version
      end
      run! if defined? Monteverde::OPERATION
    end
  end
end

这个 "Activity" 是从 CLI (Thor) 调用的:

module Monteverde
  class CLI < Thor
    desc "api", "Start Activity API"
    def api
      Monteverde.const_set("OPERATION", "started")
      Monteverde::Activity::API
    end

    desc "aversion", "Get Activity Version"
    def aversion
      puts Monteverde::Activity.version
    end
  end
end

如果我不在 Sinatra 的 运行 中添加一个 "if"!它将自动 运行 并接管模块中的其余方法:

...
class API < Sinatra::Base
  register Sinatra::DefaultRoutes
  set :port, 22340
  get "/version" do
    Monteverde::Activity.version
  end
  run!
end

$ ruby monteverde.rb aversion
$ == Sinatra (v2.0.0) has taken the stage on 22340 for development with backup from Puma
$ ...

我的问题是无法识别 OPERATION 常量,即使它是在调用模块之前设置的。

为什么 OPERATION 没有被识别,我怎样才能让它被识别? 还有其他 intuitive/useful 方法可以让 Sinatra 在我调用模块时不触发吗?

在您的 API class 定义中,只要您需要该文件,就会出现 run! 行。如果您引用 class,它不会再次 运行,因为您正在尝试使用 def api 方法的最后一行。

为了解决这个问题,您可以将 run! 命令移动到一个方法中,然后从 Thor 中调用它:

class API < Sinatra::Base
  # ... other stuff
  def self.start
    run! if defined? Monteverde::OPERATION
  end
end

然后在 Thor 文件中:

 def api
   Monteverde.const_set("OPERATION", "started")
   Monteverde::Activity::API.start
 end

你可以推断出 run! 是一个 class 方法,因为它在 class 定义 的范围内是可调用的(不是在实例方法),所以我定义了一个 class 方法来调用它。

不过,不定义 def self.start 而是直接从 Thor 文件中调用 run! 方法会更简单:

def api
  Monteverde::Activity::API.run!
end