我对Ruby不熟悉,但我在Ruby中使用Grape API进行了以下编码。我每次点击@data = YAML.load()
时都会调出GET /api/v1/foo
,Grape中有没有办法只加载一次并使用它?这种方式更加优化,并且不会每次都调用YAML.load()
。我应该覆盖initialize
方法并为此操作添加super()
吗?
谢谢,
require 'grape'
require 'json'
require "yaml"
module MyProject
CONFIG_FILE = "./config.yml"
class Api < Grape::API
rescue_from :all
prefix 'api'
version 'v1'
format :json
resources :foo do
get do
@data = YAML.load(File.open(MyProject::CONFIG_FILE))
end
end
end
end
答案 0 :(得分:3)
简短的回答是Grape
不能完全按照您的想法运作,MyProject::Api
的属性变量不是您的新网络服务的前进方式。然而,这是一个有趣的问题,值得探讨为何如此。
如果您在puts self.inspect
块中添加resources :foo
并使用rackup
运行,则在调用该路线时,您应该会看到self
实际上是Grape::Endpoint
1}}对象。此外,无论您尝试使用实例变量,它们始终会针对每个请求以相同的状态启动。这是因为Grape
将您的路径定义转换为准备好的Grape::Endpoint
对象,其中许多定义数据和设置被放入一个可快速访问的形式(因此在每个请求中都没有计算出来)。最终,在每个请求中,匹配的Grape::Endpoint
对象(包括您的块(以及您为路由定义的其他详细信息)在被调用之前都是重复的,这意味着请求之间不会维护状态。 / p>
这可能看起来很复杂,但大多数涉及Web服务请求的框架都会做类似的事情。通常,您不希望请求处理状态在请求之间保持不变。具有更大范围的框架 - 例如Rails - 可以为您计划更多持久性数据。葡萄没有这个定义,这有其优点和缺点。一个明显的优点是,您可以更自由地使用您希望的任何其他数据持久性方法。
23tux的答案会立即为你加载配置。虽然我不完全确定端点块如何可以访问@@data
(它甚至可能在变量周围创建一个闭包)。
从长远来看,您应该考虑将配置管理移出MyProject::Api
课程,并通过Grape的helpers
方法将其作为模块包含在内(如果您有兴趣,我很乐意提供一个示例)。
编辑:基于您当前代码的示例,但将配置管理移至单独的模块:
require 'grape'
require 'json'
require "yaml"
module MyProject
module Config
CONFIG_FILE = "./config.yml"
@@data = nil
def config
@@data ||= YAML.load( File.open( CONFIG_FILE ) )
end
end
class Api < Grape::API
rescue_from :all
prefix 'api'
version 'v1'
format :json
helpers MyProject::Config
resources :foo do
get do
config
end
end
end
end
这在结构上比23tux的答案更进一步,但仍然没有完全将存储(和缓存等)与api访问的关注分开。随着您向更复杂的Web服务发展,您将希望保持Grape路由定义简单,只需要少量逻辑来管理或操作数据 - 至少可以直接在块中看到。
通过Grape的helpers
方法,可以在Grape定义与可能管理配置,日志记录,身份验证和其他服务的其他gem之间建立链接的一种方法。 Grape还有一些用于常见任务的内置辅助方法。
使用helpers MyModule
向Grape添加共享功能的主要例外是当您想要管理来自核心应用程序的显示数据对象(也称为“模型”)时。为此你有一些选择,但grape-entity
gem和present
方法并不是一个糟糕的起点。
答案 1 :(得分:1)
如果@data
对于整个api是相同的,并且不会随时更改,只需使用类变量
require 'grape'
require 'json'
require "yaml"
module MyProject
CONFIG_FILE = "./config.yml"
class Api < Grape::API
@@data = YAML.load(File.open(MyProject::CONFIG_FILE))
rescue_from :all
prefix 'api'
version 'v1'
format :json
resources :foo do
get do
puts @@data
end
end
end
end
未经过测试,但通过这种方式,您确保在加载Api
类时仅加载一次数据