【问题标题】:Ruby symbol to classRuby 符号到类
【发布时间】:2010-11-17 03:52:12
【问题描述】:

Ruby 中有没有办法将符号或字符串转换为同名的类?

例如,如果我有一个类,例如

class Bob
  def talk
     puts "Hi, I'm bob"
  end
end

我在代码中其他地方的方法传递了一个符号:bob,我可以以某种方式将其转换为 Bob 类吗?也许像

b = :Bob.new
b.talk

或者有没有办法做类似的事情?

【问题讨论】:

    标签: ruby class transform symbols


    【解决方案1】:

    导轨

    仅适用于 Rails。

    带字符串:

    "Module".constantize #=> Module
    "Class".constantize #=> Class
    

    带符号:

    :module.to_s.classify.constantize #=> Module
    :open_struct.to_s.classify.constantize #=> OpenStruct
    

    如果您正在处理 多字 符号,那么您需要将 #classify 添加到链中以正确处理常量所有部分的大写。

    http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize

    【讨论】:

    • 对不起,我应该补充一点,这是 Rails 唯一的事情。
    • 如果您使用的是 Rails,这可能是最好的解决方案。
    • 该问题专门询问了符号和常量化在 Rails 中的 Symbol 类上不存在。答案应该是:Module.to_s.constantize
    【解决方案2】:

    在我的例子中,下面的两个例子都有效,但你也不要忘记命名空间:

      Object.const_get("ModuleName::#{class_model_name}")
    

      Kernel.const_get("ModuleName::#{class_model_name}").
    

    【讨论】:

      【解决方案3】:

      这是我在寻找包含模块/命名空间支持的类似内容时想到的:

      ['foo', 'bar'].inject {|r,e| "#{r.classify}::#{e.classify}"}.constantize
      

      生产

      => Foo::Bar
      

      但这需要 Rails,当然它只适用于数组包含多个元素的情况。

      这看起来很简单,所以我确定我错过了一些东西,有人愿意告诉我为什么这不是一个好方法吗?

      谢谢!

      【讨论】:

      • 您是否在回答中提出问题?耻辱! ;)
      • @JustinStolle,我不认为这是一个新问题,更多关于原始问题的指导? :)
      【解决方案4】:

      如果您想将 :foo_bar 变成 FooBar,我见过的任何解决方案都不起作用。如果这就是你要找的东西:

      :foo_bar.to_s.split("_").collect(&:capitalize).join.constantize
      => FooBar

      希望对某人有所帮助。

      【讨论】:

      • 这就是 'camelize' 的用途::foo_bar.to_s.camelize
      • @DaveSims camelize 是一个 ActiveRecord 扩展:api.rubyonrails.org/classes/ActiveSupport/…,尽管constantize 也是如此。
      • 是的,就像 Dan Frade 一样,我应该提到这一点。 :)
      【解决方案5】:

      有很多方法可以做到这一点。您缺乏上下文使得无法选择“最佳”方式。这里有一些方法。

      Kernel.const_get(:Bob)
      
      eval(:Bob.to_s)
      
      Kernel.const_get(:bob.to_s.capitalize)
      

      【讨论】:

      • 好吧,谢天谢地,我没有要求“最好”的方式,而只是一种方式...... ;)
      • 仅针对这种情况,如果Bob在模块People中定义并且你知道,你可以People.const_get(:Bob)
      【解决方案6】:
      class Bob
      end
      
      def create(name)
        return eval("#{name}.new")
      end
      
      b = create(:Bob)
      puts b.class
      

      【讨论】:

        【解决方案7】:

        NameSpace.const_get(classname) 将返回类对象(假设 classname 包含类的名称 - 如果它包含不是类的常量的名称,它将返回该常量的值)。顶层命名空间是Object,所以可以Object.const_get(:Bob).new

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-01
          • 2013-01-28
          • 2015-02-23
          • 2011-12-16
          • 1970-01-01
          • 2011-07-15
          • 2017-10-01
          • 2012-07-11
          相关资源
          最近更新 更多