irb(main):001:0> class Foo
irb(main):002:1> def self.singleton_class
irb(main):003:2> return class << self; self; end
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> sc = Foo.singleton_class
=> #<Class:Foo>
How can I get class that the singleton class is a singleton class of?
(and is there a name for this?)
class << sc
def un_singleton_class
# ?
end
end
sc.un_singleton_class #=> Foo
I know only of the brute-force solution:
irb(main):011:0> sc = Foo.singleton_class
=> #<Class:Foo>
irb(main):012:0> class Class; def singleton_class; class << self; self; end; end; end
=> nil
irb(main):013:0> ObjectSpace.each_object(Class) { |c| break c if c.singleton_class == sc }
=> Foo
irb(main):001:0> class Foo
irb(main):002:1> def self.singleton_class
irb(main):003:2> return class << self; self; end
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> sc = Foo.singleton_class
=> #<Class:Foo>
How can I get class that the singleton class is a singleton class of?
(and is there a name for this?)
--
we can deny everything, except that we have the possibility of being better. simply reflect on that.
h.h. the 14th dalai lama
I have a script that queries servers in our environment to assist with
patch-levels etc... I am having an issue and need to backtrace which
class called my class.
What I currently have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}\n"
What I would like to have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}, called from #{callingClass}\n"
irb(main):001:0> class Base; end
=> nil
irb(main):002:0> class Derived < Base; end
=> nil
irb(main):003:0> sc = class << Derived; self; end
=> #<Class:Derived>
irb(main):004:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
=> 1
irb(main):005:0> sc = class << Base; self; end
=> #<Class:Base>
irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
Base
=> 2
···
On Thu, Sep 18, 2008 at 06:07:29AM +0900, Thomas B. wrote:
I have a script that queries servers in our environment to assist with
patch-levels etc... I am having an issue and need to backtrace which
class called my class.
What I currently have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}\n"
What I would like to have
print "\nCollectData Failed 2: in needDate != yes & package == none
#{hostName}, called from #{callingClass}\n"
If I understand correctly what you want, try using the command +caller+
to get what you want. It returns an array with current stack trace.
Does doing this allow a class to be garbage-collected but allow its
singleton class to stick around?
yes. you don't have to worry about the object being stale when this is called since the singleton class if owned by the object it's looking up by id
Probably better to use define_method with a block in this case.
i was worried about the gc. also you use define_method you have to get into the singleton class of a singleton class - which starts to get yucky. 'def' works at the instance scope so my approach seemed safer and simpler. but i think define_method could be made to work...
irb(main):001:0> class Base; end
=> nil
irb(main):002:0> class Derived < Base; end
=> nil
irb(main):003:0> sc = class << Derived; self; end
=> #<Class:Derived>
irb(main):004:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
=> 1
irb(main):005:0> sc = class << Base; self; end
=> #<Class:Base>
irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
Base
=> 2
good catch! but this should work then:
irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c if
sc.equal?(class << c; self; end) }
Base
=> 2
i'll update my implementation in ruby-nuggets tomorrow (moving the
check that i'm doing anyway inside the loop; thanks).
cheers
jens
···
On Thu, Sep 18, 2008 at 06:07:29AM +0900, Thomas B. wrote:
irb(main):006:0> ObjectSpace.each_object(sc) { |c| p c }
Derived
Base
=> 2
You're right. I was thinking about "regular" object's eigenclasses and
not eigenclasses of classes, and with them I think my solution will
work. My mistake.
But now I finally understand the remark I read somewhere and ignored,
because I didn't think it was important. It said that the "method
lookup" for classes includes eigenclasses of their ancestors.
Now I'm wondering if it is possible to construct such an object that
belong to a foreign eigenclass and not be a class itself. In other
words, how to make my code fail even though a is not a Class. Any ideas?
TPR.
···
On Thu, Sep 18, 2008 at 06:07:29AM +0900, Thomas B. wrote:
Now I'm wondering if it is possible to construct such an object
that belong to a foreign eigenclass and not be a class itself. In
other words, how to make my code fail even though a is not a
Class. Any ideas?
not sure what you mean by that. but it fails for the singleton
classes of objects like true, false, and nil (TrueClass, FalseClass,
and NilClass resp.), which can safely be special-cased. here's the
updated implementation:
# strictly speaking it belongs under Class,
# but i like to keep things together in this case
class Object
# raises TypeError if neither class nor module
ObjectSpace.each_object(self) { |obj|
return obj if self.equal?(obj.singleton_class)
}
# if we got here it can't be a singleton class
# or its singleton object doesn't exist anymore
raise TypeError
rescue TypeError
raise TypeError, 'not a singleton class'
end