A criação de
layouts em aplicações
Ruby on Rails é uma funcionalidade que valorizo muito no
framework. Com ela podemos implementar na prática a filosofia de
Design de Epicentro (ver livro
Getting Real - 37
signals).
Por padrão, podemos criar dois tipos de arquivos de
layouts no
Rails:
- Layout para controllers
- Layout para a aplicação inteira
Para criar um
layout específico para um determinado
controller, criamos dentro da pasta
app/
views/
layouts da aplicação um arquivo com o nome:
nome_do_controller.html.erb
Por exemplo:
albums.html.erbUm exemplo simples do conteúdo desse arquivo seria o seguinte:

Aonde invocamos o método
yield será exibido o conteúdo da
view da página que estará sendo
acessada.
Se criarmos um arquivo parecido mas com o nome de
application.html.erb, esse
layout irá ser exibido em todas as páginas da aplicação, a menos que exista um arquivo de
layout para o
controller em questão (como
mencionado acima) ou tenha sido informado de forma explícita um outro
layout a ser exibido (demonstrarei como em breve).
O que acontece é que muitas vezes precisamos de dois ou mais
layouts diferentes em nossa aplicação, mas parte desses
layouts são iguais entre si. E replicar essas partes iguais em todos os
layouts fere o princípio de
DRY (Don't
Repeat Yourself) e acaba causando uma série de
retrabalhos.
Imagine que você altere essa parte repetida do
layout em um dos arquivos e esquece de mudar nos demais?
Para isso, vou lhes apresentar uma solução que utilizei esses dias em uma aplicação minha. Na verdade encontrei essa solução no endereço abaixo, e apenas dei uma pequena adaptada para ficar mais fácil de trabalhar:
http://blog.jerodsanto.net/2008/06/rails-nested-layoutsImagine que o
layout de nosso site é parecido com a figura abaixo:
Onde possuímos um espaço para o
logotipo, um espaço para o conteúdo e um espaço para uma
sidebar que contém o menu.
Agora imagine que em determinada parte do sites precisamos exibir algumas fotografias grandes, e seria preciso retirar o
sidebar para poupar espaço.
Para não termos que criar dois
layouts praticamente idênticos, faremos eles com apenas as partes que são diferentes, e o que for igual deixaremos em um
layout separado, o qual os dois incluirão. Conforme demonstrado na figura:
Podemos chamar isso de
layouts aninhados, ou, no termo em inglês,
nested layouts. Onde dois
layouts simples herdam informações de um
layout que trás informações comuns aos dois.
Para nos ajudar a implementar nossa solução utilizaremos um
helper do
Rails chamado
content_for.
Com
content_for podemos armazenar o conteúdo de uma determinada parte do nosso site para ser exibida depois em algum lugar específico, por exemplo:

O que é armazenado dentro do bloco do
helper content_for é exibido depois em:
<%= yield :list %>Então para solucionar nosso problema nós iremos criar dois
layouts:
- application.html.erb (que contém o sidebar e será exibido em todas as páginas da aplicação)
- expanded_content.html.erb (que será exibido apenas nas páginas que precisam de mais espaço para o conteúdo)
E um outro arquivo que conterá toda a base do site:
Tanto o
application.html.erb quanto o
expanded_content.html.erb definirão o que deverá constar no
content_for :content, e depois
renderizarão o
base.html.erb, que contém um lugar definido para exibir o conteúdo de
:content.
application.html.erb
expanded_content.html.erb
base.html.erb
Eu coloquei o conteúdo do
sidebar dentro de um
partial, para melhorar a visualização do exemplo.
Do jeito que está, todas as
views serão exibidas utilizando o
layout application.html.erb, uma vez que ele é o
layout padrão da aplicação e "
expanded_
content" não é o nome de um
controller.
Então como eu faço para utilizar o layout expanded_content.html.erb?Você tem duas opções:
1) Se você deseja aplicar este
layout à todas as
views de um determinado
controller, basta adicionar a seguinte linha no
controller:
layout 'expanded_content'Exemplo:

2) Se você deseja aplicar esse
layout apenas a uma determinada
action de seu
controller, basta informar o
layout na hora de
renderizar a
view, exemplo:

Com isso não duplicamos código e podemos administrar melhor nossa aplicação.
Gostaria de agradecer ao
Shairon Toledo que me falou da existência do
content_for la no grupo
rails-br.
Espero que tenho gostado da dica.
Qualquer dúvida podem entrar em
contato (e-mail, comentário,
twitter).
Abraços!