How do I get the name of a Ruby class?

Viewed 311323

How can I get the class name from an ActiveRecord object?

I have:

result = User.find(1)

I tried:

result.class
# => User(id: integer, name: string ...)
result.to_s
# => #<User:0x3d07cdc>"

I need only the class name, in a string (User in this case). Is there a method for that?

I know this is pretty basic, but I searched both Rails' and Ruby's docs, and I couldn't find it.

6 Answers

You want to call .name on the object's class:

result.class.name

Both result.class.to_s and result.class.name work.

In Ruby, you'd use the object.class.name method as follows.

module Bank
  class Account
  end
end

irb(main):005:0> account = Bank::Account.new
=> #<Bank::Account:0x0000000106115b00>
irb(main):006:0> account.class.name
=> "Bank::Account"
irb(main):008:0> account.class.name.split("::").last
=> "Account"

In Rails, as others mentioned, you can use the demodulize method on a string, which is added by Active Support. It removes the module part from the constant expression in the string.

irb(main):014:0> account.class.name.demodulize
=> "Account"

Internally, this method calls the demodulize class method on the ActiveSupport::Inflector class, passing itself as the argument.

# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 166
def demodulize
  ActiveSupport::Inflector.demodulize(self)
end

The Inflector.demodulize function does the same thing.

demodulize('ActiveSupport::Inflector::Inflections') # => "Inflections"
demodulize('Inflections')                           # => "Inflections"
demodulize('::Inflections')                         # => "Inflections"
demodulize('')                                      # => ""

However, its internal implementation is different than the simple version above.

# File activesupport/lib/active_support/inflector/methods.rb, line 228
def demodulize(path)
  path = path.to_s
  if i = path.rindex("::")
    path[(i + 2)..-1]
  else
    path
  end
end

After converting the path argument to a string, it gets the index of the last occurrence of :: using Ruby's rindex function. If it exists, then it returns the remaining substring. Otherwise, it returns the original string. The array[n..-1] expression returns the substring from n to the last character in the string.

Now I haven't done any benchmark studies to find why Rails uses this alternative approach using rindex (please comment if you know why), but as a code readability enthusiast, I like the first one using the split and last functions.

Source: How to Get an Object's Class Name in Rails

Related