I have a controller in which I am caching the show action. The show action has a number of before filters for security that are meant to execute and redirect if the user is not logged in, not a member of the current group etc. These before filters are working perfectly when I have not turned on caching, but when I flip the switch to turn caching on the before filters are no longer executed (my debugger calls aren't hit).
It has always been my understanding that before filters are called for cached actions, this being the main difference between page caching and action caching. This is backed up by the Rails Caching Tutorial section on action caching which reads:
Action Caching works like Page Caching except for the fact that the incoming web request does go from the webserver to the Rails stack and Action Pack so that before filters can be run on it before the cache is served. This allows authentication and other restriction to be run while still serving the result of the output from a cached copy.
So why aren't my before filters getting called?
A bit about my setup: Rails 3.1 using Devise for authentication. I'm using the dalli gem for a memcached store.
Here is some code that summarizes my code (a lot of cruft cut out):
class GroupsController < ApplicationController
caches_action :show
cache_sweeper :group_sweeper
before_filter :authenticate_user!, :except => [:index]
before_filter :init_group, :except => [:new, :create, :index]
before_filter :requires_group_membership, :except => [:new, :create, :index]
def show
end
private
def requires_group_membership
if current_user and [email protected]_active.index(current_user).nil?
return true
else
redirect_to :root
return false
end
end
def init_group
@group = current_user.active_groups.find_by_id(params[:id])
if @group.nil?
redirect_to :root
return false
end
end
So, has anyone seen this behavior before? Do I have a hole in my understanding of how before filters and action caching is supposed to work? Or perhaps I have some weird voodo happening with a weird combo of gem versions?
[EDIT]
Interestingly I just learnt that the return value has not have an effect on the whether or not methods further along the chain are run, it is whether a redirect or render are called.
[edit 2]
I upgraded my app to rails 3.2.3 to see if it had an effect, but didn't fix the problem. Something that I have discovered is that the before filters defined in ApplicationController are getting called, but the ones in my GroupsController are not.
Well this has been a very timeconsuming way to learn a new tidbit about caching.
It turns out that you need to make the call to caches_action AFTER the before_filters that you want to run. I had placed the caches action as one of the first things in my class. This meant that all the before filters were not being run as they appeared below/after the caches_action, and caches_action halts the running of the code (and serves up the cached result).
Thanks to Pan Thomakos for his answer that contained this gem of info - which is either not in the ruby docs OR I have skimmed over it. I will endevour to have this info added to the docs once I have managed to claw back the time lost due to this little blindspot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With