Доступ к основным помощникам приложения при перегрузке Rails Engine View/Layout
Я создал простой Rails Engine, чтобы предоставить некоторую общую функциональность (фотогалерею) для приложения. Я хочу иметь возможность переопределить стандартную частицу _header, чтобы меню галереи соответствовало моему главному приложению. В моем заголовке я вызываю помощника, который является частью application_helpers (основного приложения), но я продолжаю получать ошибки "undefined". Из того, что я могу сказать, основное приложение application_helpers не включается (очевидно), когда я переопределяю макет приложения для двигателей или его частичные.
Итак, мой вопрос: как переопределить представление ядра в главном приложении и получить доступ к основным вспомогательным методам приложения? Мне все равно нужен доступ к помощникам двигателя, а также не для того, чтобы испортить функциональность двигателя.
Нужно ли также переопределять контроллеры? кажется, очень много, чтобы получить помощников.
Спасибо
Rails 3.1.3
Ответы
Ответ 1
Посмотрите это сообщение в блоге: http://www.candland.net/2012/04/17/rails-routes-used-in-an-isolated-engine/
Автор добавляет определение method_missing к помощнику приложения для доступа к помощникам родительских приложений.
/config/initializers/blogit.rb
module Blogit
module ApplicationHelper
def method_missing method, *args, &block
puts "LOOKING FOR ROUTES #{method}"
if method.to_s.end_with?('_path') or method.to_s.end_with?('_url')
if main_app.respond_to?(method)
main_app.send(method, *args)
else
super
end
else
super
end
end
def respond_to?(method)
if method.to_s.end_with?('_path') or method.to_s.end_with?('_url')
if main_app.respond_to?(method)
true
else
super
end
else
super
end
end
end
end
Ответ 2
Попробуйте включить основные вспомогательные методы приложения. Например:
class MyEngineClass
include ApplicationHelper
#...
end
Возможно, вам придется сначала потребовать файл, хотя я бы ожидал, что Rails правильно найдет его в этом случае.
После того, как ApplicationHelper включен, вы должны иметь возможность напрямую использовать эти помощники в контроллере.
Похоже, вы можете вызвать ClassName.helper("application")
для большого количества классов Rails - не уверены, что это будет работать здесь.
Ответ 3
попробуйте создать помощника в вашем приложении с тем же именем помощника в вашем движке, чтобы переопределить методы поддержки хелпера.
Я нашел эту дискуссию, особенно проницательную. Есть также некоторые интересные идеи в Документах API Rails Engine в разделе Изолированные помощники двигателя.
Ответ 4
Двигатели должны быть независимы от основного приложения, поэтому вы не можете получить доступ к своим помощникам из Engine.
Однако есть хакерские способы предоставить вашему движку доступ к помощникам основного приложения. Вот как я это сделал:
# In the main app
# initializers/share_helpers_path_with_engine.rb
PhotoGallery::Engine.class_eval do
paths["app/helpers"] << File.join(File.dirname(__FILE__), '../..', 'app/helpers')
end
Вам нужно, конечно, изменить PhotoGallery
на фактическое имя вашего класса двигателя.
Не стесняйтесь взглянуть на документацию по двигателям (раздел о путях): http://edgeapi.rubyonrails.org/classes/Rails/Engine.html
Ответ 5
Отказ от ответственности: я использовал это решение только в Rails 3.2.
Если в вашем движке у вас есть стандартный заголовок vendor/gems/my_gallery_engine/app/views/application/_header.html.erb.
Затем переопределите его в главном приложении, создав индивидуальное частичное приложение /views/application/ _header.html.erb.
Функция переопределения работает, потому что путь поиска шаблона просмотра Rails (по умолчанию) начинается с основного каталога приложений app/views, а затем выполняется поиск по приложениям/представлениям движков > в порядке загрузки.
Все ваши основные помощники приложения будут доступны в частичном.