Как обезьяна пропатчить класс с помощью модуля?

У меня есть несколько файлов. В одном я хотел бы расширить некоторые классы Ruby, например

module Stylable
  class Array
    def styled
      "\n" << "*"*72 << self.to_s << "*"*72 << "\n"
    end
  end
end

В другом файле я определяю класс и смешиваю в своем пользовательском модуле.

require './stylable'

class Printer
  include Stylable

  def initialize(object)
    @object = object
  end

  def print
    puts @object.styled
  end
end

Printer.new([1,2,3]).print

По какой-то причине я не могу использовать свой обычай Array#styled метод:

$ ruby printer.rb 
printer.rb:10:in `print': undefined method `styled' for [1, 2, 3]:Array (NoMethodError)
  from array_printer.rb:14:in `<main>'

Что я делаю неправильно?

Изменить: Хотя решение из @MarekLipka ниже работает в Ruby 2+. Я должен сделать это на Ruby 1.9.3 / Rails 3. Есть ли способ сделать это, или я должен использовать глобальное расширение класса без оболочки модуля?

1 ответ

Решение

Вы ищете такую ​​функцию, как уточнения:

stylable.rb:

module Stylable
  refine Array do
    def styled
      "\n" << "*"*72 << self.to_s << "*"*72 << "\n"
    end
  end
end

printer.rb:

require './stylable'
class Printer
  using Stylable
  # ...
end
Printer.new([1,2,3]).print

Преимущество использования доработок заключается в том, что этот обезьян-патч работает только в Printer класс, так что с меньшей вероятностью что-то сломается.

Причина, по которой ваш первоначальный подход не работает, заключается в том, что вместо исправления обезьян ::Array класс, вы реализовали новый Stylable::Array класс (обратите внимание на пространство имен).

Если вы используете Ruby < 2.0, и вы не хотите использовать monkey-patch Array глобально вы можете создать собственный класс, который наследуется от массива:

class StylableArray < Array
  def styled
    "\n" << "*"*72 << self.to_s << "*"*72 << "\n"
  end
end

и использовать его в своем Printer файл:

Printer.new(StylableArray.new([1,2,3]))

Другой способ - исправление обезьян Array глобально, что не рекомендуется.

Другие вопросы по тегам