Почему открытие класса String внутри файла не работает?

Я знаю, что могу открыть класс как String и добавить функциональность. Этот тестовый скрипт 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"

Однако внутри файла тор это не работает. Например 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)

Почему и как это исправить?

1 ответ

Решение

Зачем?

Проблема здесь:

Thor::Sandbox.class_eval(content, path)

Таким образом, он берет ваш файл и загружает его в пустой модуль, таким образом, помещая его в пространство имен (не уверен, что квалифицируется как "песочница").

class Thor
  module Sandbox
  end
end

Итак, ваша попытка открыть String на самом деле создает новый класс Thor::Sandbox::String о котором никто не знает. Строковые литералы продолжают создавать экземпляры String,

Как исправить?

Откройте строку верхнего уровня вместо создания вложенной.

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

Бонусный контент

Тор на самом деле уже включает в себя метод верблюжьей струны, Thor::Util.camel_case:

  def camel_case(str)
    return str if str !~ /_/ && str =~ /[A-Z]+.*/
    str.split("_").map { |i| i.capitalize }.join
  end
Другие вопросы по тегам