如何在Ruby中覆盖ActiveMerchant CreditCard的requires_name类变量
正确覆盖 ActiveMerchant CreditCard 姓名校验的方法
针对澳大利亚支付场景不需要收集持卡人姓名的需求,你之前尝试的方法没生效,大概率是因为 requires_name 方法里的 ||= 逻辑导致类变量初始化后就不会再被覆盖。下面是两种可靠的解决方案:
方案一:直接重新定义类方法(最稳妥)
最可靠的方式是直接覆盖 requires_name 类方法,让它返回一个始终为 false 的 Proc,彻底跳过姓名非空校验:
ActiveMerchant::Billing::CreditCard.class_eval do def self.requires_name Proc.new { false } end end
这种方式不受原类变量初始化时机的影响,不管之前有没有代码调用过 requires_name,调用 self.class.requires_name.call 都会得到 false,直接绕过第328行的校验逻辑。
方案二:覆盖类变量(需注意加载时机)
如果你更倾向于修改类变量,需要确保在 requires_name 方法第一次被调用之前设置——因为原方法里的 @@requires_name ||= Proc.new { true } 会在首次调用时初始化变量,之后再修改就需要直接覆盖已有的值:
# 直接覆盖已初始化的类变量 ActiveMerchant::Billing::CreditCard.class_variable_set(:@@requires_name, Proc.new { false })
但这种方式有隐患:如果在你设置之前,已经有其他代码调用过 requires_name,类变量已经被初始化为默认的Proc.new { true },这时候再设置才会生效。所以方案一更推荐,不受加载顺序限制。
验证修改效果
修改完成后,你可以用这段代码测试:
card = ActiveMerchant::Billing::CreditCard.new( number: '4111111111111111', month: '12', year: (Time.now.year + 1).to_s, name: nil # 传入nil也不会触发校验错误 ) puts card.valid? # 应返回true,不会因name为空报错
内容的提问来源于stack exchange,提问作者Richtopia
相关产品推荐
相关产品推荐

