special_item_id_list
方法负责返回一组id。查询和逻辑足够复杂,我只想在每个页面请求中运行一次,但我会在许多不同的地方使用生成的id数组。我们的想法是能够自由地使用is_special?
方法或special_items
范围,而不必担心每次使用时都会产生开销,因此他们依靠special_item_id_list
方法来做重提升和缓存。
我不希望此查询的结果在页面加载之间保持不变,但我希望每次加载时查询只运行一次。我不想使用全局变量,并认为模型上的类变量可能有效,但看起来类变量在页面加载之间保持不变。我猜测Item
类是Rails堆栈的一部分并保留在内存中。
那么在哪里存储我的id列表的首选位置,以便在每次加载页面时重建它?
class Item < ActiveRecord::Base
scope :special_items, lambda { where(:id => special_item_id_list) }
def self.special_item_id_list
@special_item_id_list ||= ... # some complicated queries
end
def is_special?
self.class.special_item_id_list.include?(id)
end
end
更新:使用Thread
怎么样?我之前已经完成了跟踪当前用户的操作,我认为它可以在这里应用,但我想知道是否还有另一种方法?这是StackOverflow conversation discussing threads!并且还提到了request_store!宝石可能是一种更清洁的方式。
答案 0 :(得分:1)
This railscast涵盖了您正在寻找的内容。简而言之,你会想要做这样的事情:
after_commit :flush_cache
def self.cached_special_item_list
Rails.cache.fetch("special_items") do
special_item_id_list
end
end
private
def flush_cache
Rails.cache.delete("special_items")
end
答案 1 :(得分:1)
起初,我采用了Jonathan Bender关于利用Rails.cache
(感谢John)的建议,但对我如何使其过期感到不满意。由于缺乏更好的想法,我认为最好使用Thread
。我最终安装了request_store gem来存储查询结果。这样可以保持数据的持续时间(请求/响应的生命周期),不再需要过期。
答案 2 :(得分:0)
你真的确定这种优化是必要的吗?您是否因此而遇到性能问题?除非它实际上是一个问题,否则我不会担心它。
那说;您可以创建一个新类,在该类上创建special_item_id_list
实例方法,然后将该类传递给需要使用这些昂贵的计算数据的任何内容。
或者将数据缓存在Item
的实例上可能就足够了(可能通过使special_item_id_list
成为实例方法),而不必担心不能共享缓存的不同实例。