gpt4 book ai didi

模块中的 Ruby 类需要访问包含类命名空间

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

我已经用 Ruby 编写了一个小应用程序,现在想向它添加一个简单的 API,以允许其他应用程序对其运行一些基本查询。

我一直在看 senatra,因为它看起来非常轻巧和简单。但我怀疑与其将 sinatra 添加到我的应用程序以提供 API,我可能应该将应用程序编写为 sinatra 应用程序。

我目前的问题是我可以通过简单的“Hello!”来建立一个“瘦”服务器。端点,通过在我添加到我的应用程序对象的模块中定义它,如下所示:

module ApMessageIoModule

require 'sinatra/base'
require 'thin'

def start_server
Thread::abort_on_exception
Thread.new do
ApiServer.run!
end
end

class ApiServer < Sinatra::Base

configure do
server.threaded = settings.threaded if server.respond_to? :threaded=
end

get "/" do
"Hello!"
end

end
end

通过调用 start_server() 方法,我可以将服务器作为后台线程启动。但是现在我有了端点,我希望它引用我添加了模块的类中的方法。

那么如何访问封闭类的命名空间呢?

例如

我添加了模块的类称为 StateMachine,它有一个方法:
  # Query the state table for a particular state
def query_status(flag)
execute_sql_query(
"select status from state where state_flag = '#{flag}';"
)[0][0]
end

如何从上面的“get”路由中调用此方法?

我发现了另一篇似乎与此有关的帖子-

Accessing a class's containing namespace from within a module

但这有点超出我的想象,我在尝试调整给出的代码示例时没有运气。

为了尝试澄清这一点,我有一个类(class),这里显示为精简版:
class StateMachine

# Query the state table for a particular state
def query_status(flag)
execute_sql_query(
"select status from state where state_flag = '#{flag}';"
)[0][0]
end

end

该类包括上面显示的模块 ApMessageIoModule。

StateMachine 类已被实例化,在我的单元测试中:
  # Confirm that SM can load one of our modules
def test_it_loads_user_modules
sm = StateMachine.new
sm.include_module('ApMessageIoModule')
sm.start_server
sleep(600)
sm.stop_server
assert_equal(sm.test_method, 'Test String')
end

我目前在那里睡了很长时间,以允许我通过转到浏览器中的端点来手动确认服务器已启动。这样做会向我显示端点上预期的 Hello 消息。

查询状态方法与底层 sqlite3 db 对话,该数据库已由 StateMachine 的初始化方法调用的各种方法创建和填充。为简洁起见,此处未显示。

所以我想要做的是从 ApMessageIoModule 模块中的 ApiServer 类中的 StateMachine 实例中调用该方法,如果这有意义的话。

其实我觉得这个便笺簿更清楚:
require 'sinatra/base'
require 'thin'

module MyInclude
class SinatraServer < Sinatra::Base
get '/' do
test_method # This call fails with message shown below
end
get '/exit' do
exit!(0)
end
end

def startup
Thread.new do
SinatraServer.run!
end
end
end

class TopLevel
include MyInclude

def test_method
puts "TEST"
end

end

tl = TopLevel.new
tl.startup
sleep(600)


# Error message reads:
# NameError at /
# undefined local variable or method `test_method' for
# #<MyInclude::SinatraServer:0x00007fd002ac41d8>
# file: sinatra_server.rb location: block in <class:SinatraServer> line: 7

最佳答案

您的 query_status是一个不依赖任何东西的纯函数。将其放入完全分离的模块中,使其成为模块函数,并从各处调用为模块函数:

module Helpers
def query_status(flag)
...
end
module_function :query_status
end

现在在您的 get :
get "/" do
"Hello, " + Helpers.query_status('yes')
end

回答问题所述:由于该函数不干扰任何数据(是纯函数),使其成为 ApiServer的类级函数并直呼其名:
class ApiServer < Sinatra::Base
def self.query_status(flag)
flag.to_s
end

get "/" do
"Hello, " + query_status('yes')
end
end

关于模块中的 Ruby 类需要访问包含类命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48230192/

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