2011-06-30 21 views
13

Tengo una aplicación con un archivo de diseño de aplicación global application.html.haml. Luego tengo múltiples "pilas de controladores": para nuestro sitio principal, nuestro portal de administración y nuestro sitio comercial. Para cada uno de estos, los controladores están dentro de un módulo y todos heredan del mismo BaseController. Cada pila tiene su propio archivo de diseño. Dentro de la pila, algunos controladores también tienen archivos de diseño.Layout Anidado de Múltiples Niveles en Rieles 3

Me gustaría que todas las vistas (a menos que se especifique lo contrario) se procesen dentro de varios niveles de diseños anidados: aplicación, "pila", "controlador".

Por ejemplo, por la acción Site::BlogController#show, me gustaría rieles para rendir:

/site/blog/show.html.haml dentro /layouts/site/blog.html.haml dentro /layouts/site.html.haml dentro /layouts/application.html.haml

Tengo dificultades para entender cómo insertar /layouts/site.html.haml en la pila. Parece que automáticamente, los rieles mostrarán la acción dentro del diseño del controlador dentro del diseño de la aplicación, sin embargo, no puedo ver cómo "insertar" diseños en la pila de renderizado.

Cualquier ayuda es muy apreciada, sin embargo, he leído todas las guías de rieles en vano, por lo que un enlace a http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts no será realmente útil.

Respuesta

18

vuelvo a leer el enlace que he publicado (http://guides.rubyonrails.org/layouts_and_rendering.html#using-nested-layouts) y se dieron cuenta de que me perdí un detalle clave.

<%= render :file => 'layouts/application' %> 

así, en Site::BaseController tengo una llamada a layout 'site' y en /layouts/site.html.haml tengo

= content_for :footer do 
    -#Content for footer 
= render :file => 'layouts/application' 

Luego, en Site::BlogController que se extiende Site::BaseController tengo layout 'site/blog' y en /layouts/site/blog.html.haml tengo

=content_for :header do 
    %h1 HELLO WORLD! 

= render :file => 'layouts/site' 

Esto luego muestra los diseños anidados como se describe en la q pregunta Perdón por perderme esto en mi pregunta.Debería haber leído más de cerca.

+0

+1 para el enlace. Eso tiene todo lo que necesitaba. –

2

He hecho algo similar, pero solo utilicé 1 nivel de sublayouts. Se puede ajustar fácilmente para permitir múltiples niveles.

En los controladores/application_controller.rb:

def sub_layout 
    nil 
end 

En controlador (por ejemplo blog_controller.rb):

def sub_layout 
    "blog" 
end 

En diseños/application.html.erb en lugar de <%=yield%>:

<%= controller.sub_layout ? (render :partial => "/layouts/#{controller.sub_layout}") : yield %> 

Haga una parcial layouts/_blog.html.erb:

...code 
    <%=yield%> 
...code 

Repita para el otro controlador & subdivisiones.

EDIT: Si lo que necesita hacer esto sobre una base por acción:

def sub_layout 
    { 
    'index' => 'blog', 
    'new' => 'other_sub_layout', 
    'edit' => 'asdf' 
    }[action_name] 
end 
+0

Desafortunadamente, este método es mucho más difícil de generalizar a las estructuras de anidación más grandes y requiere un decente acerca de código personalizado. Estaba tratando de evitar una solución como esta. –

+0

También usando este método, pero encuentro las 3 líneas que toma si lo necesita frustrante por acción, ¿alguna idea? – Rubytastic

+0

@Rubytastic ver edit ... muy bien, ¿eh? ;) – tybro0103

2

supongo que la forma más sencilla de hacerlo es mediante la adición de esta línea de código en el padre de un diseño anidado:

((render "layouts/#{controller_name}" rescue nil)|| yield) 

se podría añadir tantos diseños anidados como desee con solo cambiar el directorio de ruta del próximo diseño a renderizar.

nota: asegúrese de que su diseño anidada se llama _layoutname.whatever y que su diseño anidada tiene un rendimiento dentro

+0

'rescue nil' aquí es _muy_ muy malo: cualquier error que ocurra en la representación de ese archivo y usted será inconsciente. Es posible que ninguno de sus usuarios pueda acceder a la página principal de su sitio y no tenga idea. Simplemente deja de usar 'rescue nil' – ecoologic

0

Se puede crear un parcial con un rendimiento en ella.

_my_sub_layout.html.erb:

<h3>I'm a sub layout and here's my content:</h3> 
<%= yield %> 

En algún otro punto de vista o incluso en su diseño principal application.html.erb hacen que el diseño parcial como:

<%= render layout: 'my_sub_layout' do %> 
    <p>I'm the sub layout's content</p> 
<% end %> 
7

si se crea una ayudante de la siguiente manera:

# renders a given haml block inside a layout 
def inside_layout(layout = 'application', &block) 
    render :inline => capture_haml(&block), :layout => "layouts/#{layout}" 
end 

entonces usted puede definir sublayout así:

= inside_layout do 
    # nested layout html here 
    = yield 

estos diseños se pueden utilizar como diseños normales.

más: http://www.requests.ch/blog/2013/10/30/combine-restful-rails-with-nested-layouts/

+1

¡Gracias por esto, esto era exactamente lo que estábamos buscando! También descubrimos que puede hacer esto simplemente con 'capture (& block)', y esta respuesta también funcionará con ERB, ya que [HAML alias 'capture_haml' a' capture'] (https://github.com/ haml/haml/blob/4.0.5/lib/haml/helpers/action_view_mods.rb # L56) – valscion

Cuestiones relacionadas