<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Blog.Impact - Home</title>
  <id>tag:blog.impactmedia.com.br,2008:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  <link href="http://blog.impactmedia.com.br/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://blog.impactmedia.com.br/" rel="alternate" type="text/html"/>
  <updated>2008-06-28T06:09:31Z</updated>
  <entry xml:base="http://blog.impactmedia.com.br/">
    <author>
      <name>davis</name>
    </author>
    <id>tag:blog.impactmedia.com.br,2008-06-28:6528</id>
    <published>2008-06-28T06:08:00Z</published>
    <updated>2008-06-28T06:09:31Z</updated>
    <category term="eeepc"/>
    <category term="efetividade.net"/>
    <category term="promocao"/>
    <link href="http://blog.impactmedia.com.br/articles/2008/6/28/ajude-a-sustentar-a-wikipdia-e-outros-projetos-sem-colocar-a-mo-no-bolso-e-concorra-a-um-eee-pc" rel="alternate" type="text/html"/>
    <title>Ajude a sustentar a Wikip&#233;dia e outros projetos sem colocar a m&#227;o no bolso, e concorra a um Eee PC!</title>
<content type="html">
            &lt;b&gt;Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!&lt;/b&gt;&lt;br /&gt;…e também a pen drives, card drives, camisetas geeks, livros e mais! O &lt;a href=&quot;http:&quot; /&gt;BR-Linux&lt;/a&gt; e o &lt;a href=&quot;http:&quot; /&gt;Efetividade&lt;/a&gt; lançaram uma &lt;a href=&quot;http:&quot; /&gt;campanha&lt;/a&gt; para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e &lt;a href=&quot;http:&quot; /&gt;participe&lt;/a&gt; - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!
          </content>  </entry>
  <entry xml:base="http://blog.impactmedia.com.br/">
    <author>
      <name>davis</name>
    </author>
    <id>tag:blog.impactmedia.com.br,2008-06-08:6525</id>
    <published>2008-06-08T16:00:00Z</published>
    <updated>2008-06-08T16:27:03Z</updated>
    <category term="Ruby on Rails"/>
    <category term="bdd"/>
    <category term="fixtures"/>
    <category term="rails"/>
    <link href="http://blog.impactmedia.com.br/articles/2008/6/8/fixtures-para-polymorphic-associations-com-o-rails-2" rel="alternate" type="text/html"/>
    <title>Fixtures para Polymorphic Associations com o Rails 2</title>
<content type="html">
            &lt;p&gt;Uma dica rápida de como fazer suas &lt;em&gt;fixtures&lt;/em&gt; para associações polimórficas.
