Matt Elhotiby
Matt Elhotiby

Reputation: 44066

Is there a way to cache the .all call?

For example i have this in my index controller

@users = User.current

this is my User model

 scope :current, :conditions => { :active => true }, :order => 'LOWER(first_name), LOWER(last_name) ASC'

Which is basically grabbing all the records and I am not paginating because I am using the jquery datatables table that has a great filter search... the problem I am wanting to achieve is to cache these if possible unless there are new users...which doesnt happen very often

I read about fresh_when but didnt know what could be used here

UPDATE

After following the answer below i dont see CACHE in the log all i see is

  Company Load (0.4ms)  SELECT `companies`.* FROM `companies` INNER JOIN `positions` ON `companies`.`id` = `positions`.`company_id` WHERE `positions`.`user_id` = 551
  Company Load (0.4ms)  SELECT `companies`.* FROM `companies` INNER JOIN `positions` ON `companies`.`id` = `positions`.`company_id` WHERE `positions`.`user_id` = 93
  Company Load (0.4ms)  SELECT `companies`.* FROM `companies` INNER JOIN `positions` ON `companies`.`id` = `positions`.`company_id` WHERE `positions`.`user_id` = 668

Upvotes: 5

Views: 381

Answers (1)

tybro0103
tybro0103

Reputation: 49713

class User < ActiveRecord::Base
  after_save :clear_cache

  def self.current
    Rails.cache.fetch("current_users", expires_in: 1.hour) do
      User.where(active: true).order("LOWER(first_name), LOWER(last_name) ASC").all
    end
  end

private

  def clear_cache
    Rails.cache.delete("current_users")
  end

end

Ensure that caching is enabled in config/environments/*.rb:

config.action_controller.perform_caching = true

This is what you want. Read more here:
http://robotmay.com/post/23161612605/everyone-should-be-using-low-level-caching?bda26d48
http://www.tmatthew.net/blog/rails-caching-example
http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html#method-i-fetch

When storing models in the cache, you may run into an odd problem that occurs when the cache is fetched before the models are loaded. Not to worry, this will only happen in development, and there's a fix (application_controller.rb):

before_filter :load_models_if_dev
def load_models_if_dev
    if Rails.env == 'development'
        User; Post; Comment # whatever other classes that can get cached.
    end
end 

UPDATE
Notice the .all in User.where().order().all. Without that, the value stored in the cache is just an ActiveRecord Relation and not the actual results. Without the .all a query will still have to run. Thanks @Frederick Cheung for bringing that to our attention.

Upvotes: 6

Related Questions