# Marshal.dump fails on extended OpenStruct

**URL:** <https://www.ruby-forum.com/t/marshal-dump-fails-on-extended-openstruct/160568>\
**Category:** Ruby\
**Created:** [February 17, 2009, 7:40pm UTC](https://www.ruby-forum.com/t/marshal-dump-fails-on-extended-openstruct/160568 "2009-02-17T19:40:23Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![synergism](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a4c791/32.png) [@synergism](https://www.ruby-forum.com/u/synergism)\
**Post date:** [February 17, 2009, 7:40pm UTC](https://www.ruby-forum.com/t/marshal-dump-fails-on-extended-openstruct/160568/1 "2009-02-17T19:40:23Z")

</div>

If I subclass OpenStruct and extend the subclass, I cannot  
Marshal.dump it. This is apparently because ostruct.rb has its own  
custom marshal\_dump / marshal\_load that only cares about what’s in  
@table:

def marshal\_dump  
@table  
end  
def marshal\_load(x)  
@table = x  
@table.each\_key{|key| new\_ostruct\_member(key)}  
end

Is there no way to fix this in ostruct.rb to allow my ‘bad’ example  
below to work?

require ‘pp’  
require ‘ostruct’

case ARGV.first  
when /bad/i,nil  
class C \< OpenStruct  
def initialize  
super()  
@var=123  
end  
end  
when /good/i  
class C  
def initialize  
@struct=OpenStruct.new  
@var=123  
end

```
        def method_missing method,*args,&block
            @struct.send method,*args,&block
        end
    end

```

end

c=C.new  
c.a=:a  
pp c  
puts ‘c.a=%s ’ % c.a  
puts ‘c var=%s’ % c.instance\_variable\_get(’@var’)  
x=Marshal.load(Marshal.dump©)

pp x  
puts ‘x.a=%s ’ % x.a  
puts ‘x var=%s’ % x.instance\_variable\_get(’@var’)

---

<div class="post-metadata">

**Author:** ![synergism](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a4c791/32.png) [@synergism](https://www.ruby-forum.com/u/synergism)\
**Post date:** [February 17, 2009, 9:33pm UTC](https://www.ruby-forum.com/t/marshal-dump-fails-on-extended-openstruct/160568/2 "2009-02-17T21:33:58Z")

</div>

synergism wrote:

> ```
> @table.each_key{|key| new_ostruct_member(key)}
> class C < OpenStruct
> end
> 
> ```
> 
> puts ‘c.a=%s ’ % c.a  
> puts ‘c var=%s’ % c.instance\_variable\_get(’@var’)  
> x=Marshal.load(Marshal.dump©)
> 
> pp x  
> puts ‘x.a=%s ’ % x.a  
> puts ‘x var=%s’ % x.instance\_variable\_get(’@var’)

You could just write new marshal\_dump and marshal\_load methods:

require ‘ostruct’  
require ‘pp’  
class C \< OpenStruct

def initialize \*args  
super  
@var = 123  
end

def marshal\_dump  
[@table, Hash[self.instance\_variables.map { |v| [v,  
self.instance\_variable\_get("#{v}")] }]]  
end

def marshal\_load x  
@table = x[0]  
@table.each\_key{|key| new\_ostruct\_member(key)}  
x[1].each do |k,v|  
self.instance\_variable\_set("#{k}", v) unless k.to\_sym == :table  
end  
end  
end

c=C.new  
c.a=:a  
pp c  
puts ‘c.a=%s ’ % c.a  
puts ‘c var=%s’ % c.instance\_variable\_get(’@var’)  
x=Marshal.load(Marshal.dump©)

pp x  
puts ‘x.a=%s ’ % x.a  
puts ‘x var=%s’ % x.instance\_variable\_get(’@var’)

-Justin

---

<div class="post-metadata">

**Author:** ![synergism](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a4c791/32.png) [@synergism](https://www.ruby-forum.com/u/synergism)\
**Post date:** [February 17, 2009, 9:53pm UTC](https://www.ruby-forum.com/t/marshal-dump-fails-on-extended-openstruct/160568/3 "2009-02-17T21:53:18Z")

</div>

Justin C. wrote:

> > ```
> > @table = x
> > when /bad/i,nil
> > @var=123
> > 
> > ```
> > 
> > pp c

Let me try that again:

require ‘ostruct’  
require ‘pp’

class C \< OpenStruct

def initialize \*args  
super  
@var = 123  
end  
def marshal\_dump  
[@table, Hash[self.instance\_variables.map { |v| [v,  
self.instance\_variable\_get("#{v}")] }]]  
end  
def marshal\_load x  
@table = x[0]  
@table.each\_key{|key| new\_ostruct\_member(key)}  
x[1].each do |k,v|  
self.instance\_variable\_set("#{k}", v) unless k.to\_sym == :table  
end  
end  
end

c=C.new  
c.a=:a  
pp c  
puts ‘c.a=%s ’ % c.a  
puts ‘c var=%s’ % c.instance\_variable\_get(’@var’)  
x=Marshal.load(Marshal.dump©)

pp x  
puts ‘x.a=%s ’ % x.a  
puts ‘x var=%s’ % x.instance\_variable\_get(’@var’)

---

<div class="post-metadata">

**Author:** ![synergism](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a4c791/32.png) [@synergism](https://www.ruby-forum.com/u/synergism)\
**Post date:** [February 19, 2009, 12:27pm UTC](https://www.ruby-forum.com/t/marshal-dump-fails-on-extended-openstruct/160568/4 "2009-02-19T12:27:05Z")

</div>

On Feb 17, 4:32 pm, Justin C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> You could just write new marshal\_dump and marshal\_load methods:

Thanks. I considered that, but the bigger issue is that this makes  
using DRb in any application of non-trivial complexity quite painful,  
as we now need to mess with the implementation details of every  
serialized object. I was just hoping something more transparent could  
be done with ostruct to make things better.

Incidentally, I continued with the delegation model I used in my  
example and found that this wasn’t where the trouble ended. I had to  
also eliminate an un-dumpable proc I had used to auto-initialize a  
Hash of Hashes (to make an empty hash be the default value so that []  
[] references would not raise an exception on uninitialized keys) i.e.

class AutoHash \< Hash  
def [] key  
\_=fetch(key) rescue \_=store(key,{})  
\_  
end  
end

class C  
def initialize  
# …  
@attributes=AutoHash.new  
end  
end

instead of:

```
    # ...
    @attributes=Hash.new{|hash,key| hash[key]={}}

```

It seems programming with DRb is fraught with difficulties like  
these. I wish we had something easier to use, as otherwise DRb is  
exactly what we need for this application.

Ben

---

<div class="post-metadata">

**Author:** ![synergism](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a4c791/32.png) [@synergism](https://www.ruby-forum.com/u/synergism)\
**Post date:** [February 17, 2009, 9:58pm UTC](https://www.ruby-forum.com/t/marshal-dump-fails-on-extended-openstruct/160568/5 "2009-02-17T21:58:00Z")

</div>

Justin C. wrote:

> > > def marshal\_load(x)  
> > > case ARGV.first  
> > > @struct=OpenStruct.new  
> > > c.a=:a
> 
> @var = 123  
> end  
> puts ‘x var=%s’ % x.instance\_variable\_get(’@var’)

I give up. I don’t know why the formatting is all weird.

-Justin
