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

为何order_items_info.pluck(:quantity_shipped).sum.abs会触发nil异常?

问题分析:sum方法触发inject(:+)的nil错误

原代码

order_items_info.pluck(:quantity_shipped).sum.abs

错误日志

Error reindexing order 123456 - NoMethodError - undefined method `+' for nil:NilClass

inject(:+) || 0
  ^^^^^^

已测试场景

Loading production environment (Rails 6.1.7)
irb(main):001:0> order_items_info = nil
=> nil
irb(main):002:0> order_items_info.pluck(:quantity_shipped).sum.abs
(irb):2:in `<main>': undefined method `pluck' for nil:NilClass (NoMethodError)
irb(main):003:0> order_items_info = []
=> []
irb(main):004:0> order_items_info.pluck(:quantity_shipped).sum.abs
=> 0
irb(main):005:0> order_items_info = [{quantity_shipped: nil}]
=> [{:quantity_shipped=>nil}]
irb(main):006:0> order_items_info.pluck(:quantity_shipped).sum.abs
=> 0
irb(main):007:0> order_items_info = [nil]
=> [nil]
irb(main):008:0> order_items_info.pluck(:quantity_shipped).sum.abs
/home/deploy/zonmaster/shared/vendor/bundle/ruby/3.1.0/gems/activesupport-6.1.7/lib/active_support/core_ext/enumerable.rb:157:in `block in pluck': undefined method `[]' for nil:NilClass (NoMethodError)

      map { |element| element[key] }
                             ^^^^^
irb(main):009:0> order_items_info = [{quantity_shipped: 'abd'}]
=> [{:quantity_shipped=>"abd"}]
irb(main):010:0> order_items_info.pluck(:quantity_shipped).sum.abs
(irb):10:in `<main>': undefined method `abs' for "abd":String (NoMethodError)

错误原因

这个错误的核心是数组中同时存在nil和数值类型,且nil是数组的第一个元素。

Rails的sum方法逻辑:

  • 若数组为空,直接返回0;
  • 若数组非空,调用inject(:+)逐个累加元素;
  • 末尾的|| 0是兜底逻辑,但如果inject(:+)在执行过程中就报错(比如第一个元素是nil,第二个是数值,执行nil + 数值),|| 0根本不会生效。

你之前的测试场景没有覆盖[nil, 数值]这种混合数组,比如当order_items_info = [{quantity_shipped: nil}, {quantity_shipped: 10}]时,pluck得到[nil,10],执行sum就会触发nil +10的错误,和日志中的报错完全一致。

另外还有极小概率是并发修改导致:在pluck获取数组后、sum执行前,数组元素被异步修改为nil开头的混合数组,但这种情况需要结合业务场景进一步排查。

修复方案

  • 过滤nil值:先去掉数组中的nil再求和
    order_items_info.pluck(:quantity_shipped).compact.sum.abs
    
  • 指定初始值:利用Rails sum方法的参数设置初始值,避免nil参与累加
    order_items_info.pluck(:quantity_shipped).sum(0).abs
    
  • 直接求和转换:跳过pluck,直接遍历处理每个元素的nil值
    order_items_info.sum { |item| item[:quantity_shipped].to_i }.abs
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 02:55:19