2011-09-28 16 views
12

Mam hook before_filter w kontrolerze aplikacji mojej głównej aplikacji, który robi coś takiego: (To nie tylko umieszcza link w flashu, jest wiadomość, ale nie jest istotne dla pytanie, po prostu dostęp do trasy w metodzie)Trasy silnika w aplikacji kontrolera

class ApplicationController < ActionController::Base 
    before_filter :set_link 

    def set_link 
    flash[:notice] = items_path 
    end 
end 

działa to dobrze dla aplikacji, ale kiedy idę do kontrolerów dla silnika zrobiłem ja dostaję wyjątek

No route matches {:controller=>"items", :action=>"index"} 

rozumiem że w silniku pomocnicy trasy są dla silnika, chyba że przedrostkiem d z main_app

więc zmianę sposobu w kontrolerze aplikacji do

def set_link 
    flash[:notice] = main_app.items_path 
    end 

pozbywa wyjątkiem, ale ja naprawdę nie chcę tego robić. Czy istnieje inne rozwiązanie pozwalające silnikowi rozpoznać trasy główne?

EDIT:

Dzieje się tak również wtedy, gdy układ aplikacja wywołuje pomocników ścieżce. Jeśli więc silnik ma być zintegrowany z układem strony głównej, problem ten również się pojawi.

+1

Co jest nie tak z 'main_app'? Poza tym, dlaczego wprowadzasz zależność w silniku od głównej aplikacji, w ten sposób twój silnik zależy od 'items_path' zdefiniowanej w ** każdej ** aplikacji, która z niego korzysta. To nie jest dobra praktyka, zwykle powinieneś używać tylko 'main_app.root_path' lub innych dobrze znanych tras (na przykład jeśli używasz opracować' sign_in_path'). – Fabio

+0

items_path zostanie zdefiniowana w głównej aplikacji, która jest już zbudowana. I chcę mieć silnik zamontowany gdzieś, ale zintegrowany z układem bieżącej aplikacji. Sam silnik nigdy w ogóle nie odwołuje się do items_path. Po prostu chcę, aby widoki wygenerowane przez silnik zostały umieszczone w treści układu aplikacji. Układ aplikacji musi jednak mieć dostęp do tras głównych tras. – Olives

+0

Jest to spowodowane tym, że silnik i aplikacja mają ten sam układ. W ten sposób, gdy użytkownik przechodzi ze strony głównej aplikacji do strony w silniku, nie ma widocznej różnicy między układem. – Olives

Odpowiedz

18

Zamontowane silniki zaprojektowano tak, aby działały w ten sposób, czyli izolowały główne trasy aplikacji i trasy silnika.

Jeśli chcesz połączyć dwa zestawy tras, możesz użyć nieizolowanego silnika.Pierwszym krokiem jest usunięcie połączenia isolated_namespace metody w definicji silnika:

module MyEngine 
    class Engine < Rails::Engine 
    isolate_namespace MyEngine # remove this line 
    end 
end 

Drugim krokiem jest przekształcenie trasy w my_engine/config/routes.rb, należy udać się z tego:

MyEngine::Engine.routes.draw do 
    # stuff that routes things 
end 

do tego:

Rails.application.routes.draw do 
    # stuff that routes things 
end 

i usuń wywołanie metody na trasach aplikacji:

App::Application.routes.draw do 
    mount MyEngine::Engine => "/engine" # remove this line 
end 

Główne zalety robi to w ten sposób byłoby:

  1. Nie trzeba szynach małpa-Patch. Wiem, że to robi, ale to może być resztka z czasów, kiedy silniki nie istniały w szynach.

  2. Nie trzeba montować silnika na trasach aplikacji. Z drugiej strony może to doprowadzić do ponownego wystąpienia, jeśli chciałbyś dokładniej kontrolować punkt wstawiania, ponieważ wszystkie trasy silnika będą wywoływane po (lub wcześniej, nie mam odpowiedzi na to pytanie) twoimi głównymi trasami.

Jeśli szukasz dokumentacji na temat silników, rails docs for the Engine class to całkiem dobry punkt wyjścia. Gorąco polecam je przeczytać (na wypadek, gdyby jeszcze nie), jeśli interesuje Cię temat.

+0

Och, dziękuję, wyciągnąłem włosy ... –

+0

zapomniałeś zauważyć, że jeśli usuniesz 'isolated_namespace' możesz narazić się na pewne konflikty nazw z główną aplikacją lub innymi klejnotami (przykład: helpers) – montrealmike

+0

Can not upvote to więcej! – Nerve

4

Wymyśliłem, jak to zrobić. Problemy leżą w odizolowanym obszarze nazw. W celu zintegrowania silnika z aplikacją i dzielić ten sam układ (który może mieć pomocników droga od głównej aplikacji) Zrobiłem to:

pierwsze usunąłem config/routes.rb z silnika

Następnie usunąłem isolate_namespace od klasa silnik

module MyEngine 
    class Engine < Rails::Engine 
- isolate_namespace MyEngine 
    end 
end 
end 

dodałem plik, który został załadowany do silnika:

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 

Wreszcie w głównym aplikacji config/routes.rb zamiast „mount'ing silnik można nazwać metoda

mount_my_engine_at "mount_location" 

Będzie to w zasadzie«montować»silnik jako część głównego aplikacji zamiast być odizolowane od niego. Jest podobny do tego, w jaki sposób Devise to robi.

0

Najprostszym sposobem jest zwrócenie trasy zarówno w głównej aplikacji i silnika, dzięki czemu są one dostępne zarówno:

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

Możesz zachować isolate_namespace. W swojej routes.rb silnika

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

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

A potem w głównej aplikacji routes.rb

Rails.application.routes.draw do 

    mount MyEngine::Engine => "/anything_you_want" 

    root to: "main#index" 
end 

W ten sposób można wybrać co trasy chcesz wystawiać (a czego nie)

Powiązane problemy