Monkeypatch для двигателей в Rails

Во-первых: да, мартышкиный патч это плохо, чувствую себя уже грешником. Но в данном случае другого решения я не нашел.

Ситуация:

Engine 1 (Alchemy-CMS): Предоставляет модель страницы, которая содержит несколько элементов.

Движок 2 (мой Alchemy-Contentable): Должен обеспечивать способ привязки этих элементов к любому ресурсу (= модели), который вам нравится.

Цель состоит в том, чтобы дать ресурсу возможности cms, как у Alchemy, что означает добавление таких элементов, как заголовки, абзацы, изображения, видео...

На "странице-слое" все нормально. Я создал миксин для модели, которая идентифицирует себя как содержательную по отношению к элементу.

Я хочу оставаться как можно ближе к алхимии, и поэтому наследование от элемента не вариант (новая таблица базы данных, новые связанные модели...). Таким образом, исправление обезьяны здесь кажется адекватным (все еще хакерским, но на этот раз я в порядке).

Проблема:

Как мне успешно исправить классы одного движка из другого движка? Когда я пытаюсь открыть классы, как обычно, он жалуется, что не находит константу. Вероятно, это связано с ленивой загрузкой классов.

Что работает:

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

но это кажется подверженным ошибкам, особенно при доступе к недавно определенному сообщению из миксина (например, Alchemy::Element.my_new_method в model_mixin, который включен в модель вашего приложения)

Была ли у кого-то подобная ситуация раньше? Есть выходы? По крайней мере, «надежный» способ создавать и перезаписывать некоторые методы в классах движка и вызывать их внутри миксина?


person Marc    schedule 29.02.2012    source источник


Ответы (1)


Решение состоит в том, чтобы исправить модель 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, который гарантирует, что исходный класс будет расширен и не будет перезаписан вашим файлом.

Дополнительную информацию см. в этой записи в блоге.

person Luc    schedule 27.08.2019