如何从ActiveRecord对象中获得类名?

我有:

result = User.find(1)

我试着:

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

我只需要类名,在字符串中(在本例中为User)。有什么方法吗?

我知道这是非常基本的,但是我搜索了Rails和Ruby的文档,我没有找到它。


当前回答

在我的例子中,当我使用result.class.name之类的东西时,我得到了Module1::class_name之类的东西。但如果我们只需要class_name,则使用

result.class.table_name.singularize

其他回答

在Ruby中,您可以如下所示使用object.class.name方法。

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"

在Rails中,正如其他人提到的,您可以对字符串使用解调方法,该方法由Active Support添加。它从字符串中的常量表达式中删除模块部分。

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

在内部,该方法调用ActiveSupport::Inflector类上的解调类方法,并将自身作为参数传递。

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

Inflector.demodulize函数做同样的事情。

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

但是,它的内部实现与上面的简单版本不同。

# 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

在将path参数转换为字符串之后,它使用Ruby的rindex函数获得::最后一次出现的索引。如果它存在,则返回剩余的子字符串。否则,返回原始字符串。数组(n . .表达式返回从n到字符串的最后一个字符的子字符串。

现在我还没有做任何基准测试研究,以找出为什么Rails使用rindex这种替代方法(如果您知道原因,请评论),但是作为一个代码可读性爱好者,我喜欢第一个使用split和最后一个函数的方法。

来源:如何在Rails中获取对象的类名

在我的例子中,当我使用result.class.name之类的东西时,我得到了Module1::class_name之类的东西。但如果我们只需要class_name,则使用

result.class.table_name.singularize

如果你想从类方法内部获取类名,class.name或self.class.name将不起作用。这些只会输出Class,因为类的类是Class。相反,你可以只使用name:

module Foo
  class Bar
    def self.say_name
      puts "I'm a #{name}!"
    end
  end
end

Foo::Bar.say_name

输出:

I'm a Foo::Bar!

以下是正确答案,摘自Daniel Rikowski和pseidemann的评论。我厌倦了在评论中寻找正确答案。

如果你使用Rails (ActiveSupport):

result.class.name.demodulize

如果你使用POR (plain-ol-Ruby):

result.class.name.split('::').last

result.class。To_s和result.class.name工作。