简体   繁体   English

Monailsypatch跨越Rails中的引擎

[英]Monkeypatch across Engines in Rails

First of all: Yes, monkey patching is bad, I'm feeling like a sinner already. 首先:是的,猴子补丁很糟糕,我感觉自己已经是个罪人了。 But in this case I haven't found another solution. 但在这种情况下,我还没有找到另一种解决方案。

Situation: 情况:

Engine 1 (Alchemy-CMS): Provides a page model that contains several elements. 引擎1(Alchemy-CMS):提供包含多个元素的页面模型。

Engine 2 (my Alchemy-Contentable): Should provide a way to bind these elements to any resource (=model) you like. 引擎2(我的Alchemy-Contentable):应该提供一种方法将这些元素绑定到您喜欢的任何资源(= model)。

Purpose is to give the resource cms-capabilities like Alchemy has, that means adding elements like headings, paragraphs, pictures, videos... 目的是为资源提供像Alchemy这样的cms功能,这意味着添加标题,段落,图片,视频等元素......

On the "page-layer" everything is fine. 在“页面层”一切都很好。 I created a mixin for a model that identifies itself as contentable towards the element. 我为一个模型创建了一个mixin,它标识了自己对元素的满足感。

I want to stay as close as possible to alchemy and therefore inheriting from element is not an option (new database-table, new associated models...). 我希望尽可能地保持炼金术,因此继承元素不是一个选项(新的数据库表,新的相关模型......)。 So monkey patching seems adequate here (still hacky, but I'm fine with it this time I guess). 所以猴子补丁在这里似乎已经足够了(仍然是hacky,但这次我猜它很好)。

Problem: 问题:

How do I successfully monkey-patch one engine's classes from another engine? 如何从另一个引擎成功修补一个引擎的类? When I try to reopen classes as usual it complains not to find the constant. 当我试图像往常一样重新开课时,它抱怨不要找到常数。 Probably this is due to lazy loading of classes. 可能这是由于类的延迟加载。

What works is: 有效的是:

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

but this seems to be error prone, especially when accessing a newly defined message from a mixin (like Alchemy::Element.my_new_method in model_mixin, which is included in your app's model) 但这似乎很容易出错,特别是在从mixin访问新定义的消息时(比如app_mixin中的Alchemy :: Element.my_new_method,它包含在你的app的模型中)

Has someone had a situation like this before? 以前有人有这种情况吗? Any ways out? 有什么方法吗? At least a 'reliable' way to create and overwrite some methods in the engine's classes and to call them inside a mixin? 至少是一种'可靠'的方法来创建和覆盖引擎类中的某些方法并在mixin中调用它们?

A solution is to monkey-patch the Alchemy::Page model in the following fashion: 解决方案是以下列方式对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

Note the require statement which will ensure that the original class is extended and not overwritten by your file. 请注意require语句,该语句将确保原始类被扩展而不会被文件覆盖。

See this blog post for more context . 有关更多上下文,请参阅此博客文章

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM