我使用 GRAPE gem 来创建 API 端点。
对于简单的用例,让我们考虑一下,当我的 Web 服务被访问时,我访问另一个第三方 REST API,我获取一些值并将这些值分配给一个或两个变量。例如变量1,变量2
这些值经常从第三方 API 更改,因此我也必须不断更新变量值,在 API 代码中使用它或将其作为参数传递给方法时一切都很好。
但是我有几个控制器应该采用更新的变量/要采用的更新值。
目前我所做的是:
class Api < Grape::API
version 'v1'
format :json
helpers MyProject::Config
resources :foo do
get do
variable1 = #hit third party URL
$global_variable1 = variable1
end
end
end
在控制器中:
class SampleController < ApplicationController
def method()
some_calc = $global_variable1 + other_variable
end
end
现在效果很好,除了全局变量之外还有什么更好的使用方法吗? 或者我们可以这样做:
Rails.application.config.variable1 = variable1
哪一个是更好的前进方向?
我尝试在 API 类中像这样设置 @instance 变量,但是在控制器方法中访问它时会给出空字符串。
@variable1 = ""
def self.variable1
@variable1
end
并像 ClassName.variable1 一样访问它
任何人都可以提出更好的前进方向吗?
恕我直言,全局变量是一个坏主意。这或多或少与单例相同。 您将如何更新变量以及谁将执行此操作?什么时候?如何检查是否过期?如果您有多个 ruby 进程并且它们使用不同的值怎么办?
这听起来像是缓存和从缓存读取的服务的一个很好的用例。
class ParameterService
def get(parameter_name)
if parameter is not in cache or expired
read from external service and store in cache
end
return value from cache
end
end
缓存可以是 Redis、DB、Memcached 之类的东西。
有些人不喜欢单例,但你可以将它们存储在单例类中。
require 'singleton'
class APIParams
include Singleton
attr_accessor :v1, :v2
end
APIParams.instance.v1 = 3
puts APIParams.instance.v1
这可能有点矫枉过正,但您也可以为它们创建一个模型并将它们存储在数据库中。 如果您有多个资源需要存储同一组变量(例如
api_key
和/或标记),这可能会很有用。
class APIResource < ActiveRecord::Base
# you probably would want some `belongs_to`, has_a relationships here to associate these with the models used in your controllers.
end
由包含如下字段的表格支持
create_table "api_resources", force: :cascade do |t|
t.string "name",
t.string "api_key",
t.string "token"
end