Rails4 : Model caching (low level caching)

别来无恙 提交于 2019-12-08 04:02:05

问题


I am trying to cache results of Active Record Query.

Here is my use case:

User.rb
  def self.awesome_users_cached
    Rails.cache.fetch("awesome_users") { where(awesome: true) }
  end

UsersController
  def index
    all_awesome_users  = User.awesome_users_cached
    less_awesome_users = User.where(less_awesome_user:true).pluck(:id)
    @users             = all_awesome_users.where.not(id: less_awesome_users)
  end

Here are 2 issues:

  1. self.awesome_users_cached doesnt cache the results and ends up hitting the
  2. all_awesome_users ends up as an array instead of active Record and hence I cannot filter out less_awesome_users from it.

There was a solution that doesnt seem to work in Rails4 anymore: Rails cache with where clause


回答1:


You should never cache ActiveRecord instances, or complex objects in general. Rather, you should cache simple primitive values, such as the primary keys of the records.

In your case, there is one more issue. where(awesome: true) is returning a scope, not a query result. Because the scope is lazy-executed, you effectively never cache anything but the query is always executed.

If you want to cache the lookup, execute the heavy query and return the IDs of the affected records. Then perform a second query fetching the records by id. You will be running 2 queries, but the first one (the most expensive one) will be cached after the first time.

def self.awesome_users_cached
  ids = Rails.cache.fetch("awesome_users") { where(awesome: true).pluck(:id) }
  find(ids)
end

You can cache the lookup of the first query, but as I mentioned before it is not a good idea.

def self.awesome_users_cached
  Rails.cache.fetch("awesome_users") { where(awesome: true).to_a }
end

You can also use a different query approach so that you can easily chain additional conditions to the cached query.

def self.awesome_users_cached
  ids = Rails.cache.fetch("awesome_users") { where(awesome: true).pluck(:id) }
  where(id: ids)
end

awesome_users_cached.where.not(id: same_company_users)


来源:https://stackoverflow.com/questions/29199223/rails4-model-caching-low-level-caching

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!