# ActiveRecord::Base.serialize and a model in a plugin

**URL:** <https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538>\
**Category:** Rails\
**Created:** [December 6, 2006, 7:31pm UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538 "2006-12-06T19:31:35Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![hatless](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/848f3c/32.png) [@hatless](https://www.ruby-forum.com/u/hatless)\
**Post date:** [December 6, 2006, 7:31pm UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538/1 "2006-12-06T19:31:35Z")

</div>

All right, I posted about this yesterday and I have to believe the  
problem is not with AR’s serialize method but with my particular  
circumstance.

The two obvious issues are that

(1) I’m serializing a hash of 15 objects that contain seven strings  
apiece. The objects were Structs, but in the interest of pulling the  
definition out of a module and putting it in app/models, I’ve since  
turned it into a non-AR Class because I thought maybe the issue was  
that the Struct was defined in a library module.

models/idx\_row.rb:

class IdxRow  
attr\_accessor :image\_url, :price, :beds, :baths, :sqft, :mls\_id,  
:mls\_url

def initialize  
@image\_url = “”  
@price = “”  
@beds = “”  
@baths = “”  
@sqft = “”  
@mls\_id = “”  
@mls\_url = “”  
end  
end

(2) The model I have the serialized attribute on is the Comment class  
created by acts\_as\_commentable. The basic class definition is in the  
plugin, not in app/models. I looked through the code and it looked like  
the proper way to extend the class was through a module of my own, so I  
created lib/commentable\_extensions.rb and put it there. I added a TEXT  
column called “feed”, and wrote the following:

lib/commentable\_extensions.rb:

module CommentableExtensions  
module Juixe  
module Acts #:nodoc:  
module Commentable #:nodoc:  
module ClassMethods  
def acts\_as\_commentable  
serialize :feed  
end  
end  
end  
end  
end  
end

I’ve tried a few ways of loading the extension, currently an include in  
application.rb, and when I load a Comment into c and assign one of my  
hashes to c.feed, I get the same old SystemStackError when I attempt  
c.save:

SystemStackError: stack level too deep  
from c:/ruby/lib/ruby/1.8/yaml/rubytypes.rb:168:in `to_yaml' from c:/ruby/lib/ruby/1.8/yaml.rb:387:in`quick\_emit’  
from c:/ruby/lib/ruby/1.8/yaml/rubytypes.rb:164:in `to_yaml' from c:/ruby/lib/ruby/1.8/yaml/rubytypes.rb:41:in`to\_yaml’  
from c:/ruby/lib/ruby/1.8/yaml/rubytypes.rb:40:in `to_yaml' from c:/ruby/lib/ruby/1.8/yaml/rubytypes.rb:39:in`to\_yaml’  
from c:/ruby/lib/ruby/1.8/yaml.rb:387:in `quick\_emit’…

Though it’s possible that my object is simply too complex for  
#to\_yaml’s tiny brain, I’m reluctant to think that’s the case with what  
seems to me such a simple data structure. At this point I’m wondering  
if the problem is the way I’m trying to declare the serialization of  
:feed. Is there some other place or way I’m supposed to do this?

Thanks.

---

<div class="post-metadata">

**Author:** ![hatless](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/848f3c/32.png) [@hatless](https://www.ruby-forum.com/u/hatless)\
**Post date:** [December 6, 2006, 9:38pm UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538/2 "2006-12-06T21:38:17Z")

</div>

Much as I have trouble believing it, I’m becoming convinced that my  
problem really, truly is that AR’s serialize method or the #to\_yaml  
method behind it simply can’t handle the hypercomplexity of a hash of  
fifteen structs of seven strings. My code shown above serializes tiny,  
simple objects like a champ (a single, small array or a single struct?  
no problem). But when given 6 kilobytes of text nested two levels deep,  
#to\_yaml pops a gasket.

Either I’m missing something obvious, or this is kinda lame. I saw a  
closed ticket in Rails Trac from two years ago in which I think Jamis  
submitted a patch that extended AR Serialize to use Marshal and a  
binary column optionally in place of YAML because of this very sort of  
#to\_yaml explosion whenever it was asked to do anything meaningful.  
Anyone know if this is present and undocumented, or something that  
fell by the wayside?

---

<div class="post-metadata">

**Author:** ![hatless](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/848f3c/32.png) [@hatless](https://www.ruby-forum.com/u/hatless)\
**Post date:** [December 6, 2006, 9:52pm UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538/3 "2006-12-06T21:52:20Z")

</div>

Okay, working through it myself. I can serialize a struct, but I can’t  
seem to serialize my custom, non-AR classes at all. This seems to be  
the Insurmountable Problem. Am I crazy for wanting to serialize my own  
classes and not just ruby core classes?

That is, I cannot say:

r = IdxRow.new  
r.price = “$300”  
c.feed = r  
c.save

…but I can say

x = Struct.new(:foo, :bar, :baz, :feh, :fez, :fex)  
r = x[1,2,3,4,5,6]  
c.feed = r  
c.save

---

<div class="post-metadata">

**Author:** ![hatless](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/848f3c/32.png) [@hatless](https://www.ruby-forum.com/u/hatless)\
**Post date:** [December 6, 2006, 10:54pm UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538/4 "2006-12-06T22:54:40Z")

</div>

I keep narrowing it down. Now I’ve banished my nice Struct and the  
less-nice custom IdxRow class i created in its place, and instead I’m  
now putting my data into a single hash containing 15 hashes of 7  
strings apiece. No Procs in sight, nothing fancy, just a hash of hashes  
of strings. I figured this would work for sure.

Nope. AR Serialize exploded like it always does when given anything  
more complex than a one-liner.

Also, attempting Marshal.dump on this hash of hashes gives me an error  
message that helpfully tells me I can’t dump a Proc. Which would be  
more helpful if I could see how a vanilla hash of vanilla hashes of  
vanilla strings is being seen as containing a Proc.

---

<div class="post-metadata">

**Author:** ![hatless](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/848f3c/32.png) [@hatless](https://www.ruby-forum.com/u/hatless)\
**Post date:** [December 6, 2006, 11:06pm UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538/5 "2006-12-06T23:06:44Z")

</div>

-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1

hatless wrote:

> message that helpfully tells me I can’t dump a Proc. Which would be  
> more helpful if I could see how a vanilla hash of vanilla hashes of  
> vanilla strings is being seen as containing a Proc.

Does your Hash have a custom contructore with a Proc? ie:

> > h2 = Hash.new{ |h,k| h[k] = 5 }  
> > =\> {}  
> > Marshal.dump( h2 )  
> > TypeError: can’t dump hash with default proc  
> > from (irb):6:in `dump’  
> > from (irb):6  
> > from :0

You can’t do that =)

