Christoffer
Christoffer

Reputation: 2411

Rails: Skip controller if cache fragment exist (with cache_key)

I have been using cache for a long time and recently discovered that my fragment caching doesn't stop my controller from executing the code, as it always has been. I have boiled the problem down to have to do with the cache_key that seems to be a new feature?

This is my previous solution that no longer works as expected.

Product#Show-view:

cache('product-' + @product.id.to_s)  do
# View stuff
end

Product#Show-controller:

unless fragment_exist?('product-19834') # ID obviously dynamically loaded
# Perform slow calculations
end

The caching works fine. It writes and reads the fragment, but it still executes the controller (which is the whole reason I want to use caching). This boils down to the fragment has an added unique id so the fragment created is something like:

views/product-19834/b05c4ed1bdb428f73b2c73203769b40f

So when I check if the fragment_exist I am not checking for the right string (since I am checking for 'views/product-19834'). I have also tried to use:

fragment_exist?("product-#{@product.id}/#{@product.cache_key}")

but it checks with a different cache_key than is actually created.

I would rather use this solution than controller-caching or gems like interlock.

My question is: - How do I, in the controller, check if a fragment exist for a specific view considering this cache key?

Upvotes: 3

Views: 1222

Answers (2)

claasz
claasz

Reputation: 2144

It might be worth pointing out that while the proposed solution (fragment_exist?) could work, it's more like a hack.

In your question, you say

It writes and reads the fragment, but it still executes the controller (which is the whole reason I want to use caching)

So what you actually want is "controller caching". But fragment caching is "view caching":

Fragment Caching allows a fragment of view logic to be wrapped in a cache block and served out of the cache store (Rails Guides 5.2.3)

For "controller caching", Rails already provides some options:

Which are all, from my point of view, better suited for your particular use case.

Upvotes: 1

Christoffer
Christoffer

Reputation: 2411

As Kelseydh pointed out in the link, the solution to this is to use skip_digest => true in the cache request:

View

cache ("product" + @product.id, :skip_digest => true) 

Controller

fragment_exist?("product-#{@product.id}")

Upvotes: 7

Related Questions