ruby-on-rails-3 ruby-on-rails-plugins rails-engines

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:

  1. Eliminar el diseño del motor en / app / view / layouts /
  2. Cambia tu control_de_aplicaciones a

    module EngineModule class ApplicationController < ::ApplicationController layout ''layouts/application'' end end

  3. En sus vistas, si desea referirse a cualquier ruta como login_path , puede referirse a través de main_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