【问题标题】:Ruby on Rails extending a gem's class and changing its inheriting classRuby on Rails 扩展 gem 的类并更改其继承类
【发布时间】:2018-08-16 09:53:20
【问题描述】:

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

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

我在我的应用程序中创建了一个新类 - 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)

根据我的理解,这基本上意味着 gem 的印象类定义与我自己对该类的扩展之间存在冲突。

任何人都可以帮助找出一种方法,我可以更改 Impression 类继承类,同时仍然保持类的行为并使我的服务器正常运行吗?

PS:所有这些的目标是将展示数据写入不同的数据库(日志数据库)而不是主应用程序数据库。为此,我需要建立与日志数据库的连接,但如果直接在 Impression 类中执行此操作,它将炸毁我的数据库连接池,如下面的链接所示:

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

这就是我需要抽象 LogsBase 类的原因。

任何帮助将不胜感激。

【问题讨论】:

标签: ruby-on-rails ruby rubygems extending-classes impressionist


【解决方案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

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

    • 关于建议 2:将在 module 中调用建立连接方法并将其包含在我的 model 中将实现防止达到池阈值的相同目标好像我使用继承?我不确定它会......(或者我该如何测试它)
    • @zivaricha 如果继承有效,则模块包含将有效。如果继承失败,那么模块包含也会失败。我也不完全确定如何最好地对其进行测试,但我至少可以说行为将是相同的。
    • @zivaricha 对此进行扩展。如果 Impression 是唯一以这种方式调用建立连接的类,则无需担心池。您是否还有其他类可以继承自 LogsBase
    • @TomLord Gotcha,我试试看。 Engineermnky,我有 8 个其他类以与印象类假设的方式相同的方式建立与不同数据库的连接。所有这些课程都经常受到打击,这就是我担心的原因。
    • @zivaricha 如果您还有 8 个其他类具有这种行为,那么无论如何都更有理由将它移到模块中! :)
    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 2014-03-15
    • 2013-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    相关资源
    最近更新 更多