views:

200

answers:

1

Hi stackoverflow. I'm running into something strange. I'm using memcached with a caches_action setup. I'm doing this in 4 different controllers. In two of them, it works flawlessly (so far), though admittedly those two controllers are less complicated than the two in which it doesn't seem to work. I'm doing something like this:

caches_action :index, :expires_in => 6.hours, :cache_path => Proc.new {|controller| controller.send(:generate_cache_path) }, :layout => false, :if => Proc.new { |c| c.request.format.js? }

The intention behind the above is to cache some results that are dependent on the params. my :generate_cache_path method just takes into account some params and session vars and creates a unique key for memcached. I can see in memcached -vv that this is working.

What's weird is that I get my request from the rails app for a given key, and I see memcached (with -vv) get the request and send back the response. But then my action runs anyway, and a new value is then set for the same key, even when all the same params are given. I can watch it happen. In the controllers where everything is working, the request is made for the fragment, it gets it, and the action in the controller is halted, and the fragment is passed back.

These lines come from the exact same request:

Cached fragment hit: views/items/?page=1&rp=10&srtn=created_at&srto=DESC.js

And then:

Cached fragment miss: views/items/?page=1&rp=10&srtn=created_at&srto=DESC.js

I don't know what to make of it, or if I'm doing something stupid. Any help or ideas where I could start looking for trouble would be greatly appreciated.

A: 

Alright, so I've looked at this for most of the night now (surprise!) and I've debugged it down to a line in vendor/rails/actionpack/lib/action_controller/caching/actions.rb ...on line 127 starts a method as follows:

def cache_layout?
  @options[:layout] == false
end

My line:

caches_action :index, :expires_in => 6.hours, :cache_path => Proc.new {|controller| controller.send(:generate_cache_path) }, :layout => false

This, to me, would indicate that we don't want to cache the layout, only the action. But by checking @options[:layout] == false, then when layout is set to false, the method itself will return true, saying that you should cache the layout.

That seems like a bug to me. For now, I've just changed my layout line to :layout => true, and it seems to work, but that's obviously counter-intuitive.

For reference, the cache_layout? method gets called here:

def after(controller)
  return if controller.rendered_action_cache || !caching_allowed(controller)
  action_content = cache_layout? ? content_for_layout(controller) : controller.response.body
  controller.write_fragment(controller.action_cache_path.path, action_content, @options[:store_options])
end

It also forces :layout => true into the render call for whatever action.call you're going to run from the controller, which is honestly not what I want to have happen if I have to set it to :layout => true just to get cache_layout? to return false.

Just what I've come up with so far.

baldtrol