Rails多行方法Memoize实现求助:首次接触该特性遇适用场景
在Rails中实现记忆化优化你的网络请求方法
嘿,刚好你的场景完美适配记忆化!每次调用manager_rep_code_and_name都发起一堆网络请求,确实会拖慢速度,用记忆化就能避免重复请求,直接复用之前的结果。我给你几种实用的实现方式:
方式一:记忆整个方法的返回值(最简单)
如果rep_code_list在实例生命周期内不会变化,直接用实例变量加||=就能搞定:
def manager_rep_code_and_name @manager ||= begin rep_code_list.map do |rep_code| context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code) { name: context.manager.response.first["Name"], rep_code: rep_code } end end end
我把你的push改成了map,代码更简洁~第一次调用方法时,会执行begin...end里的逻辑并把结果存到@manager里,之后再调用就直接返回缓存的结果,不会再发网络请求了。
方式二:按单个rep_code缓存(更灵活)
如果rep_code_list可能动态变化,或者同一个rep_code会多次出现在列表里,用哈希来缓存每个rep_code的结果更合适:
def manager_rep_code_and_name @manager_cache ||= {} rep_code_list.map do |rep_code| @manager_cache[rep_code] ||= begin context = Finfolio::GetManagerByRepCode.call(rep_code: rep_code) { name: context.manager.response.first["Name"], rep_code: rep_code } end end end
这样每个rep_code只会发起一次网络请求,哪怕后续调用方法时列表里包含之前的rep_code,也直接用缓存好的数据,效率更高。
额外注意事项
- 实例变量的缓存是绑定到实例的,每个实例的缓存独立,类方法的话可以用类变量或者
@@,不过一般不推荐类变量,容易有线程安全问题。 - 如果需要刷新缓存,比如manager的名字更新了,直接手动重置缓存即可:
@manager = nil(对应方式一)或者@manager_cache.delete(rep_code)(对应方式二)。 - 如果需要跨请求的缓存,那就要用Redis之类的外部缓存了,但如果只是优化单次请求内的重复调用,上面的实例变量方式完全够用。
内容的提问来源于stack exchange,提问作者Bitwise
相关产品推荐
相关产品推荐

