如何强制Rails使用我的缓存而不是总是去数据库?

时间:2017-05-18 23:28:20

标签: caching model ruby-on-rails-5 finder in-memory

我使用Rails 5.我有这个模型

class MyObject < ActiveRecord::Base
    ...
  belongs_to :distance_unit

当我有一条如下所示的行时,我会注意到

distance = Distance.new({:distance => my_obj.distance, :distance_unit => my_obj.distance_unit})

它会导致执行以下操作

SELECT  "distance_units".* FROM "distance_units" WHERE "distance_units"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]

没什么不寻常的,但我在我的DistanceUnit模型中创建了一个缓存方法

class DistanceUnit < ActiveRecord::Base

  def self.cached_find_by_id(id)
    Rails.cache.fetch("distanceunit-#{id}") do
      puts "looking for id: #{id}"
      find_by_id(id)
    end
  end

我希望&#34; distance = Distance.new({:distance =&gt; my_obj.distance,:distance_unit =&gt; my_obj.distance_unit})&#34;用于调用我的缓存功能而不是运行到数据库的行。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:0)

关于我的评论,请注意memory_store仅在进程中使用,因此每个进程都有自己的存储(如果这是一个问题,请考虑MemCacheStore)。当进程结束时,缓存也消失了。

作为一般说明:如果尚未提取对象,则belongs_to关联本身会触发查找 。 Rails框架中内置了大量缓存,一般来说,我不会过早担心过早优化(只有在发现查询运行速度太慢时才会优化)。

另外:访问缓存也是对一种数据库的调用,基于可能索引的id的查找通常不是一个沉重的调用。如果只有几个距离单位,你可能只是使用一个常量可以工作吗?

但要回答你的问题。您的代码中似乎没有任何内容表示cached_find_by_id(虽然rails自动执行了很多操作,但这不是其中之一)。

您可以在MyObject中创建以下方法,以覆盖“getter”&#39;由belongs_to关联创建:

def distance_unit
  DistanceUnit.cached_find_by_id(distance_unit_id)
end

但是,如果你只是简单地初始化一个ActiveRecord对象并且你不需要在这个调用中使用DistanceUnit,你也可以直接传递id,因为这是存储的内容在数据库中。

Distance.new({:distance => my_obj.distance, :distance_unit_id => my_obj.distance_unit_id})