Zach  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.3 (GNU/Linux)  
Comment: Using GnuPG with Mozilla - [http://enigmail.mozdev.org](http://enigmail.mozdev.org)

iD8DBQFFdz4QMyx0fW1d8G0RAg+IAJ94AxFW2HEi6nMmmydKzL/f7vSr3gCfRo2t  
eBFONZp45kozWKjOfRvJnsg=  
=gYhS  
-----END PGP SIGNATURE-----

---

<div class="post-metadata">

**Author:** ![hatless](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/848f3c/32.png) [@hatless](https://www.ruby-forum.com/u/hatless)\
**Post date:** [December 7, 2006, 5:03am UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538/6 "2006-12-07T05:03:23Z")

</div>

All right! Solved!

Turns out some of the methods in RubyfulSoup – the RubyfulSoup#string  
method, in fact – don’t return Strings. They return NavigableStrings,  
as I discovered when I ran

myhash[1].values.each {|v| puts “#{v}: #{v.class}”}

All was good once I changed things like:

working\_row[‘fruit’] = tr.find\_all(‘td’)[0].a.string

to

working\_row[‘fruit’] = tr.find\_all(‘td’)[0].a.string.to\_s

ARGH!

Now myhash serializes fine. I’m surprised it doesn’t seem to  
deserialize automagically and I have to YAML.load() it, but that’s for  
another thread (or not).

It didn’t help that the culprit objects rendered like normal Strings.  
Thanks again for the help and thanks to anyone sitting through a  
5-message thread of me talking myself through it.

---

<div class="post-metadata">

**Author:** ![hatless](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/848f3c/32.png) [@hatless](https://www.ruby-forum.com/u/hatless)\
**Post date:** [December 7, 2006, 12:18am UTC](https://www.ruby-forum.com/t/activerecord-base-serialize-and-a-model-in-a-plugin/78538/7 "2006-12-07T00:18:54Z")

</div>

Thanks for the help. Hmmm. I build my Hash of Hashes this way:

myhash = {}  
i = 1  
for row in [1,2,3]  
temphash = {}  
temphash[‘foo’] = “bar”  
myhash[i] = temphash  
i += 1  
end

This code works. My actual code, which assigns string values to a bunch  
more elements of the inner hashes the same way makes #to\_yaml and  
Marshal.dump() break.

The generated Hash and its members don’t contain any object  
identifiers. There are no custom constructors. Like the above code, the  
real method results in an ordinary looking hash with integer keys and  
Hash values, and inner Hashes with String keys and values.

Here’s my actual code that returns the hash. I’ve only changed the  
names of my keys so I don’t give away whose HTML I’m scraping:

def fetch\_idx\_hash(obj)  
counter = 1 # 1…n instead of starting with zero, used as the hash  
index.  
myhash = {}  
page = fetch\_page(obj)  
soup = BeautifulSoup.new page  
soup.html.body.center.find\_all(‘table’)[5].find\_all(‘tr’).each do  
|tr|  
working\_row = {}  
if tr.find\_all(‘td’)[1].string.include? “$”  
working\_row[‘price’] = tr.find\_all(‘td’)[1].string  
end  
unless tr.find\_all(‘td’)[0].a.nil?  
working\_row[‘fruit’] = tr.find\_all(‘td’)[0].a.string  
working\_row[‘vegetable’]= “[http://www.foo.com](http://www.foo.com)” +  
tr.find\_all(‘td’)[0].a[‘href’]  
end  
working\_row[‘starch’] = tr.find\_all(‘td’)[3].string  
working\_row[‘meat’] = tr.find\_all(‘td’)[4].string  
working\_row[‘cake’] = tr.find\_all(‘td’)[5].string  
# This must be the last member populated. Rows w/o images get  
discarded.  
unless tr.img.nil?  
working\_row[‘image\_url’] = tr.img[‘src’]  
myhash[counter] = working\_row  
counter += 1  
end  
end  
return myhash  
end

Calling to\_yaml on the resulting hash blows up with a SystemStackError.  
Calling Marshal.dump() carps about a Proc. I’m wondering if after  
everything I’ve done to simplify the data structure, it’s just too big.  
Incidentally, none of the member strings exceed 300 characters, and  
most are small. A typical myhash.to\_s.size is about 7K.
