我已经用 Ruby 编写了一个小应用程序,现在想向它添加一个简单的 API,以允许其他应用程序对其运行一些基本查询。
我一直在看 senatra,因为它看起来非常轻量级和简单。但我怀疑与其将 sinatra 添加到我的应用程序以提供 API,不如将应用程序编写为 sinatra 应用程序。
我现在的问题是我可以用一个简单的“你好!”来建立一个“瘦”服务器。端点,通过在我添加到我的应用程序对象的模块中定义它,如下所示:
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”路由中调用此方法?
我发现了另一个似乎与此有关的帖子 -
但这有点超出我的想象,我没有运气尝试调整给出的代码示例。
为了尝试澄清这一点,我有一个类,这里显示的是精简:
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 数据库对话,该数据库已通过从 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