<?xml version="1.0" encoding="UTF-8"?>
<post>
  <body>&lt;p&gt;O livro &lt;a href=&quot;http://pragprog.com/titles/fr_arr/advanced-rails-recipes&quot;&gt;Advanced Rails Recipes&lt;/a&gt; &#233; um livro muito interessante para quem quer aprender algumas dicas mais avan&#231;adas de Rails. Especialmente aquele tipo de dicas que voc&#234; n&#227;o encontra em tutoriais ou blogs por a&#237;. Da descri&#231;&#227;o do site:&lt;/p&gt;

&lt;p&gt;&quot;Voc&#234; ir&#225; aprender como os profissionais resolveram problemas complicados usando as t&#233;cnicas mais atualizadas de Rails 2, para que voc&#234; possa entregar a sua impressionante aplica&#231;&#227;o Web de forma mais f&#225;cil e mais r&#225;pida.&quot;&lt;/p&gt;

&lt;p&gt;Esta &#233; uma tradu&#231;&#227;o para o portugu&#234;s, com autoriza&#231;&#227;o de &lt;a href=&quot;http://pragprog.com/about&quot;&gt;Dave Thomas&lt;/a&gt; de &lt;a href=&quot;http://pragprog.com/&quot;&gt;Pragmatic Programers&lt;/a&gt;. Aproveite! :)&lt;/p&gt;&lt;br&gt;

&lt;h2&gt;Tratando M&#250;ltiplos Models em Um &#218;nico Form&lt;/h2&gt;

