You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails.cache.fetch缓存JSON数组失效,@my_api_data_报NilClass错误

问题分析与解决方案

你的问题核心在于缓存命中时,Rails.cache.fetch的代码块不会执行,导致实例变量@my_api_data_从未被赋值,最终视图调用each时触发nil类错误。

修复后的代码

def index
  api_statuses_
end

def api_statuses_
  # 把缓存的结果直接赋值给实例变量
  @my_api_data_ = Rails.cache.fetch('api_response_m_', expires_in: 3.minutes) do
    mypairs = ['ticker1','ticker2', 'ticker3', 'ticker4', 'ticker5', 'ticker6', 'ticker7', 'ticker8', 'ticker9', 'ticker10']
    my_api_data = []
    base_url = 'https://myserver.com/ticker/'

    mypairs.each do |item|
      uri = URI(base_url + item)
      response = Net::HTTP.get(uri)
      begin
        myresult = JSON.parse(response)
      rescue JSON::ParserError
        # 解析失败时给默认值,避免推入nil污染数组
        myresult = { error: 'Failed to parse response' }
      end
      my_api_data.push(myresult)
    end

    # 块最后必须返回要缓存的数据,这里是我们组装好的数组
    my_api_data
  end
end

为什么原来的代码会失效?

  1. 缓存逻辑的本质:Rails.cache.fetch的工作机制是:如果缓存键存在,则直接返回缓存值,不会执行代码块;只有缓存键不存在时,才会执行块内代码,并把块的返回值存入缓存。
  2. 实例变量的作用域问题:你原来的代码是在块内给@my_api_data_赋值,但当缓存命中时,块根本不会运行,@my_api_data_始终是nil,视图自然无法调用each方法。
  3. 缓存内容的误区:你之前尝试在块末尾返回@my_api_data_,但没有把fetch的返回值赋值给实例变量,所以缓存的数据根本没有传递到视图中。

额外优化建议

  • 修正缓存键拼写:把api_repsonse_m_改成api_response_m_(少写了一个s),避免后续维护时混淆。
  • 用局部变量替代块内实例变量:块内使用局部变量(比如my_api_data)比实例变量更安全,不会意外污染控制器的其他实例变量。
  • 完善错误处理:JSON解析失败时,不要空着rescue块,至少给个默认值,避免数组中混入nil导致后续视图逻辑出错。
  • 考虑更优雅的HTTP客户端:Net::HTTP比较繁琐,可以尝试Faraday或HTTParty,简化API请求和错误处理。

内容的提问来源于stack exchange,提问作者Vitali Grabovski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:08:35