如何让Ruby Rails的attr_encrypted属性直接返回Money对象?
解决attr_encrypted加密属性直接返回Money对象的问题
我之前也遇到过一模一样的需求,其实最直接有效的方案就是重写attr_encrypted自动生成的getter方法,既不用额外加辅助方法,还能轻松拿到当前用户的currency字段。
具体实现代码
class User < ApplicationRecord attr_encrypted :balance, key: 'some super secret key' # 重写balance getter,直接返回Money对象 def balance # 调用attr_encrypted生成的原始getter,获取解密后的数值 raw_decrypted_balance = super # 结合当前用户的currency生成Money对象,同时处理nil场景 raw_decrypted_balance.present? ? Money.new(raw_decrypted_balance, currency) : nil end end
为什么这个方案能解决问题?
- attr_encrypted在定义
attr_encrypted :balance后,会自动生成一个balance方法,负责解密并返回原始数值。我们通过super调用这个原始方法,就能拿到解密后的余额。 - 重写的
balance是实例方法,能直接访问当前User实例的currency属性,完美解决了你之前用marshaler时无法获取用户币种的痛点。
为什么之前的Marshaler方案行不通?
你尝试的自定义Marshaler是全局模块,它的load方法无法访问到具体的User实例,自然拿不到该用户的currency字段,这个思路从根源上就没法满足需求。
可选优化
如果希望nil值也返回一个有效的Money对象,可以调整代码:
def balance raw_decrypted_balance = super || 0 Money.new(raw_decrypted_balance, currency) end
这样不管balance是否为空,都会返回一个合法的Money对象,避免后续逻辑出现空指针问题。
内容的提问来源于stack exchange,提问作者Jakub Kopyś
相关产品推荐
相关产品推荐

