Подтвердить что ты не робот

Маршруты двигателей в 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, тогда эта проблема тоже будет расти.

4b9b3361

Ответ 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