2015-01-30 5 views
2

У меня есть несколько файлов. В одном я хотел бы расширить некоторые классы 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. Есть ли способ сделать это, или мне нужно использовать расширение глобального класса без оболочки модуля?

ответ

4

Вы ищете особенность, как refinements:

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 

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

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

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

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

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

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

другой путь обезьяны заплат Array globaly, который не рекомендуется.

+0

Это замечательно! К сожалению, я должен сделать это в приложении Rails 3, которое использует Ruby 1.9.3. Есть ли способ, или мне нужно расширить класс по всему миру? – sakovias

+0

@sakovias Я отредактировал свой ответ. –

+0

Отлично! Спасибо @Marek, я очень ценю ваш ответ! – sakovias

 Смежные вопросы

  • Нет связанных вопросов^_^