ruby on rails 3 - Motor de renderizado dentro del diseño de la aplicación.
ruby-on-rails-3 ruby-on-rails-plugins (3)
Fondo
Estoy creando una aplicación que se compone de un núcleo y varios módulos. Los módulos son motores de rieles y proporcionan la funcionalidad real, ya que el núcleo solo actúa como host. Los motores están alojados desde /lib
y montados en sus respectivas rutas.
coreApp
└──lib
├── module1
├── module2
└── etc
Los módulos se montan así.
mount Module1::Engine => "/module1", :as => "module1"
mount Module2::Engine => "/module2", :as => "module2"
El núcleo también es responsable de manejar la sesión, aunque el inicio de sesión en sí mismo se realiza mediante un módulo.
Problema
Todavía tengo que encontrar una gran manera de compartir el diseño de la aplicación central con los motores. A partir de ahora, así es como pongo el diseño a disposición de los motores:
coreApp
└── app
└── views
└── layouts
├── application.html.erb
└── core.html.erb
El archivo core.html.erb
solo contiene
<%= render :template => ''layouts/application'' %>
Es entonces se incluye en cada módulo como este
module Module1
class ApplicationController < ActionController::Base
layout "core"
end
end
Aunque no es particularmente elegante, funciona bien y el contenido del módulo se representa donde está la declaración de yield
en el diseño de la aplicación.
Los problemas son los siguientes:
1. Las hojas de estilo específicas del módulo no están incluidas en el encabezado
Necesito una forma de incluir las hojas de estilo del módulo activo.
2. El encabezado necesita acceso a la información sobre el usuario conectado.
El encabezado contiene información sobre el usuario que ha iniciado sesión, como
Logged in as <%= @user[:realname] %>
Esto viene de los núcleos home_controller
def index
@user = User.find_by_id(session[:user])
end
Pero cuando intento acceder al módulo, aparece el siguiente error
NoMethodError in Module1/home#index
You have a nil object when you didn''t expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]
Obviamente refiriéndose a @user
.
Pregunta
¿Cómo se puede resolver esto de la manera más elegante y seca posible sin demasiada manipulación en el lado del motor?
He buscado en Google mucho, pero realmente no puedo entender cómo resolverlo. Puede ser una falta total de información sobre cómo funcionan los rieles, por lo que es muy probable que esta pregunta ni siquiera tenga sentido para alguien que conoce bien los rieles.
Por favor comente si algo es confuso o ambiguo, y trataré de explicarlo.
He utilizado con éxito diseños de mi aplicación principal en mis motores. En primer lugar, en función de la Sección 4.3.2 de las Guías de Rails (Motores) , para acceder a las variables de ApplicationController de las aplicaciones primarias (como la session
, como se está usando arriba), debe reemplazar el application_controller.rb
del motor a partir de este Actualmente tenemos:
module Module1
class ApplicationController < ActionController::Base
layout "core"
end
end
a esto:
class Module1::ApplicationController < ::ApplicationController
end
Esto heredará ApplicationController de la aplicación principal, junto con todas sus variables.
En segundo lugar, deberá eliminar el archivo app/views/layouts/application.html.erb
de las vistas de su motor, ya que no será necesario ya que está usando la aplicación principal.
Ahora, cuando renderiza una vista de Module1 desde la aplicación principal, se utilizará el diseño de la aplicación principal y todas las variables de la session[]
se evaluarán correctamente.
No te olvides de añadir las palabras "main_app". antes de cada enlace en sus diseños, de lo contrario, intentará buscar las rutas en el motor en lugar de la aplicación principal. Por ejemplo, si el diseño en la aplicación principal incluye un enlace a some_path
(que es una vista en la aplicación principal), al mostrar una vista en el motor que usa este diseño intentará buscar some_path
en el motor en lugar de la principal. solicitud. Deberá cambiar el enlace a main_app.some_path
para que funcione.
Espero que esto ayude.
También hice lo mismo en mi aplicación. Todo lo que hice fue:
- Eliminar el diseño del motor en / app / view / layouts /
Cambia tu control_de_aplicaciones a
module EngineModule class ApplicationController < ::ApplicationController layout ''layouts/application'' end end
En sus vistas, si desea referirse a cualquier ruta como
login_path
, puede referirse a través demain_app.login_path
Utilizar layout ''layouts/application''
Y si no quieres usar main_app.your_path también puedes agregar:
module YourEngine
module ApplicationHelper
def method_missing(method, *args, &block)
if (method.to_s.end_with?(''_path'') || method.to_s.end_with?(''_url'')) && main_app.respond_to?(method)
main_app.send(method, *args)
else
super
end
end
end
end