Detecting singletons

L

Lars Westergren

I have a fairly large and complex object graph of Value Objects created
by soap4r and used in a Rails application. The app, which used to work,
now gets
Exception `TypeError' at
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:97
- singleton can't be dumped
all over the place and I have narrowed it down to Marshal.dump being
used by Rails.

I have aliased Marshal.dump so that I can inspect the objects passed
first, I thought that would be the fastest way to locate the problematic
object. My question is, how do I detect that an object is a singleton?
Should I test with "responds_to?" if the "new" method lacking or that
the "instance" method is there? Or is there an easier way?

Thanks in advance,
Lars
 
V

Vincent Bray

I have a fairly large and complex object graph of Value Objects created
by soap4r and used in a Rails application. The app, which used to work,
now gets
Exception `TypeError' at
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:97
- singleton can't be dumped
all over the place and I have narrowed it down to Marshal.dump being
used by Rails.

I have aliased Marshal.dump so that I can inspect the objects passed
first, I thought that would be the fastest way to locate the problematic
object. My question is, how do I detect that an object is a singleton?
Should I test with "responds_to?" if the "new" method lacking or that
the "instance" method is there? Or is there an easier way?

(first post to this list, so get some salt)

Singleton in this case probably means that the object you're trying to
marshal has a singleton method defined on it (maybe the wrong term.
whatever it's called when you do stuff like "def object.foo;
some_foo(); end".)

The reason it can't be dumped is likely that dumping the 'data' bits
of the object won't save the singleton method(s), so unmarshalling
would be incomplete.
 
R

Robert Klemme

2007/7/25 said:
I have a fairly large and complex object graph of Value Objects created
by soap4r and used in a Rails application. The app, which used to work,
now gets
Exception `TypeError' at
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:97
- singleton can't be dumped
all over the place and I have narrowed it down to Marshal.dump being
used by Rails.

I have aliased Marshal.dump so that I can inspect the objects passed
first, I thought that would be the fastest way to locate the problematic
object. My question is, how do I detect that an object is a singleton?
Should I test with "responds_to?" if the "new" method lacking or that
the "instance" method is there? Or is there an easier way?

If Singleton === obj
puts "it's a singleton!"
end

Kind regards

robert
 
R

Robert Dober

I have a fairly large and complex object graph of Value Objects created
by soap4r and used in a Rails application. The app, which used to work,
now gets
Exception `TypeError' at
/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:97
- singleton can't be dumped
all over the place and I have narrowed it down to Marshal.dump being
used by Rails.

I have aliased Marshal.dump so that I can inspect the objects passed
first, I thought that would be the fastest way to locate the problematic
object. My question is, how do I detect that an object is a singleton?
Should I test with "responds_to?" if the "new" method lacking or that
the "instance" method is there? Or is there an easier way?

Thanks in advance,
Lars
The following should do the trick -- alas :(

class Class
def is_singleton?
! ancestors.include?( self ) rescue false
end
end

HTH
Robert
 
R

Robert Dober

Did I do something stupid?

694/194 > irb
irb(main):001:0> require 'singleton'
=> true
irb(main):002:0> s = "abc"
=> "abc"
irb(main):003:0> sing = class << s; self end
=> #<Class:#<String:0xb7d9eaec>>
irb(main):004:0> Singleton === s
=> false
irb(main):005:0> Singleton === sing
**********
=> false
**********
irb(main):006:0> puts "??????"
??????
=> nil
irb(main):007:0>
R.
 
R

Robert Klemme

2007/7/25 said:
Did I do something stupid?

No, you seem to be dragged into the confusion between singleton and
singleton. :)
694/194 > irb
irb(main):001:0> require 'singleton'
=> true
irb(main):002:0> s = "abc"
=> "abc"
irb(main):003:0> sing = class << s; self end
=> #<Class:#<String:0xb7d9eaec>>
irb(main):004:0> Singleton === s
=> false
irb(main):005:0> Singleton === sing
**********
=> false
**********
irb(main):006:0> puts "??????"
??????
=> nil
irb(main):007:0>

The "singleton" you are referring to is the singleton class (btw, now
I understand your code suggestion). I believe the OP wanted to know
about Singleton as in

class Foo
include Singleton
end

Kind regards

robert
 
L

Lars Westergren

Robert Dober skrev:
Did I do something stupid?
Oh, good, so it wasn't just me then.
:)

