Как я могу расширить класс из драгоценного камня?

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

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

Как я могу установить гем, а затем добавить методы без конфликтов? В прошлом я переписывал методы, определенные в гемах (в частности, методы Devise), но никогда не сталкивался с необходимостью расширения самого класса.

1 ответ

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

Вероятно, это похоже на то, что вы сделали с Devise.

Так что, если у меня есть класс Bar в драгоценном камне, и это внутри модуля под названием Foo

# in the gem
module Foo
  class Bar
    def foobar
      'foobar!'
    end
  end
end

Чтобы добавить метод с именем baz к этому классу, без изменения исходного кода gem, затем в вашем приложении просто создайте новый файл, снова объявите класс внутри его модуля и начните добавлять вещи.

# in some other file in your app
module Foo
  class Bar
    def baz
      'foobar baz!'
    end
  end
end

 > f = Bar.new
 > f.foobar
=> 'foobar!'
 > f.baz
=> 'foobar baz!'

Поскольку в модуле может быть только одна копия класса с заданным именем, простое объявление класса снова добавляет функциональность к существующему классу.

Если вы хотите вместо этого дать новый класс baz метод без изменения функциональности всех Bar экземпляры объектов в вашем приложении, а затем расширить Bar вместо. Это будет иметь эффект, что ваш новый класс будет иметь все Bar функциональность, плюс новая функциональность, без изменения функциональности Bar случаи, которые вы можете использовать в другом месте в вашем приложении.

class NewClass < Foo::Bar
  def baz
    'foobar baz!'
  end
end

 > nc = NewClass.new
 > nc.foobar
=> 'foobar!'
 > nc.baz
=> 'foobar baz!'
Другие вопросы по тегам