Открытые занятия в модуле

Я знаю, что могу выполнить следующее, чтобы добавить методы в класс String

class String
  def do_something
    puts self.size
  end
end

var = "test"
var.do_something

и это вернется 4

Я хочу иметь возможность иметь модуль с функцией, которая принимает строку, но иметь возможность вызывать do_something метод для этой строки (см. ниже, например) - возможно ли это?

РЕДАКТИРОВАТЬ: Добавлен пример кода, который не работает

module TestModule
  class String
    def do_something
      puts self.size
    end
  end

  def self.test(str)    
    str.do_something
  end
end

Это дает ошибку: undefined method 'do_something' for "hello":String (NoMethodError)

2 ответа

Решение

Как написан ваш код, вы определяете новый класс с именем TestModule::String. Если вы хотите изменить встроенный класс Ruby String, вам нужно использовать полное имя String (с ""::"), если вы хотите сохранить объявление внутри модуля.

module TestModule
  class ::String
    def do_something
      puts self.size
    end
  end

  def self.test(str)  
    str.do_something
  end
end

Добавление "::" говорит Ruby, что нужный вам класс String не является частью TestModule.

Вероятно, будет проще объявить String вне TestModule в том же файле.

Если вы не хотите загрязнять глобальный класс String, вы можете просто изменить конкретный экземпляр String, к которому вы хотите добавить метод.

module TestModule
  def self.test(str)  
    do_somethingify!(str)
    str.do_something
  end

  def self.do_somethingify!(str)
    unless str.respond_to? :do_something
      str.instance_eval do
        def do_something
          puts size
        end
      end
    end
  end      
end          

Может быть, это?

module TestModule
  module_function
  def test(str)
    str.instance_eval{doSomething}
  end
end

Test.test(str)

Изменить Изменено из-за изменения в вопросе

Просто поместите определение doSomething снаружи TestModule учебный класс.

class String
  def doSomething
    puts size
  end
end

module TestModule
  module_function
  def test(str)  
    str.doSomething
  end
end
Другие вопросы по тегам