为什么打开 String class inside thor 文件不起作用?

Why is opening String class inside thor file not working?

我知道我可以像 String 一样打开 class 并添加功能。这个测试脚本 camelize.rb 工作得很好。

#!/usr/bin/env ruby
class String
  def camelize
    self.split("_").map(&:capitalize).join
  end
end

class Test
  def test
    p "test_me".camelize
  end
end

Test.test

打印 "TestMe"

但是在 thor 文件中这不起作用。例如。 test.thor

p "TEST ONE"
class String
  p "TEST TWO"
  def camelize
    self.split("_").map(&:capitalize).join
  end
end

class Test < Thor
  p "TEST THREE"
  desc "camel", "A test"
  def camel
    p "test_me".camelize
  end
end

正在通过 thor install test.thor、运行

安装
$ thor test:camel
"TEST ONE"
"TEST TWO"
"TEST THREE"
/Users/Kassi/.thor/ba3ea78d7f807c4c13ec6b61286788b5:13:in `camel': undefined method `camelize' for "test_me":String (NoMethodError)

为什么以及如何解决?

为什么?

问题是here

Thor::Sandbox.class_eval(content, path)

所以它所做的是获取您的文件并将其加载到 empty module 中,从而为其命名空间(不确定是否符合 "sandboxing")。

class Thor
  module Sandbox
  end
end

因此,您尝试重新打开 String 实际上创建了一个新的 class Thor::Sandbox::String,但没人知道。字符串文字继续创建 String.

的实例

如何修复?

打开顶级字符串而不是创建嵌套字符串。

class ::String
  def camelize
    self.split("_").map(&:capitalize).join
  end
end

奖金内容

Thor 实际上已经包含了驼峰化字符串的方法,Thor::Util.camel_case:

  def camel_case(str)
    return str if str !~ /_/ && str =~ /[A-Z]+.*/
    str.split("_").map { |i| i.capitalize }.join
  end