Monailsypatch跨越Rails中的引擎

时间:2012-02-29 05:50:59

标签: ruby-on-rails ruby metaprogramming rails-engines monkeypatching

首先:是的,猴子补丁很糟糕,我已经感觉自己像个罪人了。但在这种情况下,我还没有找到另一种解决方案。

情况:

引擎1(Alchemy-CMS):提供包含多个元素的页面模型。

引擎2(我的Alchemy-Contentable):应该提供一种方法将这些元素绑定到您喜欢的任何资源(=模型)。

目的是为资源提供像Alchemy这样的cms功能,这意味着添加标题,段落,图片,视频等元素......

在“页面层”上一切都很好。我为一个模型创建了一个mixin,它标识了自己对元素的满足感。

我希望尽可能接近炼金术,因此继承元素不是一个选项(新的数据库表,新的相关模型......)。 所以猴子补丁在这里似乎已经足够了(仍然是hacky,但这次我觉得我很好)。

问题:

如何从另一个引擎成功修补一个引擎的类? 当我试图像往常一样重新开课时,它抱怨不要找到常数。可能这是由于类的延迟加载。

有效的是:

config.after_initialize do
  Alchemy::Admin::ElementsController.send(:include, AlchemyContentable::ElementsControllerMixin)
  Alchemy::Admin::ElementsController.send(:before_filter, :load_contentable_to_page, :only => [:index, :new, :create])
end

但这似乎容易出错,尤其是在从mixin访问新定义的消息时(例如模型_mixin中的Alchemy :: Element.my_new_method,它包含在您应用的模型中)

之前有人有这种情况吗?有什么方法吗?至少是一种'可靠'的方法来创建和覆盖引擎类中的某些方法并在mixin中调用它们?

1 个答案:

答案 0 :(得分:0)

一种解决方案是以以下方式猴子化Alchemy :: Page模型:

require File.expand_path('../../app/models/alchemy/page', Alchemy::Engine.called_from)

module Alchemy

  class Page < BaseRecord

    # Your code goes here...

  end
end

请注意 require 语句,该语句将确保原始类得到扩展并且不会被文件覆盖。

请参见this blog post for more context