Banging my head about this one today and I can’t find any information on this in the API…
I have two models… User and PersonRecord. PersonRecord is a model that is shared among several applications and hooked into a completely different database. It contains the personal information about a user. The User model simply contains a username column. These models work together via a belongs_to relationship.
u = User.find 1
u.person_record.last_name
=> “Hogan”
Let’s say I have 200 users… I would hate to have to run 200 queries to the second database to grab the other data, so my thought was “Hey, I’ll just serialize that data onto my object and periodically synchronize the data.”
class User < ActiveRecord::Base
serialize :person_record_data, PersonRecord
… more stuff
end
u.person_record_data = u.person_record
u.save
That all works just great… except when I try to get the record back, person_record_data is nil.
I can serialize hashes, arrays, etc just fine… but I can’t seem to serialize ActiveRecord objects… is this a limitation? a bug?
Thanks in advance to anyone who can help me out. The documentation on what is allowed is pretty vague.
I ran into a very similar problem a while back. Eventually, my
solution was to remove the call to 'serialize' from the model and add
the following two methods...
def value
self[:value] ? Marshal.load(self[:value]) : nil
end
def value=(x)
self[:value] = Marshal.dump(x)
end
Where 'value' is the name of the column in the database where the
serialized data is to be stored, which would be 'person_record_data' in
your case. Replacing Marshal with YAML (i.e. YAML.load, YAML.dump) in
the above methods may be equally or more suitable in some scenarios.
It seems that AR's 'serialize' function tries to do a bunch of extra
magic, which makes it behave unexpectedly when one is trying to do what
we are. Personally, I wish it would knock off the magic, and just do
what it says it does... serialize.
Interesting… I arrived at a very similar solution using serialize… instead of storing the object itself, I simply stored the attributes in that field and wrote the getter myself.