我应该如何为Rails应用程序存储一个值,该值会定期更改但需要所有用户访问?

时间:2019-04-18 14:25:01

标签: ruby-on-rails global-variables

我在Rails中构建了一个仅API的应用程序,该应用程序需要加密的登录名才能接收令牌。随后,使用请求标题中的令牌值对来自API的数据请求进行身份验证。

我还有另一个Rails应用程序,该应用程序将此API用于一些其他事情。目前,我已将其设置为在发出任何请求之前进行身份验证,该请求将获得该请求的令牌。

这很好,除了一旦公众可以使用该应用程序就可以设置潜在的比赛条件。可能实际上有两个请求可能同时出现,两次重置令牌,使随后的一个数据请求成为一个不再有效的令牌。

我想使用$ global变量存储令牌和刷新令牌的日期/时间,以便始终对所有用户可用,并且仅在令牌使用了几个小时以上时才刷新令牌。

这可以解决比赛条件问题,但是从我读到的所有内容来看,在铁路中使用全球变量都是很糟糕的。在我看来,这种用例是个例外,但我想以正确的方式来做。

将这些值存储在我自己的数据库中是我唯一的选择吗?为只包含两列和两行的表建立数据模型似乎很愚蠢,但是我不知道这是Rails Way(TM)还是Best Way。

任何建议都值得赞赏。

1 个答案:

答案 0 :(得分:3)

您可以使用Rails' cache来做到这一点。它被存储在内存或易失性数据库(例如Redis)中。您可能会有类似的内容:

def a_cool_token
  Rails.cache.fetch("a_cool_token", expires_in: 2.hours.to_i) do
    a_method_to_regenerate_a_cool_token
  end
end

会发生什么:

  1. 使用a_cool_token将其传递给请求时,它将尝试从缓存中获取它;
  2. 如果缓存键过期或未定义,则返回a_method_to_regenerate_a_cool_token;
  3. expires_in上设置的时间过去后,密钥无效。

您总是可以使用更多的全状态缓存键,通过一些数据库查询来构建它,例如:

Rails.cache.fetch("a_cool_token/#{some_timestamp_that_gets_updated_with_a_cool_token}", expires_in: 2.hours.to_i)

实施def some_timestamp_that_gets_updated_with_a_cool_token可以检索上次更新令牌的时间,如果其他原因更改了a_cool_token之外的令牌,可以避免过时的响应

我希望这有助于您找到一个“好的”解决方案。