Не найдены вспомогательные методы для монтирования Rails при маршрутизации из основного приложения
У меня есть модуль в виде монтируемого двигателя, установленного в главном приложении через
mount MyEngine::Engine, :at => '/myengine'
У меня все пространство имен находится в negine, и у движка есть свои представления в engine/app/views/myengine/
Все работает нормально, когда я запускаю сервер rails, затем пытаюсь получить доступ
локальный:3000/myengine
затем перейдите в корень основного приложения и вернитесь к движку по ссылке в индексном представлении основного приложения.
Однако, когда я запускаю сервер, перехожу к localhost:3000 и оттуда кликаю по ссылке на модуль движка, он пытается правильно получить представления, однако методы, содержащиеся в помощниках движка, выдают ошибку при вызове, так как они не определены.
Я на рельсах 4
2 ответа
Я использовал eager_load, чтобы загрузить монтируемый движок в его инициализированном в основном приложении приложении, и теперь все работает.
Myengine::Engine.eager_load!
Я тоже столкнулся с этой проблемой. Я определил ApplicationController
внутри моего двигателя и видел NoMethodError
когда я пытался использовать вспомогательные методы внутри одного из контроллеров моего двигателя.
Эта проблема
Код выглядел примерно так:
в my_engine/app/controllers/my_engine/application_controller.rb
module MyEngine
class ApplicationController < ActionController::Base
helper ApplicationHelper
end
end
в my_engine/app/controllers/my_engine/projects_controller.rb
module MyEngine
class ProjectsController < ApplicationController
def new
# some action code here
end
end
end
в my_engine/app/helpers/my_engine/application_helper.rb
module MyEngine
module ApplicationHelper
def translations_include_tag
javascript_include_tag "translations-#{I18n.locale}.js"
end
end
end
Если бы я перешел к маршруту в приложении host rails, а затем щелкнул ссылку, которая перешла на my_engine / projects / new, я бы получил NoMethodError
поговорка translations_include_tag
не существовало
Объяснение
Я думаю, что это произошло, потому что у приложения было два класса с одинаковым именем: ApplicationController
в MyEngine
а также ApplicationController
в приложении хоста. Когда первый маршрут за пределами двигателя посещается, Rails автоматически загружает ApplicationController
из хост-приложения. Это означает, что Rails ассоциирует главное приложение ApplicationController
с именем "ApplicationController". Когда вы переходите к my_engine/projects/new, Rails загружается лениво ProjectsController
который также наследует от ApplicationController
, Rails / ruby думает, что вы имеете в виду то же самое ApplicationController
он уже загружен, так что в действительности ProjectsController
заканчивается наследование от хост-приложения ApplicationController
вместо того, что в двигателе. Так как translations_include_tag
метод не определен в приложении хоста ApplicationController
Рубин поднимает NoMethodError
когда представление пытается вызвать это.
Решение
Я смог решить проблему, явно унаследовав от MyEngine
"s ApplicationController
:
в my_engine/app/controllers/my_engine/projects_controller.rb
module MyEngine
# changed from just plain 'ol ApplicationController
class ProjectsController < ::MyEngine::ApplicationController
def new
# some action code here
end
end
end
После исправления проблемы наследования NoMethodError
ушел.
В принятом ответе говорится, что нужно использовать энергичную загрузку, что также решит проблему, потому что это заставляет двигатель ApplicationController
загрузить первым. Так как двигатель ApplicationController
внутри пространства имен MyEngine
Это полное имя MyEngine::ApplicationController, которое не конфликтует с основным приложением. ApplicationController
потому что имена констант разные.
Вы должны явно включить помощников в свой lib/engine.rb
файл:
initializer 'your-gem-name.setup_helpers' do |app|
app.config.to_prepare do
ActionController::Base.send :include, HelperModuleName
end
end
end