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
相关产品推荐
相关产品推荐

