Ok, so I posted this on the ‘ruby on rails’ newsgroup
(http://groups.google.com/group/rubyonrails/browse_frm/thread/cfce770d3fbfbd1f/a51aad47e46e2adf#a51aad47e46e2adf)
but didn’t get very far.
Hopefully this community will be able to help or let me know whether
this is a genuine rails bug. This is a lengthy post, but please bear
with me.
So, I am trying to cache some data in memory, accross page invocation. I
am using a simple class ‘MyCache’, which simply holds a class variable
‘@@saved_obj’. A problem arises when you try to put a model object (an
ActiveRecord object) in @@saved_obj. If your model has ANY method
(besides those in ActiveRecord::Base) , the cached object will NOT have
these methods when you get the object back from the cache. Yes, that’s
true. It looks like the metadata for the cached object was reset between
invocation.
(if you have read my previous post on the ‘ruby on rails’ newsgroup, you
will notice that rails reloads model and controller classes between
invocation, so that’s why the class variable has to be in a separate
class, one that won’t be reloaded between invocation)
Let me simply give a code example to show what I mean:
Here is the SimpleObj model (notice the new method ‘extra_attr’):
# file app/models/simple_obj
class SimpleObj < ActiveRecord::Base
def extra_attr
“hello”
end
end
Here is the controller
# file app/controllers/my_test_controller.rb
class MyTestController < ApplicationController
def put
MyCache.put
end
def get
MyCache.get
end
end
Here is the cache object:
# file app/my_cache.rb
class MyCache
@@saved_obj = nil
def self.put
@@saved_obj = SimpleObj.new
p @@saved_obj.extra_attr
end
def self.get
p @@saved_obj.extra_attr
end
end
To recreate a full setup:
rails test
cd test
./script/generate model SimpleObj
./script/generate controller MyTest
Create a simple db with a table ‘simple_objs’. No need to put anything
in the table db… My sqlite schema is:
drop table simple_objs;
create table simple_objs (
id integer primary key autoincrement
);
Again, the schema doesn’t matter, but it needs to be there.
That’s it.
Now start your app: ./script/server
and point your bowser to:
http://localhost:3000/my_test/put
(forget about the missing view for ‘put’)
then
http://localhost:3000/my_test/get
(undefined method `extra_attr’ exception)
Ok, so what happening is:
put: after accessing my_test/put, a new SimpleObj is stored in
@@saved_obj. The value of ‘extra_attr’ is printed in the
logs/development.log file (“hello”). Perfect.
get: after accessing my_test/get, the value is retrieve from
@@saved_obj. Now, for some reason, this time the @@saved_obj does NOT
have the method ‘extra_attr’ !!! HOW BIZARRE.
If you simply print @@saved_obj, you will see that the object is indeed
of type ‘SimpleObj’ but for some reasons, it doesn’t seem to have the
method ‘extra attr’.
I know this is a lengthy post… I tried my best to summarize everything
and isolate the problem. Thanks for reading and let me know if this
makes any sense to you.
-Didier