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

Rails重写Noticed Gem的FCM投递方法遇device_tokens未定义错误

问题描述

在Rails应用中使用noticed Gem v1.6.3版本,通过lib/noticed/delivery_methods/fcm.rb重写FCM投递方法,期望响应返回非404错误码时记录日志并继续遍历设备令牌。编写的代码如下:

class Noticed::DeliveryMethods::Fcm < Noticed::DeliveryMethods::Base
  def deliver
    puts"****************************Overrdie is called*****************"
    device_tokens.each do |device_token|
      post("#{BASE_URI}#{project_id}/messages:send", headers: {authorization: "Bearer #{access_token}"}, json: {message: format(device_token)})
    rescue ResponseUnsuccessful => exception
      if exception.response.code == 404
        cleanup_invalid_token(device_token)
      else
        Rails.logger.error("FCM request failed with code #{exception.response.code}: #{exception.message}")
      end
    end
  end
end

运行时出现错误:

NameError (undefined local variable or method `device_tokens'`

尽管device_tokens方法在原FCM类中已定义。

解决方案

问题出在类的继承关系上:你当前继承的是Noticed::DeliveryMethods::Base,但原FCM投递方法类是Noticed::DeliveryMethods::Fcm,正确做法是直接打开原类进行重写,而非继承Base类。修改代码如下:

# lib/noticed/delivery_methods/fcm.rb
module Noticed
  module DeliveryMethods
    class Fcm
      def deliver
        puts"****************************Override is called*****************"
        device_tokens.each do |device_token|
          post("#{BASE_URI}#{project_id}/messages:send", headers: {authorization: "Bearer #{access_token}"}, json: {message: format(device_token)})
        rescue ResponseUnsuccessful => exception
          if exception.response.code == 404
            cleanup_invalid_token(device_token)
          else
            Rails.logger.error("FCM request failed with code #{exception.response.code}: #{exception.message}")
          end
        end
      end
    end
  end
end

如果不想完全覆盖原方法,也可以用prepend模块的方式(更安全):

# lib/noticed/delivery_methods/fcm_override.rb
module Noticed::DeliveryMethods::FcmOverride
  def deliver
    puts"****************************Override is called*****************"
    device_tokens.each do |device_token|
      post("#{BASE_URI}#{project_id}/messages:send", headers: {authorization: "Bearer #{access_token}"}, json: {message: format(device_token)})
    rescue ResponseUnsuccessful => exception
      if exception.response.code == 404
        cleanup_invalid_token(device_token)
      else
        Rails.logger.error("FCM request failed with code #{exception.response.code}: #{exception.message}")
      end
    end
  end
end

# 在初始化文件中加载并应用
# config/initializers/noticed.rb
Noticed::DeliveryMethods::Fcm.prepend(Noticed::DeliveryMethods::FcmOverride)
原因说明

device_tokens方法原本定义在Noticed::DeliveryMethods::Fcm类中,当你新建一个继承自Base的同名类时,相当于重新定义了该类,原类的方法无法被继承。直接打开原类修改或使用prepend模块,才能访问到原类中定义的device_tokens等方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 18:29:57