Digamos que a estrutura abaixo faz parte de sua aplicação:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;  &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Address&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    belongs_to &lt;span class=&quot;sy&quot;&gt;:addressable&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:polymorphic&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Person&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    has_one &lt;span class=&quot;sy&quot;&gt;:contact&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:as&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:addressable&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Company&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    has_one &lt;span class=&quot;sy&quot;&gt;:contact&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:as&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:addressable&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Abaixo as &lt;em&gt;fixtures&lt;/em&gt; para esses modelos:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;  &lt;span class=&quot;c&quot;&gt;# Person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  daviscabral:&lt;tt&gt;
&lt;/tt&gt;    username: daviscabral&lt;tt&gt;
&lt;/tt&gt;    password: super_secret&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# Company&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  impact:&lt;tt&gt;
&lt;/tt&gt;    name = &lt;span class=&quot;co&quot;&gt;Impact&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Media&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;# Address&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  daviscabral_address:&lt;tt&gt;
&lt;/tt&gt;    contactable: daviscabral (&lt;span class=&quot;co&quot;&gt;Person&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    address: &lt;span class=&quot;co&quot;&gt;Rua&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Meia&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Mole&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;69&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  impact_address:&lt;tt&gt;
&lt;/tt&gt;    addressable: impact (&lt;span class=&quot;co&quot;&gt;Company&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    address: &lt;span class=&quot;co&quot;&gt;Av&lt;/span&gt;. &lt;span class=&quot;co&quot;&gt;Brazuca&lt;/span&gt;, &lt;span class=&quot;i&quot;&gt;999&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;O grande detalhe, é o &lt;strong&gt;(class_name)&lt;/strong&gt; que é a chave que define o campo &lt;em&gt;type&lt;/em&gt; do relacionamento.&lt;/p&gt;


	&lt;h3&gt;Livro de Rails 2.1&lt;/h3&gt;


	&lt;p&gt;O Carlos Brando, do blog &lt;a href=&quot;http://www.nomedojogo.com&quot;&gt;Nome do Jogo&lt;/a&gt;, publicou o primeiro livro que cobre as novas funcionalidades de Rails 2.1. Junto do Marcos Tapajós, que deu uns tapas no livro revisando e escrevendo o código do &lt;em&gt;fazedor&lt;/em&gt; de livros, e do Daniel Lopes, que fez a capa. 
Bem, códigos do &lt;em&gt;fazedor&lt;/em&gt; de livros? Isso mesmo, eles escreveram um projeto em ruby que gera o &lt;span class=&quot;caps&quot;&gt;PDF&lt;/span&gt; do livro.&lt;/p&gt;


	&lt;p&gt;O projeto está no Github e a galera está convidada a ajudar a traduzir para o inglês.&lt;/p&gt;


	&lt;p&gt;Ótima iniciativa de todos os envolvidos. A comunidade só ganha com atitudes como essa.&lt;/p&gt;


	&lt;p&gt;Sem perder tempo, fica também a dica do projeto para escrita de livros feito pelo Nando Vieira, do blog &lt;a href=&quot;http://www.simplesideias.com.br&quot;&gt;Simples idéias&lt;/a&gt;. O projeto é muito parecido, mas parece que ambos tiveram a mesma idéia.&lt;/p&gt;


	&lt;p&gt;Fica a minha sugestão para um merge dos projetos! :-)&lt;/p&gt;


	&lt;h3&gt;Nova fase&lt;/h3&gt;


	&lt;p&gt;Não comentei sobre isso aqui no Blog, mas fazem alguns meses que me desliguei da empresa onde trabalhava. Com a saída de lá, estou podendo me dedicar muito ao Rails e a projetos pessoais.&lt;/p&gt;


	&lt;p&gt;Com essas mudanças, aderi totalmente as melhores práticas, desde o &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; até o &lt;span class=&quot;caps&quot;&gt;BDD&lt;/span&gt;. Isso acabou me levando a comprar um MacBook, e a testar o famoso textmate. Realmente o Mac OS é incrível. O textmate não fica atrás, nem as várias coisas novas que ando experimentando com essa nova aquisição.&lt;/p&gt;


	&lt;p&gt;Na quarta-feira passada, tive a oportunidade de presenciar e participar da primeira palestra sobre &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; aqui em Cascavel, PR, que foi realizada na Unioeste. Fiz uma gravação, mas o audio não saiu muito bom. Estou providenciando um microfone bluetooth para ver se a coisa fica melhor.&lt;/p&gt;


	&lt;p&gt;Demos uma introdução ao &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; e também já demos sinais que as próximas palestras e/ou mini-cursos serão sobre testes, mão na massa mesmo. Podem surgir bons artigos a respeito disso.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.impactmedia.com.br/">
    <author>
      <name>davis</name>
    </author>
    <id>tag:blog.impactmedia.com.br,2008-05-25:6523</id>
    <published>2008-05-25T18:00:00Z</published>
    <updated>2008-05-25T18:22:46Z</updated>
    <category term="Ruby on Rails"/>
    <category term="controller"/>
    <category term="polymorphic"/>
    <category term="resources"/>
    <category term="routes"/>
    <link href="http://blog.impactmedia.com.br/articles/2008/5/25/polymorphic-resources-de-uma-forma-dry" rel="alternate" type="text/html"/>
    <title>Polymorphic resources, de uma forma DRY</title>
<content type="html">
            &lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/25/parent.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;h3&gt;Modelo polimórfico&lt;/h3&gt;


	&lt;p&gt;Um modelo polimórfico pode pertencer a mais de uma classe modelo pai. Por exemplo, &lt;em&gt;Comments&lt;/em&gt; pode pertencer a &lt;em&gt;Articles&lt;/em&gt; e &lt;em&gt;Documents&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Para isso teriamos um campo &lt;em&gt;string&lt;/em&gt; chamado &lt;em&gt;type&lt;/em&gt; em nossa tabela &lt;em&gt;comments&lt;/em&gt;. Esse campo é chave no Rails e é preenchido com a classe do modelo pai num relacionamento polimórfico.&lt;/p&gt;


	&lt;p&gt;Nossos modelos ficariam como abaixo:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Article&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class=&quot;sy&quot;&gt;:comments&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:as&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:commentable&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Document&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class=&quot;sy&quot;&gt;:comments&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:as&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:commentable&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Comment&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  belongs_to &lt;span class=&quot;sy&quot;&gt;:commentable&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:polymorphic&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Dessa maneira, você pode referenciar &lt;em&gt;article.comments&lt;/em&gt; e &lt;em&gt;document.comments&lt;/em&gt; para seus objetos &lt;em&gt;Article&lt;/em&gt; e &lt;em&gt;Document&lt;/em&gt;, respectivamente.&lt;/p&gt;


	&lt;h3&gt;Rotas para nosso controlador polimórfico&lt;/h3&gt;


	&lt;p&gt;Agora temos nossos modelos &lt;em&gt;Article&lt;/em&gt; e &lt;em&gt;Document&lt;/em&gt; possuindo o mesmo modelo &lt;em&gt;Comment&lt;/em&gt;. Definindo nossas rotas, veremos que ele será polimórfico também, pois vai estar aninhado aos controladores &lt;em&gt;Articles&lt;/em&gt; e &lt;em&gt;Documents&lt;/em&gt; .&lt;/p&gt;


	&lt;p&gt;Abaixo as rotas:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;ActionController&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Routing&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Routes&lt;/span&gt;.draw &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |map|&lt;tt&gt;
&lt;/tt&gt;  map.resources &lt;span class=&quot;sy&quot;&gt;:articles&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:has_many&lt;/span&gt; =&amp;gt; [ &lt;span class=&quot;sy&quot;&gt;:comments&lt;/span&gt; ]&lt;tt&gt;
&lt;/tt&gt;  map.resources &lt;span class=&quot;sy&quot;&gt;:documents&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:has_many&lt;/span&gt; =&amp;gt; [ &lt;span class=&quot;sy&quot;&gt;:comments&lt;/span&gt; ]&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Abaixo exemplo de alguns itens gerados a partir dessas duas rotas:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;article_comment_path(&lt;span class=&quot;iv&quot;&gt;@article&lt;/span&gt;,&lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt;) &lt;span class=&quot;c&quot;&gt;# =&amp;gt; /articles/1/comments/22&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;article_new_comment_path(&lt;span class=&quot;iv&quot;&gt;@article&lt;/span&gt;)     &lt;span class=&quot;c&quot;&gt;# =&amp;gt; /articles/1/comments/new&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;document_comment_path(&lt;span class=&quot;iv&quot;&gt;@document&lt;/span&gt;,&lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt;) &lt;span class=&quot;c&quot;&gt;# =&amp;gt; /documents/1/comments/22&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;document_new_comment_path(&lt;span class=&quot;iv&quot;&gt;@document&lt;/span&gt;)     &lt;span class=&quot;c&quot;&gt;# =&amp;gt; /documents/1/comments/new&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;h3&gt;Controlador polimórfico&lt;/h3&gt;


	&lt;p&gt;Através das novas rotas, vimos que um comentário poderia ser criado a partir de &lt;em&gt;/articles/1/comments/new&lt;/em&gt; ou &lt;em&gt;/documents/1/comments/new&lt;/em&gt;. Podemos fazer com que nosso controlador gerencie isso de uma forma simples, como abaixo:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CommentsController&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;new&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt; = parent_object&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt; = &lt;span class=&quot;co&quot;&gt;Comment&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt; = parent_object&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt; = &lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt;.comments.build(params[&lt;span class=&quot;sy&quot;&gt;:comment&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt;.valid? &lt;span class=&quot;r&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;      redirect_to parent_url(&lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      render &lt;span class=&quot;sy&quot;&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;private&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;parent_object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;case&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;when&lt;/span&gt; params[&lt;span class=&quot;sy&quot;&gt;:article_id&lt;/span&gt;] &lt;span class=&quot;r&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Article&lt;/span&gt;.find_by_id(params[&lt;span class=&quot;sy&quot;&gt;:article_id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;when&lt;/span&gt; params[&lt;span class=&quot;sy&quot;&gt;:document_id&lt;/span&gt;] &lt;span class=&quot;r&quot;&gt;then&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Document&lt;/span&gt;.find_by_id(params[&lt;span class=&quot;sy&quot;&gt;:document_id&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;    &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;  &lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;parent_url&lt;/span&gt;(parent)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;case&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;when&lt;/span&gt; params[&lt;span class=&quot;sy&quot;&gt;:article_id&lt;/span&gt;] &lt;span class=&quot;r&quot;&gt;then&lt;/span&gt; article_url(parent)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;when&lt;/span&gt; params[&lt;span class=&quot;sy&quot;&gt;:document_id&lt;/span&gt;] &lt;span class=&quot;r&quot;&gt;then&lt;/span&gt; document_url(parent)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;    &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Faz o que precisa? Faz. Mas isso pode ser mais bonito. Dessa forma, sempre que adicionar-mos um item que pode receber um comentário, ele deverá criar uma nova condição em nossos &lt;em&gt;case&lt;/em&gt;. Para isso, vamos passar todo esse código de forma genérica para nosso &lt;em&gt;ApplicationController&lt;/em&gt;.&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ApplicationController&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActionController&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;protected&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &amp;lt;&amp;lt; &lt;span class=&quot;cl&quot;&gt;self&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;    attr_reader &lt;span class=&quot;sy&quot;&gt;:parents&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;parent_resources&lt;/span&gt;(*parents)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;iv&quot;&gt;@parents&lt;/span&gt; = parents&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;parent_id&lt;/span&gt;(parent)&lt;tt&gt;
&lt;/tt&gt;    request.path_parameters[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt; parent &lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_id&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;parent_type&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.class.parents.detect { |parent| parent_id(parent) }&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;parent_class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    parent_type &amp;amp;&amp;amp; parent_type.to_s.classify.constantize&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;parent_object&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    parent_class &amp;amp;&amp;amp; parent_class.find_by_id(parent_id(parent_type))&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;CommentsController&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  parent_resources &lt;span class=&quot;sy&quot;&gt;:article&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:document&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;new&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt; = parent_object&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt; = &lt;span class=&quot;co&quot;&gt;Comment&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;create&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt; = parent_object&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt; = &lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt;.comments.build(params[&lt;span class=&quot;sy&quot;&gt;:comment&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt;.valid? &lt;span class=&quot;r&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;iv&quot;&gt;@comment&lt;/span&gt;.save&lt;tt&gt;
&lt;/tt&gt;      redirect_to send(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;dl&quot;&gt;#{&lt;/span&gt; parent_type &lt;span class=&quot;dl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;_url&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;iv&quot;&gt;@parent&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      render &lt;span class=&quot;sy&quot;&gt;:action&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Essa solução foi publicada inicialmente por Val Aleksenko, em seu blog &lt;a href=&quot;http://revolutiononrails.blogspot.com&quot;&gt;Revolution On Rails&lt;/a&gt;. Através dela, criei um plugin chamado &lt;a href=&quot;https://github.com/daviscabral/parent_resources/tree&quot;&gt;&lt;em&gt;parent_resources&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Isso será adicionado ao Edge e já tem um patch sendo desenvolvido. Então esse plugin tem um tempo bem curto de vida. Mas a solução me salvou de várias repetições de código. Fica ae para o caso de alguem precisar.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.impactmedia.com.br/">
    <author>
      <name>davis</name>
    </author>
    <id>tag:blog.impactmedia.com.br,2008-05-23:6519</id>
    <published>2008-05-23T15:00:00Z</published>
    <updated>2008-05-23T16:02:49Z</updated>
    <category term="SCRUM"/>
    <category term="acunote"/>
    <category term="planning poker"/>
    <category term="product backlog"/>
    <category term="scrum board"/>
    <category term="sprints"/>
    <link href="http://blog.impactmedia.com.br/articles/2008/5/23/trabalho-com-equipes-remotas-posso-utilizar-scrum" rel="alternate" type="text/html"/>
    <title>Trabalho com equipes remotas, posso utilizar SCRUM?</title>
<content type="html">
            &lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/8/remote-team.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Sim, você pode! Mas o correto seria perguntar como e não se pode!&lt;/p&gt;


	&lt;p&gt;Em alguns dias de pesquisa sobre ferramentas online para o auxilio e redução de consumo de papel (na busca de uma prática sustentável sem perder a produtividade), encontrei duas ferramentas que me chamaram a atenção e me fizeram publicar esse texto.&lt;/p&gt;


	&lt;p&gt;Mas a relação custo x benefício dessa prática não me agradou. A produtividade não me parece ser a mesma, quando se utiliza esses scrum-boards virtuais. O impact visual que um quadro branco tem na sua frente, durante seu dia de trabalho, é muito maior que um site onde você entra quando quer para ver as tarefas pendentes, ou faz um trabalho de estimativa.&lt;/p&gt;


	&lt;p&gt;Mas se é a única alternativa, no caso de equipes remotas, é melhor do que nada.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;NOTA&lt;/span&gt;:&lt;/strong&gt; Observei que se for possível, utilizar dois monitores, mantendo o &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; board virtual aberto em um dos monitores durante seu dia, essa questão do impacto visual diminui. Mas trocamos os gastos com papel por gastos com energia.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;NOTA&lt;/span&gt;:&lt;/strong&gt; Em uma empresa que visitei e está iniciando a aplicação do &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; agora, verifiquei a utilização de um scrum-board de vidro, e seus traços feitos com fitas coloridas. O uso de números identificando documentos relacionados as tarefas ao invés de post-its. É uma alternativa também.&lt;/p&gt;


	&lt;h2&gt;Planning poker&lt;/h2&gt;


	&lt;p&gt;Encontrei o site &lt;a href=&quot;www.planningpoker.com&quot;&gt;Planning Poker&lt;/a&gt;, que proporciona o jogo de cartas para estimativa online. Você, como &lt;em&gt;product owner&lt;/em&gt;, acessa o sistema sendo moderador e convida seu time de desenvolvedores para fazer as estimativas através de uma &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt;. Os membros acessam essa &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; e aguardam as histórias e o início das contagens para mostrar o resultado. Ele fornece opções para contar sua estória de forma estruturada, onde você responde algumas questões, ou de forma livre, onde é aceito qualquer coisa.&lt;/p&gt;


	&lt;p&gt;Após contar sua estória, você inicia a contagem do tempo. Após o resultado, você passa para a próxima estória. Uma mão na roda para quem não tem possibilidade de estar se encontrando frequentemente.&lt;/p&gt;


	&lt;p&gt;Na primeira reunião do projeto Marca Pelada, foi montado todo o &lt;em&gt;product backlog&lt;/em&gt; sem estimativas. O planningpoker.com será utilizado para estimar e após esse resultado, será colocado aqui um update dessa experiência.&lt;/p&gt;


	&lt;h2&gt;Scrum board&lt;/h2&gt;


	&lt;p&gt;O scrum-board virtual realmente é um problema. Encontrei várias opções para uso no desktop, com alguma ajuda de um papél de parede interessante você consegue um bom resultado. Mas o impacto visual realmente fica prejudicado. E vai totalmente contra o &lt;span class=&quot;caps&quot;&gt;DRY&lt;/span&gt; você ficar atualizando um scrum-board com as tarefas que os outros da sua equipe fizeram ao final da sua tarefa.&lt;/p&gt;


	&lt;p&gt;Mas como nem tudo são flores no desenvolvimento remoto, ou você faz isso ou utiliza sistemas online para controle de tarefas compartilhadas. Um simples todo ou até mesmo um aplicativo que gera os burndown chart, como o &lt;a href=&quot;www.acutenote.com&quot;&gt;Acunote.com&lt;/a&gt;.
Para um único projeto ele é gratuito. Após o cadastro, ele tem alguns dados preenchidos para demonstração.&lt;/p&gt;


	&lt;p&gt;Incrivelmente foi a única ferramenta que encontrei para esse tipo de controle. Mas unindo controles de versão, sistemas de tickets e um wiki, você consegue muito bem fazer o controle de forma objetiva e bem similar.&lt;/p&gt;


	&lt;p&gt;O importante é uma forma única e ágil da equipe se comunicar.&lt;/p&gt;


	&lt;h2&gt;Mais recursos&lt;/h2&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;www.scrumalliance.com/resources/&quot;&gt;Scrum Alliance &#8211; Resources&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://blog.impactmedia.com.br/">
    <author>
      <name>davis</name>
    </author>
    <id>tag:blog.impactmedia.com.br,2008-05-22:6521</id>
    <published>2008-05-22T01:00:00Z</published>
    <updated>2008-05-22T01:41:25Z</updated>
    <category term="SCRUM"/>
    <category term="planning poker,crisp,estimativas"/>
    <link href="http://blog.impactmedia.com.br/articles/2008/5/22/planning-poker" rel="alternate" type="text/html"/>
    <title>Planning poker</title>
<content type="html">
            &lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/8/planning-poker.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Um dos métodos de estimativas mais comuns no &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; é o uso do planning poker, um jogo de cartas numeradas com uma sequência de Fibonacci. A idéia é pontuar suas estórias, e a primeira estória pontuada serve como referência para pontuar as seguintes.&lt;/p&gt;


	&lt;p&gt;As cartas são geralmente as seguintes (pelas explicações que li, o modelo abaixo me parece o mais correto):&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/8/planning-poker.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;h3&gt;Ok&#8230; Mas qual o porquê dessa série de números?&lt;/h3&gt;


	&lt;p&gt;Simples, os números menores conseguem ser mais precisos e refletem muito bem algo realmente possível de realizar. Os número maiores não são estórias muito claras, difíceis de estimar e que devem ser transformadas em estórias menores. Numa escala coerente, estimativas com números maiores que 13 já levantam questões como: &#8220;Isso é mesmo uma estória?&#8221;, &#8220;Isso não poderia ser quebrado em estórias menores?&#8221;, etc.&lt;/p&gt;


	&lt;h3&gt;Cartas especiais&lt;/h3&gt;


&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/8/special-card-0_1.png&quot; alt=&quot;&quot; /&gt;
&lt;/td&gt;
&lt;td&gt;

	&lt;h4&gt;Feito&lt;/h4&gt;


Essa estória já foi realizada, ou é tão simples, que levará apenas alguns minutos para ser realizada.
&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;
&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/8/special-card-1_1.png&quot; alt=&quot;&quot; /&gt;
&lt;/td&gt;
&lt;td&gt;

	&lt;h4&gt;Sem idéia&lt;/h4&gt;


Não se tem a mínima idéia do tempo que essa estória pode levar.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;
&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/8/special-card-2_1.png&quot; alt=&quot;&quot; /&gt;
&lt;/td&gt;
&lt;td&gt;

	&lt;h4&gt;Hora da pausa&lt;/h4&gt;


Hora de fazer uma pausa para descansar um pouco.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

	&lt;h3&gt;Como funciona&lt;/h3&gt;


	&lt;p&gt;Cada membro da equipe possui um conjunto dessas cartas.&lt;/p&gt;


	&lt;p&gt;O &lt;em&gt;product owner&lt;/em&gt;, junto da equipe, seleciona a estória que mais se aproxima de uma pontuação 2. Essa pontuação no momento, é apenas 2, não significa 2 dias, nem duas horas¹.&lt;/p&gt;


	&lt;p&gt;A questão aqui é definir uma estória referência. Apartir dessa estória, serão feitas as estimativas para outras estórias seguindo o &lt;em&gt;planning poker&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Todos pensam, selecionam suas cartas e as pões sobre a mesa com o verso para cima.  Quem não prestou atenção, acaba não tendo saída e pedir que o &lt;em&gt;product owner&lt;/em&gt; explique novamente a estória.&lt;/p&gt;


	&lt;p&gt;Se houverem muitas divergências de opiniões, o que é comum, o menor valor estimado e o maior, explicam o motivo que os levou a estimar tal valor, questão de um minuto mesmo. É feita a rodada de estimativas novamente. Havendo consenso, a estória fica estimada e se passa para a próxima. Se ainda houverem muitas divergências, outra rodada se torna necessária, se nessa rodada nada for decidido, toma-se a opinião da maioria como a real. É importante que o &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; master esteja envolvido para evitar discussões e brincadeiras durante esse momento.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Atenção:&lt;/strong&gt; &lt;em&gt;Esse artigo foi baseado em uma palestra realizada pelo Juca, do &lt;span class=&quot;caps&quot;&gt;CESAR&lt;/span&gt;, através do Treina Tom e na página &lt;a href=&quot;http://www.crisp.se/planningpoker/&quot;&gt;Planning Poker&lt;/a&gt;. Sendo partes do texto apenas transcrições do texto original&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;¹ &lt;em&gt;Story points&lt;/em&gt; parece ser a forma mais bacana de estimar, mesmo parecendo ser algo muito abstrato inicialmente. Essa abstração se vai, apartir do momento em que o primeiro &lt;em&gt;sprint&lt;/em&gt; é executado. No final do &lt;em&gt;sprint&lt;/em&gt;, essa pontuação virou referência, e já pode ser considerada num gráfico &lt;strong&gt;pontos x tempo&lt;/strong&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://blog.impactmedia.com.br/">
    <author>
      <name>davis</name>
    </author>
    <id>tag:blog.impactmedia.com.br,2008-05-04:6516</id>
    <published>2008-05-04T15:30:00Z</published>
    <updated>2008-05-04T15:31:06Z</updated>
    <category term="Qualidade"/>
    <category term="SCRUM"/>
    <category term="estimate"/>
    <category term="planningpoker"/>
    <category term="quality"/>
    <category term="scrum"/>
    <category term="teams"/>
    <category term="time"/>
    <link href="http://blog.impactmedia.com.br/articles/2008/5/4/como-saber-quanto-tempo-eu-levo-para-um-projeto" rel="alternate" type="text/html"/>
    <title>Como saber quanto tempo eu levo para um projeto?</title>
<content type="html">
            &lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/4/time.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;A resposta é simples: medindo!&lt;/p&gt;


	&lt;p&gt;Se você nunca medir, nunca saberá o tempo que leva. Todo trabalho de estimativa baseia-se na experiência (registros passados) do tempo que levou. Medir o tempo pode parecer uma coisa simples, mas é importante ser sempre pessimista, problemas podem ocorrer, e todo o tempo que ganhou no projeto, pode ser perdido na última tarefa.&lt;/p&gt;


	&lt;p&gt;Estimativa é um indicador, e como qualquer outro indicador, você precisa de uma referência. Se você nunca mediu seu tempo, comece agora, sem esses dados suas estimativas serão chutes, e a entrega do projeto na data marcada será uma loteria.&lt;/p&gt;


	&lt;p&gt;Divida todo seu trabalho em tarefas equivalentes. Reduza seu nível ao mais operacional possível, onde você possua apenas instruções de trabalho. Um exemplo disso é uma tarefa &#8220;Programar formulário de cadastro de pessoas&#8221;. Reduzindo ao nível mais operacional possível, você evita que a evolução das tarefas possam ser mensuradas (a tarefa A está 78% concluída) e acabem não mostrando sua real evolução dentro do projeto.&lt;/p&gt;


	&lt;p&gt;Isso não é novo, o &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; prega isso, e nele uma tarefa só pode estar pendente, em andamento ou concluída. Estou no início dos meus estudos sobre &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt;, e pode ter muita coisa que eu entendi errado, mas de qualquer forma, aprendi uma porção de coisas bacanas que podem ajudar mesmo não sendo o padrão correto.&lt;/p&gt;


	&lt;p&gt;Meu maior problema era definir o que seria uma estória e o que seria uma tarefa. Um exemplo que me ajudou a definir isso esta no livro &lt;a href=&quot;http://www.infoq.com/minibooks/scrum-xp-from-the-trenches&quot;&gt;Scrum and XP from the Trenches&lt;/a&gt; e segue abaixo de maneira simplificada:&lt;/p&gt;


	&lt;h3&gt;Quebrando suas estórias em estórias menores&lt;/h3&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/4/story-to-small-stories.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;h3&gt;Quebrando estórias em tarefas&lt;/h3&gt;


	&lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/4/story-to-tasks.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Então, defina suas estórias, suas tarefas e então inicie seus trabalhos. Leia sobre &lt;span class=&quot;caps&quot;&gt;SCRUM&lt;/span&gt; e XP para ter uma idéia melhor, acredito que isso lhe ajudará muito mesmo, não apenas no seu trabalho, mas para organização de sua vida.&lt;/p&gt;


	&lt;p&gt;Após o início dos seus trabalhos, acompanhe a evolução do seu trabalho x tempo.  Esse indicador é muito importante e será, após a conclusão dos trabalhos, seu indicador base. Vai ser com ele que você saberá o tempo real necessário para concluir um número X de tarefas. É um número aproximado, mas é melhor que número nenhum.&lt;/p&gt;


	&lt;p&gt;Com isso, você terá uma estimativa real &#8211; aproximada, mas real &#8211; do potencial de trabalho que tem em mãos. Como ele será possível definir os trabalhos que poderão ser feitos em determinado tempo e até planos para melhoria desse potencial, como treinamentos, aumento do número de pessoas na equipe ou até mesmo troca de membros que possam não estar se adequando a forma de trabalho.&lt;/p&gt;


Mais informações podem ser encontradas nos links abaixo:
	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.infoq.com/minibooks/scrum-xp-from-the-trenches&quot;&gt;InfoQ: Scrum and XP from the Trenches&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Scrum&quot;&gt;Scrum na Wikipedia&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.implementingscrum.com/&quot;&gt;Implementing Scrum&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.planningpoker.com/&quot;&gt;Planning Poker Game&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://blog.impactmedia.com.br/">
    <author>
      <name>davis</name>
    </author>
    <id>tag:blog.impactmedia.com.br,2008-05-03:6515</id>
    <published>2008-05-03T17:00:00Z</published>
    <updated>2008-05-03T17:39:23Z</updated>
    <category term="Ruby on Rails"/>
    <link href="http://blog.impactmedia.com.br/articles/2008/5/3/sti-e-polymorphic-associations" rel="alternate" type="text/html"/>
    <title>STI e Polymorphic associations</title>
<content type="html">
            &lt;p&gt;&lt;img src=&quot;http://blog.impactmedia.com.br/assets/2008/5/3/892003_48006074.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Essa semana me deparei com um problema: meus modelos que herdavam do modelo &lt;code&gt;User&lt;/code&gt;, faziam parte de uma associação polimórfica, onde cada tipo distinto de usuário, poderia ter um vepiculo. Esse problema é documentado no manual, e para utilizar &amp;lt;abbrv title=&quot;Single Table Inheritance&quot;&gt;&lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt;&amp;lt;/abbrv&gt; com associações polimórficas é necessário uma pequena alteração no seu modelo.&lt;/p&gt;


	&lt;p&gt;O meu problema era, que ao chamar &lt;code&gt;current_user.vehicles.find&lt;/code&gt; ele pesquisava por veículos com &lt;code&gt;owner_type&lt;/code&gt; igual a &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Quando utilizo associações polimórficas, eu preciso de dois campos para isso, o campo que armazena o código, &lt;code&gt;id&lt;/code&gt;, e o campo que armazena o tipo, &lt;code&gt;type&lt;/code&gt;. Como minha associação se chama &lt;code&gt;owner&lt;/code&gt;, meu modelo possui dois campos &lt;code&gt;owner_id&lt;/code&gt; e &lt;code&gt;owner_type&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Mas na hora do meu cadastro, o tipo armazenado no veículo era &lt;code&gt;Manager&lt;/code&gt;, que é um modelo &amp;lt;abbrv title=&quot;Single Table Inheritance&quot;&gt;&lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt;&amp;lt;/abbrv&gt; de &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Para o uso de associações polimórficas com &amp;lt;abbrv title=&quot;Single Table Inheritance&quot;&gt;&lt;span class=&quot;caps&quot;&gt;STI&lt;/span&gt;&amp;lt;/abbrv&gt; eu preciso de um pequeno ajuste no meu modelo &lt;code&gt;Vehicle&lt;/code&gt; para que ele armazene a classe base do objeto que estiver sendo fornecido como &lt;code&gt;owner&lt;/code&gt;, como está no código abaixo:&lt;/p&gt;


&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Vechile&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  belongs_to &lt;span class=&quot;sy&quot;&gt;:owner&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:polymorphic&lt;/span&gt; =&amp;gt; &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;owner_type=&lt;/span&gt;(sType)&lt;tt&gt;
&lt;/tt&gt;     &lt;span class=&quot;r&quot;&gt;super&lt;/span&gt;(sType.to_s.classify.constantize.base_class.to_s)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;User&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  has_many &lt;span class=&quot;sy&quot;&gt;:vehicles&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:as&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:owner&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:dependent&lt;/span&gt; =&amp;gt; &lt;span class=&quot;sy&quot;&gt;:destroy&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Manager&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;User&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Administrator&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;User&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
          </content>  </entry>
</feed>
