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
我正在开发一个包含标准方法以及 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