如何获取 Ruby 类的名称?

发布于 2024-07-19 03:40:16 字数 339 浏览 9 评论 0原文

如何从 ActiveRecord 对象获取类名?

我有:

result = User.find(1)

我尝试过:

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

我只需要字符串中的类名(在本例中为User)。 有办法吗?

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

鸠魁 2024-07-26 03:40:16

您想要在对象的类上调用 .name

result.class.name

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

result.class.name
记忆里有你的影子 2024-07-26 03:40:16

这是从 Daniel Rikowski 和 pseidemann 的评论中摘录的正确答案。 我厌倦了必须通过评论来找到正确的答案...

如果您使用 Rails (ActiveSupport):

result.class.name.demodulize

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

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

Here's the correct answer, extracted from comments by Daniel Rikowski and pseidemann. I'm tired of having to weed through comments to find the right answer...

If you use Rails (ActiveSupport):

result.class.name.demodulize

If you use POR (plain-ol-Ruby):

result.class.name.split('::').last
苏大泽ㄣ 2024-07-26 03:40:16

result.class.to_sresult.class.name 都可以工作。

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

娇纵 2024-07-26 03:40:16

如果您想从类方法内部获取类名,class.nameself.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!

If you want to get a class name from inside a class method, class.name or self.class.name won't work. These will just output Class, since the class of a class is Class. Instead, you can just use name:

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

Foo::Bar.say_name

output:

I'm a Foo::Bar!
旧城空念 2024-07-26 03:40:16

在 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 中,正如其他人提到的,您可以使用 demodulize< /code>字符串上的方法,由 Active Support 添加。 它从字符串中的常量表达式中删除模块部分。

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

在内部,此方法调用 demodulize 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

将路径参数转换为字符串后,它使用 Ruby 的 rindex 函数。 如果存在,则返回剩余的子字符串。 否则,它返回原始字符串。 array[n..-1] 表达式返回从 n 到字符串中最后一个字符的子字符串。

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

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

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

葬花如无物 2024-07-26 03:40:16

就我而言,当我使用 result.class.name 之类的内容时,我得到了类似 Module1::class_name 的内容。 但如果我们只想要class_name,请使用

result.class.table_name.singularize

In my case when I use something like result.class.name I got something like Module1::class_name. But if we only want class_name, use

result.class.table_name.singularize

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文