Rails caching: Expiring multiple pages for one action
Asked Answered
K

2

6

I've set up action caching (with sweepers, but I guess that's irrelevant here) in my app, and so far it works great except for one thing:

I use Kaminari for pagination, and thus when I execute expire_action on my action it only expires the first page. As I know caching won't work when using the query string for specifying the page, I've set up a route so the pages are appended to the end of the url (for example /people/123/page/2).

I'll add more info to this post if necessary, but I'm guessing there is something obvious I'm missing here, so: Anyone know how to expire the rest of my pages?

Kenon answered 19/5, 2012 at 13:47 Comment(1)
What would work equally well would be if I could exclude anything but the first page from indexing at all, since close to nobody will ever view the following pages...Kenon
K
5

I'm still interested in an answer to my original question and will change my accepted answer should a solution come up. That said, I ended up only caching the original page by checking if a page was specified at all:

caches_action :index, :if => Proc.new { params[:page].nil? }

Kenon answered 20/5, 2012 at 6:28 Comment(1)
Another solution for that case is using cache_path option.. https://mcmap.net/q/395127/-rails-action-caching-with-querystring-parametersAcre
F
1

Here is a solution I've thought of, facing the same problem, though haven't implemented it yet. Cache the actual expiry time in its own key. The key would be a canonical representation of the search URL, ie without the "page" parameter. e.g.:

User searches on http://example.com?q=foo&page=3, so params is { q: 'foo', page: 3 }. Strip out "page=3" and we're left with { q: 'foo' }.

Run to_param on it and add some prefix, and we're left with a cache key like search_expiry_q=foo.

Look up cache for this canonical query, ie Rails.cache.read(search_expiry_q=foo). If it exists, we'll make our result expire at this time. Unfortunately, we only have expires_in, not expires_at, so we'll have to do a calculation. i.e. something like expires_in: expiry_time - Time.now - 5.seconds (the 5 seconds hopefully prevents any race conditions). We cache the full URL/params this way.

OTOH if there's no expiry, then no-one's performed the search recently. So we do:

expiry_time = Time.now + 1.hour
Rails.cache.write(`search_expiry_q=foo`, expiry_time, expires_in: 1.hour)

And cache this fragment/page, again with full URL/params, and expires_in: 1.hour.

Flunky answered 14/8, 2012 at 18:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.