Маршруты двигателя в Application Controller - PullRequest
12 голосов
/ 28 сентября 2011

У меня есть ловушка 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, то эта проблема также возникнет там.

Ответы [ 4 ]

19 голосов
/ 02 октября 2011

Монтируемые движки предназначены для такой работы, то есть изолируют основные маршруты приложений и маршруты движков.

Если вы хотите объединить два набора маршрутов, вы можете использовать неизолированный движок,Первым шагом является удаление вызова метода 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

Основными преимуществами этого способа будут:

  1. Нет необходимости в обезьяне-патч-рейках.Я знаю, что devise делает это, но это может быть пережитком тех дней, когда в рельсах не было двигателей.

  2. Нет необходимости устанавливать двигатель на маршрутах применения.С другой стороны, это может иметь неприятные последствия, если вы хотите более точно контролировать точку вставки, так как все маршруты вашего двигателя будут вызываться после (или до того, у меня нет ответа на этот вопрос) ваших основных маршрутов.

Если вы ищете документацию по двигателям, документы по рельсам для класса Engine являются довольно хорошей отправной точкой.Я настоятельно рекомендую вам прочитать их (если вы еще этого не сделали), если вы заинтересованы в этой теме.

4 голосов
/ 30 сентября 2011

Я понял, как это сделать. Проблемы лежат в изолированном пространстве имен. Чтобы интегрировать движок с приложением и использовать тот же макет (в котором могут быть помощники пути из основного приложения), я сделал это:

Сначала я снял config/routes.rb с двигателя

Затем я удалил пространство isolate_name из класса двигателя

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.

2 голосов
/ 21 апреля 2013

Вы можете оставить изолят_пространства имен.В вашем движке route.rb

MyEngine::Engine.routes.draw do
  ...
  root to: "something#index"
end

Rails.application.routes.draw do
  get "something", to: "my_engine/something#index"
end

А затем в главном приложении rout.rb

Rails.application.routes.draw do

  mount MyEngine::Engine => "/anything_you_want"

  root to: "main#index"
end

Таким образом вы можете выбрать, какие маршруты вы хотите выставить (а какие нет).)

0 голосов
/ 25 июля 2012

Самый простой способ - нарисовать маршруты как в основном приложении, так и в движке, чтобы они были доступны обоим:

[MyEngine::Engine, App::Application].each do |app|
  app.routes.draw do
    # Declare all your routes here
  end
end
...