This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the caching category.
Last Updated: 2025-11-05
I wrote the following code and it executed just fine. This was despite the fact that, as I would later learn, it had an error:
@taxonomies = Rails.cache.fetch("taxons_db_data_#{current_store}") do
Taxonomy.includes(:taxon) # should have been :taxons (plural)
end
My first hint that there was a bug here was that downstream code consuming this
@taxonomies instance variable failed - the bug essentially was deferred until
this data structure was consumed. I saw the issue and fixed the incorrect pluralization:
@taxonomies = Rails.cache.fetch("taxons_db_data_#{current_store}") do
Taxonomy.includes(:taxons) # now plural
end
Desite my fix, the bug continued. This seemed weird because usually a cache doesn't store errors - i.e. this would not be cached.
@taxonomies = Rails.cache.fetch("taxons_db_data_#{current_store}") do
raise
end
When I experimented with clearing the cache, however, my code worked again,
indicating that the cached entity was the source of my woes. And so I got to the
bottom of it. The issue was that Rails scopes (i.e. code that executes SQL such
as Taxonomy.include()) are lazy, so therefore the error doesn't actually
crop up until you call .to_a (explicitly or implicitly) on it - which only happens
upon consumption of the taxonomies array.
I can prove this laziness by looking at what the postgres server (not the Rails client logs, which cannot be fully trusted) see when I cache this way:
taxonomies = Rails.cache.fetch("test123") { Taxonomy.includes(:taxons) }
# postgres server: executes every time - i.e. even though it is correct, it is not cached.
taxonomies = Rails.cache.fetch("test123") { Taxonomy.includes(:taxons).to_a }
# postgres server: DOES NOT execute every time, i.e. it caches