Маршруты двигателей в Application Controller
У меня есть привязка before_filter в моем основном прикладном контроллере приложения, которая делает что-то вроде: (Он не просто помещает ссылку во флеш, есть сообщение, но это не имеет отношения к вопросу, он просто обращается к маршрут в методе)
class ApplicationController < ActionController::Base
before_filter :set_link
def set_link
flash[:notice] = items_path
end
end
Это отлично подходит для приложения, однако, когда я иду в контроллеры для движка, я сделал исключение
No route matches {:controller=>"items", :action=>"index"}
Я понимаю, что когда в двигателе используются помощники маршрутов для движка, если только префикс main_app
Таким образом, изменив метод в контроллере приложения на
def set_link
flash[:notice] = main_app.items_path
end
Получает освобождение от исключения, но я действительно не хочу этого делать. Есть ли еще одно решение, чтобы заставить двигатель распознавать маршруты main_app?
EDIT:
Это также происходит, если макет приложения вызывает помощники путей. Поэтому, если движок разработан для интеграции в макет main_app, тогда эта проблема тоже будет расти.
Ответы
Ответ 1
Монтажные двигатели разработаны таким образом, чтобы изолировать основные маршруты приложений и маршруты двигателей.
Если вы хотите, чтобы два набора маршрутов были объединены, вы можете использовать неизолированный движок. Первый шаг - удалить вызов метода isolated_namespace
в определении вашего двигателя:
module MyEngine
class Engine < Rails::Engine
isolate_namespace MyEngine # remove this line
end
end
Второй шаг - преобразовать ваши маршруты в my_engine/config/routes.rb
, вы должны перейти от этого:
MyEngine::Engine.routes.draw do
# stuff that routes things
end
:
Rails.application.routes.draw do
# stuff that routes things
end
и удалите вызов метода mount
в маршрутах вашего приложения:
App::Application.routes.draw do
mount MyEngine::Engine => "/engine" # remove this line
end
Основные преимущества этого способа:
-
Нет необходимости в рельсах обезьян-патч. Я знаю, что разработка делает это, но это может быть остатком от тех дней, когда двигателей не было в рельсах.
-
Не нужно монтировать движок в маршрутах приложения. С другой стороны, это может иметь неприятные последствия, если вы хотите более точно контролировать точку ввода, поскольку все ваши маршруты двигателей будут вызваны после (или до того, как у меня нет ответа на этот вопрос) ваши основные маршруты.
Если вы ищете документацию по двигателям, рельсы docs для класса Engine являются довольно хорошей отправной точкой. Я бы настоятельно рекомендовал вам их прочитать (если вы еще этого не сделали), если вы заинтересованы в этом вопросе.
Ответ 2
Я понял, как это сделать. Проблемы лежат в изолированном пространстве имен. Чтобы интегрировать движок с приложением и использовать один и тот же макет (который может содержать помощники пути из основного приложения), я сделал следующее:
Во-первых, я удалил config/routes.rb
из движка
Затем я удалил изолированное_пространство из класса движка
module MyEngine
class Engine < Rails::Engine
- isolate_namespace MyEngine
end
end
end
Я добавил файл, загруженный в движок:
module ActionDispatch::Routing
class Mapper
def mount_my_engine_at(mount_location)
scope mount_location do
#Declare all your routes here
end
end
end
end
Наконец, в главном приложении config/routes.rb
вместо "монтирования движка" вы можете вызвать свой метод
mount_my_engine_at "mount_location"
В основном это будет "монтировать" ваш движок как часть основного приложения, а не быть изолированным от него. Это похоже на то, как это делает Devise.
Ответ 3
Вы можете сохранить изолированное пространство имен.
На вашем маршруте engine.rb
MyEngine::Engine.routes.draw do
...
root to: "something#index"
end
Rails.application.routes.draw do
get "something", to: "my_engine/something#index"
end
И затем в главном приложении routes.rb
Rails.application.routes.draw do
mount MyEngine::Engine => "/anything_you_want"
root to: "main#index"
end
Таким образом, вы можете выбрать маршруты, которые вы хотите просмотреть (а какие нет)
Ответ 4
Самый простой способ - нарисовать маршруты как в главном приложении, так и в движке, чтобы они были доступны для обоих:
[MyEngine::Engine, App::Application].each do |app|
app.routes.draw do
# Declare all your routes here
end
end