Unwanted Caching

I am having a problem with Rails caching an action even though I’m in
development mode with caching disabled. I have an action that fetches a
collection of objects from the db and then passes the collection to the
view for rendering using a partial. The catch is that the db is being
updated outside the application by a rails background process. But the
db updates aren’t being reflected when the view is re-rendered. The
rendering works fine the first time but the collection doesn’t change
after that.

Anybody have an idea on why this caching would be taking place and how
to disable it in this instance?

Thanks, Don

Don S. wrote:

Hmmm. I still don’t get it. I checked my development.rb environment
and config.action_controller.perform_caching is set to false. But the
view always renders the same result.

Any suggestions would certainly be appreciated.

Thanks!

  • Don

Don S. wrote:

OK, I was able to resolve this by using reload in my action like this:

def dashboard
user = session[:rbac_user]
@pollers = user.pollers.reload
end

Without the reload, Rails was not fetching the data from the db after
the first rendering. It was just re-rendering the stale data. I’m sure
that neither the action nor the view was being cached because I added a
@now = Time.now in the action and rendered it in the view and it worked
perfectly. But my @pollers collection was not being updated.

The Pick Axe book says (page 220 under the Reloading Data section) “In
practice, reload() is rarely used outside the context of unit tests.”

Any ideas why it would be needed here? Is it simply because this
dataset is being updated outside the application? If so, is this the
best workaround?

Thanks!

  • Don

Don S. wrote:

Don S. wrote:

OK, I was able to resolve this by using reload in my action like this:

def dashboard
user = session[:rbac_user]
@pollers = user.pollers.reload
end

Without the reload, Rails was not fetching the data from the db after
the first rendering. It was just re-rendering the stale data. I’m sure
that neither the action nor the view was being cached because I added a
@now = Time.now in the action and rendered it in the view and it worked
perfectly. But my @pollers collection was not being updated.

The Pick Axe book says (page 220 under the Reloading Data section) “In
practice, reload() is rarely used outside the context of unit tests.”

Any ideas why it would be needed here? Is it simply because this
dataset is being updated outside the application? If so, is this the
best workaround?

Thanks!

  • Don

Don S. wrote:

Don S. wrote:

OK, I was able to resolve this by using reload in my action like this:

def dashboard
user = session[:rbac_user]
@pollers = user.pollers.reload
end

Without the reload, Rails was not fetching the data from the db after
the first rendering. It was just re-rendering the stale data. I’m sure
that neither the action nor the view was being cached because I added a
@now = Time.now in the action and rendered it in the view and it worked
perfectly. But my @pollers collection was not being updated

Any ideas why it would be needed here? Is it simply because this
dataset is being updated outside the application? If so, is this the
best workaround?

Thanks!

  • Don

The problem isn’t “caching” as defined in your environment files, but
ActiveRecord query caching so it doesn’t have to run a query it already
knows the answer to. Most of the time an object is only alive for a
single page load, and then recreated form the DB for subsequent page
loads.

user = User.find(1) # SELECT * FROM users WHERE id = 1
user.pollers # SELECT * pollers WHERE user_id = 1
user.pollers # No query

This is standard ActiveRecord behavior, regardless of environment
setting.

Your problem is that youare caching the entire ActiveRecord object in
the session. This gives your object an unintentionally extended life
span. This is precisely the problem with storing the entire object in
the session. AR objects in the session can become stale quickly.

ActiveRecord was designed objects existing briefly, not for extended
periods. But just in case, the reload method is provided to clear out
the old data and get new stuff.

The more common solution is to simply store the user id in the session
rather the user object itself. Then you load the user from the DB on
each page load. This is ESPECIALLY important if you are updating the DB
from outside the rails app itself.

You can reinflate it a few ways. The simplest is to prepare an instance
variable with the user object before every request.

application.rb

before_filter :get_user
def get_user
@user = User.find_by_id(session[:user_id])
end

controller

def dashboard
@pollers = @user.pollers
end

Alex W. wrote:

The problem isn’t “caching” as defined in your environment files, but
ActiveRecord query caching so it doesn’t have to run a query it already

Alex,

Thank you for your excellent explanation. You were exactly right.
Watching the log, I could see that the query was not running but adding
dynamic content like Time.now showed that it was not an action or
template caching issue. Even though I knew that the user object was
being stored in the session (I’m using ActiveRBAC) but for some reason,
I didn’t realize that all of the user object’s children would also be
stored. That makes perfect sense now.

I took your suggestion and added a before filter in application.rb to
set a @user variable and now it’s working like a champ.

I’ve learned a valuable lesson with this one. You rock!

Thanks a ton.

  • Don

On Wed, 2006-11-01 at 20:53 +0100, Don S. wrote:

to disable it in this instance?


I’ve had this happen to me using svn when I’ve cached pages in
production, made svn commits and mistakenly added the ‘cached pages’
into svn whereupon the cached page ended up in my
development_path/public/model/cached_page.html - obviously deleting the
page remedied that issue as well as clearing it out from svn

Craig

Don S. wrote:

db updates aren’t being reflected when
the view is re-rendered.

Could you say a bit more about what exactly you mean when you say “the
view
is re-rendered”?

Thanks,
Bill

Don S. wrote:

Hmmm. I still don’t get it. I checked my development.rb environment
and config.action_controller.perform_caching is set to false. But the
view always renders the same result.

Any suggestions would certainly be appreciated.

I forget the beginning part of this thread, but any chance you’re using
mysql and it’s query cache is messing you up? It’s supposed to get
cleared if you update the table, but we’ve had it get confused before…

?