Serialize limitations?

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. :wink:

Jon:

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.

#callback that stores the data on create
def sync_with_remote_person_data

    self.person_record_data = self.person_record.attributes
    self.save

end

def person_record_data
PersonRecord.new(self.attributes[“person_record_data”])
end

But I think I like your way better as seems much cleaner. Thanks much!