4

I'm following the low-level caching tutorial found on Heroku's website. Copying their example almost word-for-word, here is my method:

def Trip.test_low_level
  Rails.cache.fetch("test_destinations", expires_in: 12.hours) do
    Trip.all.joins(:destinations).where("destinations.id = ?", 382)
  end
end

To the best of my knowledge, this should:

  1. Execute the query the first time Trip.test_low_level() is called
  2. The second time Trip.test_low_level(), it should look for the cache called 'test_destinations' and return the result without querying the database.

However, no matter how many times I run the method, the query is still called. Here are results from my terminal.

Trip.test_low_level()
  Trip Load (6.2ms)  SELECT "trips".* FROM "trips" INNER JOIN "destination_orders" ON "destination_orders"."trip_id" = "trips"."id" INNER JOIN "destinations" ON "destinations"."id" = "destination_orders"."destination_id" WHERE (destinations.id = 382)
 => #<ActiveRecord::Relation [#<Trip id: 2783, title: "Test Saving"....


Trip.test_low_levle()
  Trip Load (3.6ms)  SELECT "trips".* FROM "trips" INNER JOIN "destination_orders" ON "destination_orders"."trip_id" = "trips"."id" INNER JOIN "destinations" ON "destinations"."id" = "destination_orders"."destination_id" WHERE (destinations.id = 382)
 => #<ActiveRecord::Relation [#<Trip id: 2783, title: "Test Saving"

Even if I call the cache directly, I get the same result:

Rails.cache.fetch('test_destinations')
  Trip Load (5.0ms)  SELECT "trips".* FROM "trips" INNER JOIN "destination_orders" ON "destination_orders"."trip_id" = "trips"."id" INNER JOIN "destinations" ON "destinations"."id" = "destination_orders"."destination_id" WHERE (destinations.id = 382)
 => #<ActiveRecord::Relation [#<Trip id: 2783, title: "Test Saving"...

How can I prevent it from hitting the database the second time?

EDIT: Here is my settings in development.rb

# In the development environment your application's code is reloaded on
  # every request. This slows down response time but is perfect for development
  # since you don't have to restart the web server when you make code changes.
  config.cache_classes = false

  # Do not eager load code on boot.
  config.eager_load = false

  # Show full error reports and disable caching.
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = true

Production.rb

# Code is not reloaded between requests.
  config.cache_classes = true

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both threaded web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = true

  # Full error reports are disabled and caching is turned on.
  config.consider_all_requests_local       = false
  config.action_controller.perform_caching = true
CHawk
  • 1,346
  • 5
  • 22
  • 40
  • Could it be that the cache is not used in dev? – max Feb 21 '16 at 11:35
  • Development definitely performs fragment caching as I've already implemented that. Edited my post with my other settings. – CHawk Feb 21 '16 at 11:40
  • what is your setting for `production.rb`? – Hieu Pham Feb 21 '16 at 12:01
  • I can't see anything obvious, maybe its because '.where' returns a scope. Is there any difference if you explicity load it with '.to_a'? – max Feb 21 '16 at 12:09
  • Just tested - adding .to_a doesn't change the result. @HieuPham, I edited my response with my production settings. How would that affect development though? – CHawk Feb 21 '16 at 13:24
  • 1
    See http://stackoverflow.com/questions/11218917/confusion-caching-active-record-queries-with-rails-cache-fetch – Frederick Cheung Feb 21 '16 at 14:45
  • Ahh! @FrederickCheung, that was the key. I searched SO and couldn't find other questions that helped. What is the etiquette for selecting an answer on this thread? – CHawk Feb 21 '16 at 15:08

0 Answers0