It doesn't seem to work for me either. I get false, and then the
exception anyway.

I think that test only works if the class in question used the Singleton
module mixin, I believe the problematic class probably uses some form of
sing = class << self; self end
magic.

I tried looking at the code for marshalling, but alas, it was C, and
therefore not much help to me...

if (FL_TEST(klass, FL_SINGLETON)) {
if (check && RCLASS(klass)->m_tbl->num_entries ||
(RCLASS(klass)->iv_tbl && RCLASS(klass)->iv_tbl->num_entries
rb_raise(rb_eTypeError, "singleton can't be dumped");
}



Thanks,
Lars
 
R

Robert Klemme

2007/7/25 said:
No, you seem to be dragged into the confusion between singleton and
singleton. :)

No, *I* confused them. Just forget all the rest of what I wrote.

Sorry for the noise. I should have checked.

Cheers

robert
 
R

Robert Dober

well seems you have to use my code then, it depends on a "feature"
Matz has put deliberately into the implementation of ancestor,
singletons are not included.
Does this fit your definition of singleton?
Robert
 
L

Lars Westergren

Robert Dober skrev:
well seems you have to use my code then, it depends on a "feature"
Matz has put deliberately into the implementation of ancestor,
singletons are not included.
Does this fit your definition of singleton?

Not sure.... Your code works good in irb and catches singletons
created as
class << self;self;end;

there. However, I still got the bug in Rails. I have done this-

marsh = class << Marshal; self; end
marsh.send :alias_method, "old_dump", "dump"
marsh.class_eval<<ENDOFSTRING
def dump(o);
STDERR.puts \"Problem class is a \" + o.class.name;
STDERR.puts o.inspect;
if o.class.is_singleton?;
puts \"it's a singleton!\";
else
puts \"not a singleton...\";
end;
old_dump(o);
end
ENDOFSTRING

And I get "not a singleton..." immediately followed by the exception.
The "problematic" object I think is the :session hash object, or rather
an object stored inside it. Either I'm looking in the wrong place, or I
need to traverse the object graph examening each object in array/hash.

Is there a library available for that?

I wish I could paste the inspect string for you people, but it is
several pages long and contains personal information.

Thanks again,
Lars
 
R

Robert Dober

Robert Dober skrev:

Not sure.... Your code works good in irb and catches singletons
created as
class << self;self;end;

there. However, I still got the bug in Rails.
OMG Rails, what do they do my Ruby? ;)
But I think it is Marshal, are you sure that it is the singleton which
causes problems?
AFAIK there are other things which make objects not serializable,
gotta find some time to look into this...
I have done this-

marsh = class << Marshal; self; end
marsh.send :alias_method, "old_dump", "dump"
marsh.class_eval<<ENDOFSTRING
def dump(o);
STDERR.puts \"Problem class is a \" + o.class.name;
STDERR.puts o.inspect;
if o.class.is_singleton?;
puts \"it's a singleton!\";
else
puts \"not a singleton...\";
end;
old_dump(o);
end
ENDOFSTRING

And I get "not a singleton..." immediately followed by the exception.
The "problematic" object I think is the :session hash object, or rather
an object stored inside it. Either I'm looking in the wrong place, or I
need to traverse the object graph examening each object in array/hash.

Is there a library available for that?

I wish I could paste the inspect string for you people, but it is
several pages long and contains personal information.
hmm maybe you can get us some condensed info, but did you check the
RDoc for what could raise the TypeError in dump?

Cheers
Robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top