【问题标题】:Classify a Ruby string对 Ruby 字符串进行分类
【发布时间】:2010-11-01 18:59:55
【问题描述】:

我有一个创建类的程序,如下所示:

  MyClass = Class.new do
    def initialize; end
    # ...
  end

但我想从一个字符串中动态命名 MyClass。因为它是一个类的名称,所以我想对该字符串进行分类,例如(感谢 Rails 方法):

  "hello_world".classify # => "HelloWorld"

我不知道在纯 Ruby 中是否有这样的方法。

谢谢

【问题讨论】:

    标签: ruby string metaprogramming


    【解决方案1】:

    不,没有。这是String reference page

    你可以这样做:

    "hello_world".split('_').collect!{ |w| w.capitalize }.join
    

    您可以通过重新分类 String 类轻松实现这一点。

    但是,如果您出于某种原因使用 Rails,为了方便起见,会添加 classify 以及 underscore 方法。我相信它仍在 Rails 3 中使用。

    【讨论】:

    • 很好的解决方案。它可以(在 MRI 1.8.7 及更高版本中)缩短为:hello_world".split('_').collect(&:capitalize).join
    • 啊,太好了!离开 Ruby 世界有一段时间了。感谢您的提示!
    • 感谢您的方法;我会用这个来改进我的 String 类 呵呵
    • 您可能会发现获取和使用 ActiveSupport 最简单。
    • @Mladen Jablanović - 感谢您的提示,对于大多数情况,使用 ActiveSupport 可能是一个好主意。但是,如果您只需要对单数 underscored_word 进行分类,那会增加一些臃肿;否则,它非常有用。
    【解决方案2】:

    不确定您的问题是否只是关于构造一个驼峰式字符串,还是关于为其分配一个新创建的类。因为,对于后者,你应该使用Module::const_set 方法:

    class_name = 'MyClass'
    #=> "MyClass"
    klass = Class.new do
      def foo
        "foo"
      end
    end
    #=> #<Class:0xa093a68>
    Object.const_set class_name, klass
    #=> Module::MyClass
    MyClass.new.foo
    #=> "foo"
    

    【讨论】:

    • 这就是我认为他想要的。
    • 谢谢,这就是我想做的 Mladen。还有这个版本对我来说没问题: Object::const_set(class_name.intern, Class::new { def foo; "foo"; end }
    • 我很好奇这会有什么好处?如果类名是动态的,并且您想编写额外的代码来调用新创建的类,并且在编写代码时使用您不知道的名称......那么您打算如何使用这个新类? ?
    • @grail:你是在问const_set,还是用它来动态创建命名类?后者只是类成为 Ruby 中一流对象的结果。
    • @grail:这是 OP 的问题。我刚刚回答了他的问题。也许他知道类的名称,但在运行前不知道它的定义。也许有几个类,它们的含义可以动态确定。也许这个问题纯粹是学术性的,并不打算在实际代码中使用。谁知道呢。
    【解决方案3】:

    如果您只想从字符串名称访问类,而不是从字符串定义它,您也可以使用:

    MyClass = Class.new do
        def test; end
        # ...
    end
    "MyClass".constantize.test # => what you wanted ?
    

    【讨论】:

      【解决方案4】:

      这是很久以后的事了,但我正在经历这个过程并扩展 mway 的答案我正在使用这个:

      class String
        def classify
          self.split('/').collect do |c|
            c.split('_').collect(&:capitalize).join
          end.join('::')
        end
      end
      

      这将允许您将命名空间添加到字符串。所以:

      "api/post_comments".classify
      => "Api::PostComments" 
      

      【讨论】:

        猜你喜欢
        • 2013-08-29
        • 2016-10-27
        • 1970-01-01
        • 1970-01-01
        • 2011-05-09
        • 2021-01-04
        • 1970-01-01
        • 2014-04-23
        • 2010-12-15
        相关资源
        最近更新 更多