ruby-on-rails – 如何在rails中缓存计算列?

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 如何在rails中缓存计算列?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一棵活动记录对象的树,像:
  1. class Part < ActiveRecord::Base
  2. has_many :sub_parts,:class_name => "Part"
  3.  
  4. def complicated_calculation
  5. if sub_parts.size > 0
  6. return self.sub_parts.inject(0){ |sum,current| sum + current.complicated_calculation }
  7. else
  8. sleep(1)
  9. return rand(10000)
  10. end
  11. end
  12.  
  13. end

每次重新计算complex_calculation成本太高.所以,我需要一种缓存值的方法.然而,如果任何部分被更改,它需要使其缓存和其父代和祖父母等的缓存无效.

作为一个粗略的草稿,我创建了一个列,以将缓存的计算保存在“parts”表中,但是这味道有点烂.似乎应该有一个更清洁的方法来缓存计算值,而不是将它们填充在“真实”列的旁边.

解决方法

>您可以在Rails缓存中填充实际缓存的值(如果需要分发,请使用memcached).
>难点是缓存到期,但缓存到期不常见,对吧?在这种情况下,我们可以依次循环遍历每个父对象,并对其缓存进行zap.我添加了一些ActiveRecord魔法到你的类,使得父对象的简单性本身 – 而你甚至不需要触摸你的数据库.记得在您的代码中适当调用Part.sweep_complicated_cache(some_part) – 您可以将其放在回调等中,但是我无法为您添加它,因为当complex_calculation发生变化时,我不明白.
  1. class Part < ActiveRecord::Base
  2. has_many :sub_parts,:class_name => "Part"
  3. belongs_to :parent_part,:class_name => "Part",:foreign_key => :part_id
  4.  
  5. @@MAX_PART_NESTING = 25 #pick any sanity-saving value
  6.  
  7. def complicated_calculation (...)
  8. if cache.contains? [id,:complicated_calculation]
  9. cache[ [id,:complicated_calculation] ]
  10. else
  11. cache[ [id,:complicated_calculation] ] = complicated_calculation_helper (...)
  12. end
  13. end
  14.  
  15. def complicated_calculation_helper
  16. #your implementation goes here
  17. end
  18.  
  19. def Part.sweep_complicated_cache(start_part)
  20. level = 1 # keep track to prevent infinite loop in event there is a cycle in parts
  21. current_part = self
  22.  
  23. cache[ [current_part.id,:complicated_calculation] ].delete
  24. while ( (level <= 1 < @@MAX_PART_NESTING) && (current_part.parent_part)) {
  25. current_part = current_part.parent_part)
  26. cache[ [current_part.id,:complicated_calculation] ].delete
  27. end
  28. end
  29. end

猜你在找的Ruby相关文章