JP Richardson
JP Richardson

Reputation: 39385

Class Method to 'Know' Class Name in Ruby?

I want an inherited ruby class to 'know' its class name via a class method. This is best illustrated by a contrived example:

class Parent
  def self.whoami
    ??
  end
end

class Child < Parent
  #No code should be needed.
end

So I should be able to call:

Parent.whomai

and expect a return of "Parent" I should then be able to call:

Child.whoami

and expect a return of "Child" I have a feeling that in conventional languages this might not be possible. But Ruby's metaprogramming model has amazed me before. Any thoughts? Thanks in advance.

Upvotes: 16

Views: 13172

Answers (4)

J&#246;rg W Mittag
J&#246;rg W Mittag

Reputation: 369428

The method to get the name of a class (module, actually) is just Module#name. There's no need to write your own:

Parent.name # => 'Parent'
Child.name  # => 'Child'

However, in Ruby, there really is no such thing as a "class name" as there is in some other languages. In Ruby, a class is simply an object like any other object which gets assigned to a variable like any other variable.

All the Module#name method does is loop through all the constants in the system and check whether the module has been assigned to any one of them, and return that constant's name or nil if it cannot find any.

So, just like any other object, the "name" of a class is really nothing but whatever variable you use to refer to it.

Example:

foo = Class.new
foo.name # => nil

Now, the "name" of the class is foo. However, Module#name returns nil, because foo is not a constant.

bar = foo
bar.name # => nil

Now, the "name" of the class is both foo and bar, but Module#name obviously still returns nil.

BAZ = foo
foo.name # => 'BAZ'

Now, since the class has been assigned to a constant, that constant's name will be considered that class's name …

BAZ = nil
foo.name # => 'BAZ'

… even after the constant has been assigned to something different and …

QUX = foo
QUX.name # => 'BAZ'

… even after the class has been assigned to a different constant.

Module#to_s uses Module#name if it is not nil, so, to print the name of a class, you simply do

puts Parent

There's really absolutely no need for all the complex fluff in the other answers.

Upvotes: 15

Taimoor Changaiz
Taimoor Changaiz

Reputation: 10684

Suppose you class:

class ABC
 def self.some_method
   self.name #it will return 'ABC'
   self.name.constantize #it will return ABC
 end
end 

Upvotes: 2

horseyguy
horseyguy

Reputation: 29895

A Class Method is a method where the CLASS is the receiver, so to find the object upon which the method is invoked (what you appear to be trying to do here) simply inspect the value of self.

class Parent
  def self.whoami
    self
  end
end

class Child < Parent
end

puts Parent.whoami #=> Parent
puts Child.whoami #=> Child

Upvotes: 24

Adam Lassek
Adam Lassek

Reputation: 35505

Isn't that what Parent.class will tell you?

class Parent
  def self.whoami
    self.to_s
  end
end

class Child < Parent
end

> Parent.whoami
=> "Parent"
> Child.whoami
=> "Child"

Upvotes: 4

Related Questions