I have a module that provides logging functionality. Some classes extend
it, others include
it. As part of the logging, I pass in a class name.
If I do this:
global_logger.call(level, self, msg)
It could log either:
WARN -- Some::Class: some msg
OR
WARN -- #<Some::OtherClass:0x00007fdc04907710>: some msg
based on if the module was extended or included. I can call self.class
instead, but then the the other one turns into Class
.
Is there a way to get a class name(without the #<...:0x00007fdc04907710>
), given that you don't know if self
is a class or an instance?
CodePudding user response:
There are a number of things you could do, but one of the easiest is probably to see if the passed object is a class before trying to extract other information about it. For example:
Object.kind_of? Class #=> true
Object.new.kind_of? Class #=> false
You can then decide what methods are appropriate to call based on whether or not it's a class. For example:
p Object.new.class.name #=> "Object"
P Object.name #=> "Object"
CodePudding user response:
We know that, for a given module M
, you can determine if a class C
has included M
by writing
C.included_modules.include?(M)
To determine if a class C
has extended M
you may execute
C.singleton_class.included_modules.include?(M)
because extending a module to a class is equivalent to including the same module to the class' singleton class.
See Module#included_modules and Object#singleton_class.
Here is an example.
module M
def m; end
end
class C
extend M
end
a = C.singleton_class.included_modules
#=> [M, Kernel]
a.include?(M)
#=> true