简体   繁体   中英

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.

Engine 2 (my Alchemy-Contentable): Should provide a way to bind these elements to any resource (=model) you like.

Purpose is to give the resource cms-capabilities like Alchemy has, that means adding elements like headings, paragraphs, pictures, videos...

On the "page-layer" everything is fine. I created a mixin for a model that identifies itself as contentable towards the element.

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).

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)

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?

A solution is to monkey-patch the Alchemy::Page model in the following fashion:

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.

See this blog post for more context .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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