&lt;p&gt;Por Ryan Bates (http://railscasts.com/). Ryan trabalha com desenvolvimento Web desde 1998. Come&#231;ou a trabalhar profissionalmente com Ruby on Rails em 2005 e &#233; mais conhecido pelo seu trabalho com os Railscasts, uma s&#233;rie gratuita de screencasts sobre Ruby on Rails.&lt;/p&gt;

&lt;h2&gt;Problema&lt;/h2&gt;

&lt;p&gt;A maioria do c&#243;digo Rails que voc&#234; encontra geralmente trata um model de cada vez. Isso nem sempre &#233; pr&#225;tico. Algumas vezes voc&#234; precisa criar e/ou editar dois (ou mais) models em um &#250;nico form, nas situa&#231;&#245;es onde voc&#234; tem uma associa&#231;&#227;o one-to-many entre os models.&lt;/p&gt;

&lt;h2&gt;Solu&#231;&#227;o&lt;/h2&gt;

&lt;p&gt;Digamos que n&#243;s precisamos salvar todas as tarefas pendentes para v&#225;rios projetos. Quando n&#243;s criarmos ou atualizarmos um projeto, n&#243;s gostar&#237;amos de adicionar, remover e atualizar suas tarefas, em um &#250;nico form. O que estamos imaginando &#233;:&lt;/p&gt;

&lt;img src=&quot;/images/posts/Multiple_models_one_form_NewProject.jpg&quot;&gt;

&lt;p&gt;Vamos come&#231;ar criando um relacionamento &lt;i&gt;has_many&lt;/i&gt; entre &lt;i&gt;Project&lt;/i&gt; e &lt;i&gt;Task&lt;/i&gt;. Para simplificar, vamos dar para cada model um atributo obrigat&#243;rio chamado &lt;i&gt;name&lt;/i&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/models/project.rb
class Project &lt; ActiveRecord::Base
  has_many :tasks, :dependent =&gt; :destroy
  validates_presence_of :name
end

# Arquivo: app/models/task.rb
class Task &lt; ActiveRecord::Base
  belongs_to :project
  validates_presence_of :name
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;N&#243;s vamos usar a biblioteca de Javascript Prototype, ent&#227;o antes de qualquer coisa vamos garantir que ela est&#225; carregada em nosso arquivo de layout:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/views/layouts/application.html.erb
&lt;%= javascript_include_tag :defaults %&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Vamos voltar a nossa aten&#231;&#227;o para o form, para criar um projeto com suas m&#250;ltiplas tarefas, e associadas ao projeto. Quando precisamos tratar m&#250;ltiplos models em um form, &#233; muito &#250;til eleger um model como sendo o foco prim&#225;rio ou principal, e a partir da&#237; construir os models adicionais atrav&#233;s da associa&#231;&#227;o entre eles.&lt;/p&gt;

&lt;p&gt;Neste caso, vamos fazer de &lt;i&gt;Project&lt;/i&gt; o nosso model prim&#225;rio e construir suas tarefas atrav&#233;s da associa&#231;&#227;o &lt;i&gt;has_many&lt;/i&gt;. Ent&#227;o para a action new de nosso &lt;i&gt;ProjectsController&lt;/i&gt;, n&#243;s criamos um objeto &lt;i&gt;Project&lt;/i&gt; da forma usual. No entanto, n&#243;s tamb&#233;m inicializamos uma nova &lt;i&gt;Task&lt;/i&gt; (em mem&#243;ria) que &#233; associada com o &lt;i&gt;Project&lt;/i&gt; de forma que nosso form tem alguma coisa para come&#231;ar a trabalhar:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/controllers/projects_controller.rb
def new
  @project = Project.new
  @project.tasks.build
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O template para o form precisa de algumas &#8220;manhas&#8221; j&#225; que n&#243;s precisamos tratar os campos para o model &lt;i&gt;Project&lt;/i&gt; e tamb&#233;m os campos de cada um dos models &lt;i&gt;Task&lt;/i&gt;. Ent&#227;o, vamos quebrar o problema em partes menores e usar um partial para renderizar os campos da &lt;i&gt;Task&lt;/i&gt; e adicionar um helper &lt;i&gt;add_task_link&lt;/i&gt; para criar o link que adiciona uma nova tarefa:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/views/projects/_form.html.erb
&amp;lt;%= error_messages_for :project %&amp;gt;

&amp;lt;% form_for @project do |f| -%&amp;gt;
  &amp;lt;p&amp;gt;
  Name: &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;div id=&quot;tasks&quot;&amp;gt;
    &amp;lt;%= render :partial =&amp;gt; 'task', :collection =&amp;gt; @project.tasks %&amp;gt;
  &amp;lt;/div&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= add_task_link &quot;Add a task&quot; %&amp;gt;
  &amp;lt;/p&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= f.submit &quot;Submit&quot; %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end -%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Os templates &lt;i&gt;new&lt;/i&gt; e &lt;i&gt;edit&lt;/i&gt; simplesmente renderizam este partial de formul&#225;rio, de forma que n&#243;s temos uma forma consistente para criar e atualizar um projeto. A partial do form vai e renderiza uma partial de tarefa para cada uma das tarefas do projeto. Antes de entrarmos no conte&#250;do da partial de tarefa, vamos dar uma olhada naquele helper &lt;i&gt;add_task_link&lt;/i&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/helpers/projects_helper.rb
def add_task_link(name)
  link_to_function name do |page|
    page.insert_html :bottom, :tasks, :partial =&gt; 'task' , :object =&gt; Task.new
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Quando n&#243;s clicamos no link &#8220;Add a Task&#8221;, n&#243;s queremos um novo conjunto de campos de tarefas aparecendo abaixo dos campos de tarefa que j&#225; existem no formul&#225;rio. Ao inv&#233;s de ocupar o servidor com isto, n&#243;s podemos usar JavaScript para adicionar os campos dinamicamente. O m&#233;todo &lt;i&gt;link_to_function&lt;/i&gt; aceita um bloco de c&#243;digo RJS. Geralmente n&#243;s associamos c&#243;digo RJS com chamadas ass&#237;ncronas indo para o servidor. Mas neste caso o c&#243;digo RJS gera JavaScript que &#233; executado no browser imediatamente quando o usu&#225;rio clica no link. O resultado &#233; que renderizar os campos para adicionar uma nova tarefa n&#227;o requer uma requisi&#231;&#227;o enviada ao servidor, o que leva a um tempo de resposta mais r&#225;pido no uso da aplica&#231;&#227;o.&lt;/p&gt;

&lt;p&gt;Voltando ao partial do form, n&#243;s estamos usando &lt;i&gt;form_for&lt;/i&gt; para dedicar o form para o model &lt;i&gt;@project&lt;/i&gt;. Como ent&#227;o n&#243;s vamos adicionar campos para cada uma das tarefas do projeto? A resposta est&#225; dentro da partial de tarefa:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/views/projects/_task.html.erb
&amp;lt;div class=&quot;task&quot;&amp;gt;
&amp;lt;% new_or_existing = task.new_record? ? 'new' : 'existing' %&amp;gt;
&amp;lt;% prefix = &quot;project[#{new_or_existing}_task_attributes][]&quot; %&amp;gt;

&amp;lt;% fields_for prefix, task do |task_form| -%&amp;gt;
  &amp;lt;p&amp;gt;
    Task: &amp;lt;%= task_form.text_field :name %&amp;gt;
    &amp;lt;%= link_to_function &quot;remove&quot; , &quot;$(this).up('.task').remove()&quot; %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end -%&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O ingrediente chave aqui &#233; o m&#233;todo &lt;i&gt;fields_for&lt;/i&gt;. Ele se comporta de forma muito parecida com form_for mas ele n&#227;o renderiza a tag HTML &lt;i&gt;form&lt;/i&gt;. Isto nos permite mudar o contexto para um model diferente, no meio do form principal &#8211; como se n&#243;s estiv&#233;ssemos embutindo um form dentro de outro.&lt;/p&gt;

&lt;p&gt;O primeiro par&#226;metro para &lt;i&gt;fields_for&lt;/i&gt; &#233; muito importante. Esta string ser&#225; usada como um prefixo para cada campo de tarefa. Como vamos usar esta partial tamb&#233;m para renderizar tarefas existentes &#8211; e n&#243;s queremos mant&#234;-las separadas quando o form &#233; enviado &#8211; no prefixo n&#243;s inclu&#237;mos uma indica&#231;&#227;o dizendo se a tarefa &#233; nova ou existente. (O ideal seria criar esta string de prefixo em um helper, mas vamos simplificar um pouco as coisas aqui.)&lt;/p&gt;

&lt;p&gt;O HTML gerado para uma nova tarefa se parece com isto:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;
&amp;lt;input name=&quot;project[new_task_attributes][][name]&quot; size=&quot;30&quot; type=&quot;text&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Se esta fosse uma tarefa existente, o Rails iria colocar automaticamente o ID da tarefa entre as chaves, assim:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;html&quot;&gt;
&amp;lt;input name=&quot;project[existing_task_attributes][7][name]&quot; size=&quot;30&quot; type=&quot;text&quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Agora, quando o form &#233; enviado, o Rails ir&#225; decodificar o nome do campo de entrada, para for&#231;ar uma estrutura no hash &lt;i&gt;params&lt;/i&gt;. As chaves ([]) que est&#227;o preenchidas se tornam keys em um hash aninhado. As chaves que est&#227;o vazias se tornam um array. Por exemplo, se n&#243;s enviarmos o form com duas novas tarefas, o hash &lt;i&gt;params&lt;/i&gt; vai ficar assim:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
&quot;project&quot; =&gt; {
  &quot;name&quot; =&gt; &quot;Yard Work&quot; ,
  &quot;new_task_attributes&quot; =&gt; [
    { &quot;name&quot; =&gt; &quot;rake the leaves&quot; },
    { &quot;name&quot; =&gt; &quot;paint the fence&quot; }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note que os atributos para o projeto e cada tarefa est&#227;o aninhados dentro do hash project. Isto &#233; conveniente porque significa que a action &lt;i&gt;create&lt;/i&gt; em nosso controller pode simplesmente passar todos os atributos de projeto ao model &lt;i&gt;Project&lt;/i&gt; sem se preocupar sobre o que est&#225; dentro do hash project:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/controllers/projects_controller.rb
def create
  @project = Project.new(params[:project])
  if @project.save
    flash[:notice] = &quot;Successfully created project and tasks.&quot;
    redirect_to projects_path
  else
    render :action =&gt; 'new'
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Este c&#243;digo se parece com uma action &lt;i&gt;create&lt;/i&gt; padr&#227;o, para um form de um &#250;nico model. Mas existe algo s&#250;til acontecendo aqui. Quando chamamos &lt;i&gt;Project.new(params[:project])&lt;/i&gt;, o Active Record assume que nosso model &lt;i&gt;Project&lt;/i&gt; tem um atributo correspondente chamado &lt;i&gt;new_task_attributes&lt;/i&gt; porque ele procura uma key chamada &lt;i&gt;new_task_attributes&lt;/i&gt; dentro do hash &lt;i&gt;params[:project]&lt;/i&gt;. Isto &#233;, o Active Record tentar&#225; fazer uma atribui&#231;&#227;o em massa (mass assign) de todos os dados contidos neste hash, para os atributos correspondentes no model &lt;i&gt;Project&lt;/i&gt;. Mas n&#243;s n&#227;o temos um atributo &lt;i&gt;new_task_attributes&lt;/i&gt; em nosso model &lt;i&gt;Project&lt;/i&gt;.&lt;/p&gt;

&lt;p&gt;Um jeito conveniente de manter tudo isto transparente, da ponto de vista do controller, &#233; usar um atributo virtual. Para fazer isso, n&#243;s simplesmente criamos um m&#233;todo &lt;i&gt;setter&lt;/i&gt; em nosso model &lt;i&gt;Project&lt;/i&gt;, chamado &lt;i&gt;new_task_attributes=&lt;/i&gt;, que recebe um array e constr&#243;i a tarefa para cada elemento:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/models/project.rb
def new_task_attributes=(task_attributes)
  task_attributes.each do |attributes|
    tasks.build(attributes)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Pode parecer que estas tarefas n&#227;o est&#227;o sendo salvas em lugar nenhum. De fato, o Rails vai fazer isso automaticamente quando o projeto &#233; salvo, porque ambos o projeto e suas tarefas associadas, s&#227;o novos registros.&lt;/p&gt;

&lt;p&gt;E isso &#233; tudo que precisamos para criar um projeto. Vamos ver agora como atualiz&#225;-lo.&lt;/p&gt;

&lt;p&gt;Assim como antes, n&#243;s precisamos de uma forma de adicionar e remover tarefas dinamicamente, mas desta vez se uma tarefa j&#225; existe, ela deve ser atualizada. As actions do controller s&#243; precisam se preocupar sobre o projeto, ent&#227;o elas s&#227;o bem convencionais. Como antes, a atualiza&#231;&#227;o de tarefas ser&#225; tratada no model &lt;i&gt;Project&lt;/i&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/controllers/projects_controller.rb
def edit
  @project = Project.find(params[:id])
end

def update
  params[:project][:existing_task_attributes] ||= {}

  @project = Project.find(params[:id])
  if @project.update_attributes(params[:project])
    flash[:notice] = &quot;Successfully updated project and tasks.&quot;
    redirect_to project_path(@project)
  else
    render :action =&gt; 'edit'
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Um detalhe importante: a primera linha da action update seta o par&#226;metro &lt;i&gt;existing_task_attributes&lt;/i&gt; para um hash vazio, se ele j&#225; n&#227;o est&#225; setado. Sem esta linha, n&#227;o teria como deletar a &#250;ltima tarefa de um projeto. Se n&#227;o existem campos de tarefa no form (porque n&#243;s removemos todos eles com JavaScript), ent&#227;o &lt;i&gt;existing_task_attributes()&lt;/i&gt; n&#227;o ser&#225; setado pelo form, o que significa que o nosso m&#233;todo &lt;i&gt;Project#existing_task_attributes=&lt;/i&gt; n&#227;o ser&#225; invocado. Setando um hash vazio aqui, se &lt;i&gt;existing_task_attributes()&lt;/i&gt; est&#225; vazio, garante que o m&#233;todo &lt;i&gt;Project#existing_task_attributes=&lt;/i&gt; &#233; chamado ao deletar a &#250;ltima tarefa.&lt;/p&gt;

&lt;p&gt;A partial de form n&#227;o precisa de altera&#231;&#245;es. No entanto, quando n&#243;s submetemos o form com tarefas existentes, o hash &lt;i&gt;params[:project]&lt;/i&gt; ir&#225; incluir uma key chamada &lt;i&gt;existing_task_attributes&lt;/i&gt;. Isto &#233;, quando n&#243;s atualizamos o projeto, os par&#226;metros do POST ir&#227;o se parecer com isto:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
&quot;project&quot; =&gt; {
  &quot;name&quot; =&gt; &quot;Yard Work&quot; ,
  &quot;existing_task_attributes&quot; =&gt; [
    {
      &quot;1&quot; =&gt; {&quot;name&quot; =&gt; &quot;rake the leaves&quot; },
      &quot;2&quot; =&gt; {&quot;name&quot; =&gt; &quot;paint the fence&quot; },
    }
  ]
  &quot;new_task_attributes&quot; =&gt; [
    { &quot;name&quot; =&gt; &quot;clean the gutters&quot; }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Para tratar isto, n&#243;s precisamos adicionar um m&#233;todo &lt;i&gt;existing_task_attributes=&lt;/i&gt; ao nosso model &lt;i&gt;Project&lt;/i&gt;, que ir&#225; receber cada tarefa existente e a&#237; vai: ou atualizar a tarefa ou delet&#225;-la, dependendo se os atributos s&#227;o passados:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
# Arquivo: app/models/project.rb
after_update :save_tasks

def existing_task_attributes=(task_attributes)
  tasks.reject(&amp;:new_record?).each do |task|
    attributes = task_attributes[task.id.to_s]
    if attributes
      task.attributes = attributes
    else
      tasks.delete(task)
    end
  end
end

def save_tasks
  tasks.each do |task|
    task.save(false)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note que n&#243;s estamos salvando as tarefas em um callback chamado &lt;i&gt;after_update&lt;/i&gt;. Isto &#233; importante porque, diferente de antes, as tarefas existentes n&#227;o ser&#227;o automaticamente salvas quando o projeto for atualizado. E j&#225; que os callbacks s&#227;o encapsulados em uma transa&#231;&#227;o, se algum problema inesperado acontecer ser&#225; feito um roll back.&lt;/p&gt;

&lt;p&gt;Ao passar &lt;i&gt;false&lt;/i&gt; para o m&#233;todo &lt;i&gt;task.save&lt;/i&gt;, os dados s&#227;o salvos sem passar pela valida&#231;&#227;o. Ao inv&#233;s disso, para garantir que todas as tarefas sejam validadas quando o projeto &#233; validado, n&#243;s simplesmente adicionamos esta linha ao model &lt;i&gt;Project&lt;/i&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
validates_associated :tasks
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Isto vai garantir que tudo &#233; valido antes de salvar. E se a valida&#231;&#227;o falha, ent&#227;o o uso de &lt;i&gt;error_messages_for :project&lt;/i&gt; no template de formul&#225;rio inclui os erros de valida&#231;&#227;o para o projeto e qualquer uma de suas tarefas.&lt;/p&gt;

&lt;p&gt;Ent&#227;o agora n&#243;s podemos criar e editar projetos e suas tarefas em uma tacada s&#243;. E ao usar atributos virtuais, n&#243;s mantemos o c&#243;digo do controller felizmente ignorante que n&#243;s estamos tratando v&#225;rios models a partir de um &#250;nico formul&#225;rio.&lt;/p&gt;

&lt;h2&gt;Discuss&#227;o&lt;/h2&gt;

&lt;p&gt;Uma vez que voc&#234; come&#231;a a colocar mais de um model em um &#250;nico formul&#225;rio, voc&#234; provavelmente vai querer criar um helper customizado para mensagens de erro, para fazer coisas como ignorar certos erros e detalhar outros. Veja a receita 17 &quot;Customize as Mensagens de Erro&quot;, na p&#225;gina 91 para saber como escrever um m&#233;todo &lt;i&gt;error_messages_for&lt;/i&gt; customizado. (Nota do tradutor: cap&#237;tulo dispon&#237;vel no livro &lt;a href=&quot;http://pragprog.com/titles/fr_arr/advanced-rails-recipes&quot;&gt;Advanced Rails Recipes&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Campos de data causam alguns problemas porque, por algum motivo, o Rails remove as chaves [] do nome do campo. Isto pode ser arrumado especificando manualmente a op&#231;&#227;o &lt;i&gt;:index&lt;/i&gt; e set&#225;-lo para uma string vazia se a tarefa &#233; nova:

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
&amp;lt;%= task_form.date_select :completed_at,
:index =&amp;gt; (task.new_record? ? '' : nil) %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Infelizmente, campos do tipo checkbox n&#227;o v&#227;o funcionar com esta receita porque o valor destes campos n&#227;o &#233; passado pelo browser quando o checkbox &#233; desmarcado. Portanto, voc&#234; n&#227;o tem como saber a qual tarefa um checkbox pertence quando estiver criando um novo projeto. Para resolver este problema, voc&#234; pode usar um menu select para campos booleanos:

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
&amp;lt;%= task_form.select :completed, [['No' , false], ['Yes' , true]] %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Copyright (c) 2008 The Pragmatic Programmers, LLC&lt;/p&gt;</body>
  <comments-count type="integer">19</comments-count>
  <created-at type="datetime">2009-01-13T17:18:42Z</created-at>
  <id type="integer">14</id>
  <permalink nil="true"></permalink>
  <slug></slug>
  <title>Tratando M&#250;ltiplos Models em Um &#218;nico Form</title>
  <updated-at type="datetime">2009-01-13T17:18:42Z</updated-at>
  <user-id type="integer" nil="true"></user-id>
</post>
