Rails全局变量-来自API的每个请求更新

时间:2019-08-31 12:21:26

标签: ruby-on-rails ruby global-variables grape

我已经使用GRAPE gem创建API端点。

对于简单的用例,让我们考虑一下,当点击我的Web服务时,我点击了另一个第三方REST API,并且获取了一些值并将这些值分配给一个或两个变量。例如variable1,variable2

这些值经常从第三方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

一样访问它

任何人都可以提出更好的前进方向吗?

2 个答案:

答案 0 :(得分:1)

理想情况下,您将在启动期间的某个时间创建一个用于保存这些参数的对象,然后通过某种形式的依赖注入将单个实例注入到需要它们的每个类中,但是由于我不知道任何常用的依赖注入方案对于铁轨,我建议这两种选择。

有些人不喜欢单例,但是您可以将它们存储在单例类中。

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

答案 1 :(得分:1)

全局变量是恕我直言的坏主意。这或多或少与单例相同。 您将如何更新变量,谁来做?什么时候?您如何检查是否过期?如果您有多个红宝石过程并且它们使用不同的值怎么办?

这听起来像是缓存和从缓存读取的服务的好用例。

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,数据库,Memcached。