In the home_controller of my Rails 4 app, I perform a custom sql query and save the results to an instance variable
@studentscoring = ActiveRecord::Base.connecti
From the ActiveRecord cache perspective:
The way I understand this is that the ActiveRecord query cache is per web request. Meaning that if you ran your SQL query twice in the same request that it would use the cache, but the cache is cleared at the end of each request.
Source: ActiveRecord::QueryCache middleware source
(I do believe that `ActiveRecord::Base.execute calls are cached, in general, just like queries you make with the ActiveRecord query API)
If you only want to do the query once for the lifecycle of your app (or once per several hours) you can use another Rails API: the caching API to store your cache on the file system, in memory, in memcache, or in a custom store. The Rails Guide on Caching / Cache Stores.
If you do decide to use Rails.cache
the Heroku Dev Center on Caching Strategies has some code examples showing you what the API for Rails.cache
looks like. It's pretty easy to use.
Why the fragment cache doesn't work like you expect
The cache call in your view means that you are defining a fragment cache. ( see the Rails Guide on Caching / Fragment caching section ). This will cache the HTML output by the view, as you are seeing in your log.
But the fragment cache only applies to the HTML. When you do your query and assign the results to @studentscoring
you're doing it in the controller (right?) before the view executes.
ActiveRecord queries are usually lazy - execution is delayed until the data is really needed, like iterating the records - so your trick might have worked when using the ActiveRecord query API. However, I'd guess that ActiveRecord::Base.execute
queries are not lazy. I can't prove it, but it's something you could run an experiment on.
So your fragment cache may be used, but you already paid the price for the query in the controller.
Cache the query results in your controller. You can read or write back to the cache in one call (that is, set the data in the cache if it does not already exist)
def index
@studentscoring = Rails.cache.fetch("your_cache_key", :expires_in => 5.minutes) do
ActiveRecord::Base.connection.select_rows(sql_string_student)
end
end
So the above will first check the cache for "your_cache_key"
and if the data exists will return it from the cache. If it does not exist than the block will execute and it will be set in the cache