【问题标题】:How do I force Rails to use my cache instead of always going to the database?如何强制 Rails 使用我的缓存而不是总是访问数据库?
【发布时间】:2017-05-18 23:28:20
【问题描述】:

我正在使用 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

我希望“distance = Distance.new({:distance => my_obj.distance, :distance_unit => my_obj.distance_unit})”行调用我的缓存功能,而不是跑到数据库中。我怎样才能做到这一点?

【问题讨论】:

  • 你用什么来存储缓存?
  • 哦,好问题。我的配置文件中有“config.cache_store = :memory_store”。

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


【解决方案1】:

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

作为一般说明:belongs_to 关联会固有地触发查找如果尚未获取对象。 Rails 框架中内置了很多缓存,一般来说,我不会太担心一开始的过早优化(只有当你发现查询运行太慢时才进行优化)。

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

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

您可以在MyObject 中创建以下方法,覆盖belongs_to 关联创建的“getter”:

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})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多