0

我有一个基于 Ruby on Rails 的网络应用程序。在这个应用程序中显然使用不同的宝石。Iv 到了我想扩展一些特定 gem 的类并为其添加方法的地步。

现在我有一个用例,我想扩展 gem 的类,但是我不想添加方法,而是想更改它的继承类,让我们以印象派 Gem 为例:

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:所有这一切的目标是将印象数据写入不同的数据库(日志数据库)而不是主应用程序数据库。为此,我需要建立与日志数据库的连接,但如果直接在 Impression 类中执行此操作,它将炸毁我的数据库连接池,如下面的链接所示:

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

这就是为什么我需要抽象 LogsBase 类。

任何帮助将不胜感激。

4

2 回答 2

1

免责声明:不要那样做!

我能想到的唯一方法是一个讨厌的 hack,既不可靠,也不健壮,与新版本的外部 gem 不兼容。由于 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. 在文件的第二行unset original class

像这样的东西:

require 'impressionist/models/active_record/impression'

Object.send :remove_const, 'Impression'

class Impression < LogsBase
  # ORIGINAL CONTENT OF THIS FILE
end
于 2018-08-16T10:13:03.573 回答
1

没有(明智的)方法可以在 ruby​​ 中重新定义基类。这是可能的,但只能通过奇怪的黑客攻击。

我建议在这里采取两条路线之一:

  1. 分叉库,并使基类可配置(具有向后兼容性)。
  2. 不要通过继承来做到这一点。相反,放入establish_connection ENV['SPLACER_LOGS_DB']一个模块,并将include其放入类中。

我现在倾向于使用选项 2,因为它是一种快速/简单的解决方法,应该很适合应用程序的其余部分。

于 2018-08-16T13:24:18.197 回答