Ruby on Rails расширяет класс гема и изменяет его наследующий класс

У меня есть веб-приложение, построенное на Ruby on Rails. В этом приложении очевидно использовать разные драгоценные камни. Я дошел до того, что я хочу расширить некоторые классы гемов и добавить к ним методы.

Теперь у меня есть сценарий использования, в котором я хочу расширить класс гема, но вместо добавления методов я хочу изменить его наследующий класс, например, возьмем импрессионистский гем:

Iv создал новый класс в моем приложении - app/models/impression.rb

class Impression < ActiveRecord::Base
  establish_connection(ENV[App_LOGS_DB'])
end

я хочу изменить Наследование, чтобы использовать мой собственный класс с именем LogsBase

class Impression < LogsBase
end

класс LogsBase определяется следующим образом:

class LogsBase < ActiveRecord::Base
  establish_connection ENV['APP_LOGS_DB']
  self.abstract_class = true
end

При попытке запустить сервер возникает следующее исключение:

/gems/impressionist-1.6.1/lib/impressionist/models/active_record/impression.rb:5:in `<main>': superclass mismatch for class Impression (TypeError)

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

Может кто-нибудь помочь, пожалуйста, выяснить, как я могу изменить класс наследования класса Impression, сохраняя при этом поведение класса и обеспечивая правильную работу моего сервера?

PS: цель всего этого - записать данные о впечатлениях в другую базу данных (logs db), а не в основное приложение db. чтобы сделать это, мне нужно установить соединение с журналами базы данных, но если я сделаю это напрямую в классе Impression, он взорвет мой пул соединений с БД, как указано в следующей ссылке:

https://www.thegreatcodeadventure.com/managing-multiple-databases-in-a-single-rails-application/

Вот почему мне нужен абстрактный класс LogsBase.

Любая помощь будет оценена.

2 ответа

Отказ от ответственности: не делайте этого!

Единственный способ, которым я могу придумать, - это неприятный хак, ни надежный, ни надежный, который не совместим с более новыми версиями вашего внешнего драгоценного камня. Поскольку Ruby не позволяет переопределять предки классов, вы можете (но, пожалуйста, не делать):

  1. захватить содержание оригинала /gems/impressionist-1.6.1/lib/impressionist/models/active_record/impression.rb файл.
  2. скопируйте его в свой /blah/foo/impression,
  3. сделать ваш класс загруженным impressionist/models/active_record/impression в явном виде.
  4. во второй строке файла сбрасывается оригинальный класс.

Что-то вроде этого:

require 'impressionist/models/active_record/impression'

Object.send :remove_const, 'Impression'

class Impression < LogsBase
  # ORIGINAL CONTENT OF THIS FILE
end

Нет (разумного) способа переопределить базовый класс в ruby. Это возможно, но только через странные хаки.

Я бы предложил выбрать один из двух маршрутов здесь:

  1. Разветвите библиотеку и сделайте базовый класс настраиваемым (с обратной совместимостью).
  2. Не делай этого по наследству. Вместо этого положите establish_connection ENV['SPLACER_LOGS_DB'] в модуль, и include это в классе.

Я был бы склонен использовать вариант 2 на данный момент, так как это быстрый / простой обходной путь, который должен хорошо сочетаться с остальной частью приложения.

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