1

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对话!并且还提到了request_store!gem 可能是一种更清洁的方式。

4

3 回答 3

1

这个 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
于 2013-10-18T00:29:22.500 回答
1

起初,我采用了 Jonathan Bender 的一种使用建议的形式Rails.cache(感谢 John),但对我不得不将其过期的方式不太满意。由于缺乏更好的主意,我认为Thread毕竟使用它可能会更好。我最终安装了request_store gem 来存储查询结果。这样可以在我想要的持续时间(请求/响应的生命周期)内保留数据,并且不再需要过期。

于 2013-10-18T21:42:48.287 回答
0

你真的确定这个优化是必要的吗?您是否因此而遇到性能问题?除非它实际上是一个问题,否则我不会担心它。

那就是说;您可以创建一个新类,在该类special_item_id_list上创建一个实例方法,然后将该类传递给任何需要使用该昂贵计算数据的东西。

或者将数据缓存在 的实例上Item(可能通过创建special_item_id_list实例方法)就足够了,而不必担心不同的实例无法共享缓存。

于 2013-10-18T00:29:44.663 回答