<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Minerama - Home</title>
  <id>tag:minerama.net,2009:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  <link href="http://minerama.net/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://minerama.net/" rel="alternate" type="text/html"/>
  <updated>2009-08-01T21:38:20Z</updated>
  <entry xml:base="http://minerama.net/">
    <author>
      <name>joaolins</name>
    </author>
    <id>tag:minerama.net,2008-08-08:16</id>
    <published>2008-08-08T21:48:00Z</published>
    <updated>2009-08-01T21:38:20Z</updated>
    <link href="http://minerama.net/2008/8/8/rails-i18n-catucando" rel="alternate" type="text/html"/>
    <title>Catucando no I18n do rails</title>
<content type="html">
            &lt;p&gt;Depois de dar uma olhada no artigo do &lt;a href=&quot;http://www.nomedojogo.com/2008/07/24/como-funcionara-o-novo-suporte-a-internacionalizacao-no-rails-22/&quot;&gt;Carlos Brando&lt;/a&gt; e do &lt;a href=&quot;http://www.mouseoverstudio.com/blog/?p=105&quot;&gt;Diego Carrion&lt;/a&gt;, resolvi dar uma catucada no I18n.
Comecei com um exemplo simples citado nos blogs dos mesmos. Resolvi ir um pouco mais longe, usar o ActiveRecord e tentar internacionalizar mensagens pré-customizadas do rails e atributos das tabelas.&lt;/p&gt;


	&lt;p&gt;Bom, o resultado do meu arquivo de internacionalização foi esse:&lt;/p&gt;


&amp;lt;script src=&quot;http://gist.github.com/4622.js&quot;&gt;&amp;lt;/script&gt;

Depois com seu arquivo de internacionalização pronto você pode criar um scaffold (scaffold é ótimo para exemplos/testes):
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;script/generate scaffold post title:string description:text author:string&lt;/code&gt;&lt;/pre&gt;

Adicione algumas validações no model post:
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Post &amp;lt; ActiveRecord::Base
  validates_presence_of :title
  validates_length_of   :author, :within =&amp;gt; 3..10
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Depois de rodar os migrations acesse a &lt;span class=&quot;caps&quot;&gt;URL&lt;/span&gt; de posts http://localhost:3000/posts/new tente criar um post sem digitar nada nos campos e veja todas as mensagens devidamente traduzidas.&lt;/p&gt;


Para traduzir os atributos da sua tabela/model você deverá usar algo como:
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;:human_attribute_names =&amp;gt; { 
      :post =&amp;gt; { 
        :title =&amp;gt; &amp;quot;Título&amp;quot; 
      } 
}&lt;/code&gt;&lt;/pre&gt;

Se você quizer ser mais especifico para uma determinada validação de um atributo você pode fazer isso da seguinte forma:
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;:active_record =&amp;gt; {
  :error_messages =&amp;gt; {
     :custom =&amp;gt; { 
        :post =&amp;gt; { 
          :title =&amp;gt; { 
            :blank =&amp;gt; &amp;quot;erro especifico para título em branco no post&amp;quot; 
        }
      }
    }
 }
}
#observe que isso tem que ser feito dentro do 
#contexto do active_record.error_messages&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: 
Para minha surpresa acabei descobrindo um bug que acontece quando você não especifica mensagens default para o ActiveRecord no seu arquivo de localização. O que acontece é que o método full_messages do ActiveRecord procura por mensagens padrões para os validations e  quando não encontra a chave, ele retorna um Array  ao invés  de uma String, por consequência o error_messages_for usa o full_messages esperando dele uma mensagem string, mas recebe esse bendito Array que não deveria ter sido retornado e ao concatenar a string com o Array dá pau. 
O erro na minha opinião é bem bobo mais é uma coisa que deve ser tratada&#8230;&lt;/p&gt;


	&lt;p&gt;Mais informações sobre I18n: &lt;a href=&quot;http://www.artweb-design.de/2008/7/18/the-ruby-on-rails-i18n-core-api&quot;&gt;http://www.artweb-design.de/2008/7/18/the-ruby-on-rails-i18n-core-api&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://minerama.net/">
    <author>
      <name>thiago.arrais</name>
    </author>
    <id>tag:minerama.net,2008-07-23:14</id>
    <published>2008-07-23T15:09:00Z</published>
    <updated>2009-08-21T12:25:45Z</updated>
    <link href="http://minerama.net/2008/7/23/escreveu-mas-n&#227;o-leu" rel="alternate" type="text/html"/>
    <title>Escreveu mas n&#227;o leu</title>
<content type="html">
            &lt;p&gt;Uma boa forma de aprender é simplesmente observar quem já sabe. Muita gente sabe
disso e sabe tomar proveito do trabalho de quem veio antes. Bons pintores gostam
de admirar boas telas, bons músicos geralmente são apaixonados por simplesmente
&lt;em&gt;ouvir&lt;/em&gt; música. Escritores, arquitetos, engenheiros e marceneiros todos aprendem
através dos trabalhos dos mestres do passado. Ora, quem quiser ser médico é até
obrigado a trabalhar algum tempo observando quem já sabe.&lt;/p&gt;

&lt;p&gt;É certo que muitas vezes os aprendizes de médico são simplesmente usados no
lugar de profissionais experientes como mão de obra mais barata e que isso não é
exclusivade da área deles, mas isto é assunto para outro texto. Em outro blog.&lt;/p&gt;

&lt;p&gt;Isto certamente acontece em qualquer área do conhecimento, mas é flagrante como
programadores não gostam de ler código dos outros. Nós não fomos treinados para
isto. É bem possível passar quatro ou cinco anos num curso de graduação na área
de computação e não ler sequer um programa escrito pelos professores. Não falo
de exemplos didáticos, como a definição do
&lt;a href=&quot;http://en.wikipedia.org/wiki/Quicksort&quot;&gt;QuickSort&lt;/a&gt; em
&lt;a href=&quot;http://www.helmutschneider.com/haskell.htm&quot;&gt;duas linhas de Haskell&lt;/a&gt;, mas de
programas vivos de verdade que andam e respiram.
Algo como o &lt;a href=&quot;http://www.haskell.org/ghc/&quot;&gt;compilador GHC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A triste verdade é que a maioria de nós não lê código dos outros, a não ser
quando somos obrigados a mantê-lo. Mais ou menos como a grande parte das
pessoas não lê mais nenhum livro depois que conclui a escola e não precisa mais
ler clássicos de Machado de Assis ou de José de Alencar para passar nas provas.
Dada a imensa quantidade de código livre de que dispomos hoje em dia, isso é de
espantar. Não é escassez de código para leitura, quer dizer que nós simplesmente
não &lt;em&gt;nos damos ao trabalho&lt;/em&gt; de ler. Ao invés disso, preferimos
&lt;a href=&quot;http://haacked.com/archive/2007/10/07/the-greatest-compliment-a-developer-can-receive.aspx&quot;&gt;espernear e xingar&lt;/a&gt;
quando precisamos ler o código de alguém, só porque a pessoa não usou a
linguagem que preferimos, os padrões que preferimos, o estilo de endentação
que preferimos. Só porque não escreveu como nós escreveríamos. Enfim, só porque
não fomos nós que escrevemos.&lt;/p&gt;

&lt;p&gt;Adivinha só! O código provavelmente não está tão ruim quanto pensamos, &lt;em&gt;nós&lt;/em&gt; é
que não estamos acostumados a ler código dos outros. Então, pelo bem de todos os
programadores, vamos levantar nossos traseiros e começar a ler um pouco mais de
código. De quebra ainda vamos aprender mais.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://minerama.net/">
    <author>
      <name>joaolins</name>
    </author>
    <id>tag:minerama.net,2008-07-05:13</id>
    <published>2008-07-05T16:56:00Z</published>
    <updated>2008-07-05T16:57:12Z</updated>
    <link href="http://minerama.net/2008/7/5/ii-esol-palestra-ruby-on-rails-colocando-a-web-nos-trilhos" rel="alternate" type="text/html"/>
    <title>2&#186; ESOL - Palestra: Ruby on Rails colocando a web nos trilhos</title>
<content type="html">
            &lt;div&gt;&amp;lt;object height=&quot;355&quot; width=&quot;425&quot; style=&quot;margin:0px&quot;&gt;&amp;lt;param name=&quot;movie&quot; value=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=iiesol-1215270510567222-8&quot; /&gt;&amp;lt;param name=&quot;allowFullScreen&quot; value=&quot;true&quot; /&gt;&amp;lt;param name=&quot;allowScriptAccess&quot; value=&quot;always&quot; /&gt;&amp;lt;embed allowfullscreen=&quot;true&quot; type=&quot;application/x-shockwave-flash&quot; src=&quot;http://static.slideshare.net/swf/ssplayer2.swf?doc=iiesol-1215270510567222-8&quot; allowscriptaccess=&quot;always&quot; height=&quot;355&quot; width=&quot;425&quot;&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;&lt;div&gt;&lt;a href=&quot;http://www.slideshare.net/?src=embed&quot;&gt;&lt;img src=&quot;http://static.slideshare.net/swf/logo_embd.png&quot; alt=&quot;SlideShare&quot; /&gt;&lt;/a&gt; | &lt;a href=&quot;http://www.slideshare.net/jpaulolins/ruby-on-rails-colocando-a-web-nos-trilhos?src=embed&quot; title=&quot;View Ruby on Rails Colocando a web nos trilhos on SlideShare&quot;&gt;View&lt;/a&gt; | &lt;a href=&quot;http://www.slideshare.net/upload?src=embed&quot;&gt;Upload your own&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;

	&lt;p&gt;Essa semana participei do &lt;a href=&quot;http://tsi.cefetpe.br/esol/&quot; title=&quot;ESOL&quot;&gt;&lt;span class=&quot;caps&quot;&gt;II ESOL&lt;/span&gt;&lt;/a&gt;  que aconteceu no &lt;span class=&quot;caps&quot;&gt;CEFET&lt;/span&gt;-PE. Foi a minha primeira paticipação em um evento de software livre. Tentei passar um pouco do mundo Ruby e Rails  com o intuito de consquistar alguns adeptos e fortalecer a nossa comunidade local. A palestra foi nos moldes do &lt;span class=&quot;caps&quot;&gt;DHH&lt;/span&gt;. Fiz uma breve introdução ao Ruby e um hands on com Rails para mostrar as facilidades de utilizar o framework.&lt;/p&gt;


	&lt;p&gt;O evento estava muito bom e só tenho a agradecer ao pessoal da organização pelo apoio e atenção que me deram durante todo tempo que estive por lá.&lt;/p&gt;


	&lt;p&gt;O código da &lt;a href=&quot;http://www.minerama.net/assets/2008/7/5/esol.zip&quot;&gt;aplicação&lt;/a&gt; para quem quizer brincar.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://minerama.net/">
    <author>
      <name>joaolins</name>
    </author>
    <id>tag:minerama.net,2007-12-18:8</id>
    <published>2007-12-18T21:36:00Z</published>
    <updated>2009-08-21T12:25:03Z</updated>
    <link href="http://minerama.net/2007/12/18/contribuindo-com-o-rails" rel="alternate" type="text/html"/>
    <title>encontrando uma sarna para se co&#231;ar</title>
<content type="html">
            &lt;p&gt;Muita gente se beneficia de software open source e ferramentas livres. Quando isso acaba se tornando constante pode acabar batendo aquele sentimento de que é necessário dar alguma coisa em troca, contribuir. É ruim pensar que existem pessoas trabalhando por trás daquilo e você está simplesmente mamando. Isso certamente não passa pela cabeça de todo mundo, mas provavelmente da maioria dos mineradores.&lt;/p&gt;


	&lt;p&gt;Bom, eu vou contar a história que aconteceu comigo.&lt;/p&gt;


	&lt;p&gt;Tudo começou quando tive um pequeno problema com um sistema que estou fazendo com Rails. Lá é preciso fazer upload de um arquivo &lt;span class=&quot;caps&quot;&gt;XML&lt;/span&gt; em um dado momento. Até ai tudo bem:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;result = xml_parser.parser(params[:file_upload])&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Isso funcionou bem. Todos os testes passaram e eu nem me preocupava com o tipo de objeto que vinha dentro do &lt;code&gt;params[:file_upload]&lt;/code&gt;, tinha em mente que sempre seria um TempFile.&lt;/p&gt;


	&lt;p&gt;Qual não foi minha surpresa quanto foi feito o deploy em produção: &lt;span class=&quot;caps&quot;&gt;BOMBA&lt;/span&gt;! Acabei descobrindo que, nas versões de Ruby anteriores à 1.8.6, somos obrigados a chamar &lt;code&gt;open&lt;/code&gt; no &lt;code&gt;TempFile&lt;/code&gt;.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;result = xml_parser.parser(params[:file_upload].open)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Aparentemente é uma modificação bem pequena. Desta vez a surpresa foi um pouco menor, já que aconteceu em ambiente de testes. Mas não pude deixar de me assustar quando um erro saltou na minha cara:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;NoMethodError: private method `open' called for #&amp;lt;StringIO:0xb7c35020&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Depois da mão na cabeça, veio naturalmente um pouco de depuração e inspeção. Notei que o &lt;code&gt;params[:file_upload]&lt;/code&gt; estava retornando um &lt;code&gt;StringIO&lt;/code&gt; e que a chamada ao método &lt;code&gt;open&lt;/code&gt;, que na documentação do &lt;a href=&quot;http://www.ruby-doc.org/core/&quot;&gt;ruby core&lt;/a&gt; aparece como publico e na verdade  é privado, dava o erro acima. Resolvi tirar a história a limpo. Dei uma lida no código do Rails e acabei descobrindo que se o upload for de arquivos menores do que 10KB um &lt;code&gt;StringIO&lt;/code&gt; é retornado e não um &lt;code&gt;TempFile&lt;/code&gt; como eu esperava.&lt;/p&gt;


	&lt;p&gt;Neste ponto eu já sabia a razão de todos os meus problemas e só faltava resolver, o que fiz foi o seguinte:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;if params[:upload_file].instance_of?(StringIO)
    result = xml_parser.parser(params[:upload_file])
else
    result = xml_parser.parser(params[:upload_file].open)
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Isso funciona para todas as versões de Ruby e tamanhos de arquivo, mas eu não fiquei satisfeito com a solução porque não a achava limpa o bastante e porque esse comportamento do Rails não era documentado.&lt;/p&gt;


	&lt;p&gt;Meu código estava funcionando, mas eu não estava satisfeito. Lembra da história de contribuir e parar de mamar? Pensei: &#8220;é hora de largar a teta!&#8221; Eu estava disposto e há algum tempo já vinha procurando sarna para me coçar, foi só procurar um pouco na internet para saber o que eu precisava fazer para contribuir com o Rails. Encontrei os slides encorajadores de &lt;a href=&quot;http://blog.hasmanythrough.com/2007/5/24/laying-tracks-slides&quot;&gt;Josh Susser&lt;/a&gt; e arregacei as mangas para por as mãos à obra.&lt;/p&gt;


	&lt;p&gt;Depois de ter lido o código, eu sabia exatamente como resolver o problema. Escrevi um email para a &lt;a href=&quot;http://groups.google.com/group/rubyonrails-core&quot;&gt;rails-core&lt;/a&gt; falando do problema e fazendo uma proposta para que o Rails retornasse apenas TempFile, ao invés de tentar fazer uma otimização que pode fazer muita gente ter que coçar a cabeça para resolver . Alguns emails rolaram na lista e o primeiro a me responder foi o &lt;a href=&quot;http://koziarski.com/&quot;&gt;Michael Koziarski&lt;/a&gt; que escreve para  o &lt;a href=&quot;http://therailsway.com/&quot;&gt;The Rails Way&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://koziarski.com/&quot;&gt;Koz&lt;/a&gt; achou a minha proposta interessante, mas ele não conseguiu entender que tipo de bug aquela otimização poderia resolver. Enviei uma  resposta e tentei explicar tudo de forma mais detalhada em outro email para  a lista. Foi quando &lt;a href=&quot;http://giantrobots.thoughtbot.com/&quot;&gt;Jonathan Yurek&lt;/a&gt; me respondeu que todos os meus problemas poderiam ser solucionados de uma forma bem simples usando o poder libertador do duck typing:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;result = xml_parser.parser(params[:upload_file].read)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;A solução proposta pelo Yurek funciona perfeitamente. Eu não tinha prestado atenção, mas o método &lt;code&gt;read&lt;/code&gt; que funciona no &lt;code&gt;StringIO&lt;/code&gt;, também pode ser usado para o &lt;code&gt;TempFile&lt;/code&gt;, pois ele é um Delegate de &lt;code&gt;File&lt;/code&gt; que herda de &lt;code&gt;IO&lt;/code&gt; e possui o método &lt;code&gt;read&lt;/code&gt;.&lt;/p&gt;


	&lt;p&gt;Depois disso Koz respondeu que ainda acharia interessante que isso fosse documentado em algum lugar da &lt;span class=&quot;caps&quot;&gt;API&lt;/span&gt; do Rails e que ele poderia aplicar a modificação caso alguém fizesse o patch. &lt;a href=&quot;http://izumi.plan99.net/blog/index.php/2007/04/07/ruby-on-railss-handling-of-uploaded-files/&quot;&gt;Hongli Lai&lt;/a&gt; também escreveu para a lista informando sobre um post que fez em seu blog ao ter um problema bem parecido com o que eu tive e pareceu solidário a minha proposta.&lt;/p&gt;


	&lt;p&gt;Ainda não mandei o patch para deixar claro o comportamento do Rails ao fazer uploads. Explicar esse comportamento não é difícil. Na verdade o maior problema é saber exatamente o melhor local para colocar a informação. Alguma sugestão?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://minerama.net/">
    <author>
      <name>thiago.arrais</name>
    </author>
    <id>tag:minerama.net,2007-12-13:10</id>
    <published>2007-12-13T02:27:00Z</published>
    <updated>2009-08-21T12:24:43Z</updated>
    <link href="http://minerama.net/2007/12/13/eigenclass" rel="alternate" type="text/html"/>
    <title>Objetos especializados com eigenclass</title>
<content type="html">
            &lt;p&gt;&lt;em&gt;Todo o código incluído neste texto foi projetado para ser executado interativamente no interpretador irb. Você pode copiar os trechos de código daqui para o interpretador na ordem em que aparecem e tudo deve funcionar como esperado. Mas digo logo que eu não garanto que isso aconteça, então use por sua conta e risco.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Todo mundo que programa em Ruby já deve ter definido métodos em classes
singleton ou, para usar um termo mais na moda, em &lt;em&gt;eigenclasses&lt;/em&gt;. Mesmo quem não
sabe o que diabos é isso muito provavelmente já as usou sem saber. Até há bem
pouco tempo atrás eu não tinha a mínima idéia da existência dessas coisas, mas
um dia precisei usá-las. Mais ou menos como todo mundo que programa em Haskell
acaba um dia escrevendo um tutorial sobre Monads, todo mundo que tenta um pouco
de metaprogramação em Ruby acaba escrevendo seus próprios artigos sobre eigenclasses. Essa é a minha tentativa de tornar o assunto um pouco menos obscuro
para mim mesmo e para os demais. Depois eu conto o que estava querendo fazer,
vamos primeiro tentar entender essas classes diferentes.&lt;/p&gt;

&lt;p&gt;Primeiramente, as classes singleton não têm muito a ver com o padrão Singleton. O termo provavelmente foi escolhido pela alusão à unicidade, mas as similaridades páram por aí. Classes singleton são classes que,
como no padrão, estão associadas a um único objeto. Porém, diferente da implementação comum do padrão,
o objeto &lt;em&gt;não&lt;/em&gt; é instância dela, mas de outra classe. O maior problema com o termo
&quot;classe singleton&quot; é a confusão com o nome do padrão, por isso muita gente tem procurado
usar outros termos, como o diferentíssimo &lt;em&gt;eigenclass&lt;/em&gt; (que até hoje eu não sei se deu ou roubou o nome do &lt;a href=&quot;http://eigenclass.org/&quot;&gt;blog do Mauricio Fernandez&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Em Ruby todo objeto possui uma eigenclass associada (para ser realmente preciso, alguns
objetos não possuem, mas vamos assumir que não sabemos disso por enquanto). Os
métodos definidos nesta classe especial ficam disponíveis somente para o objeto
associado e para nenhuma outra instância da mesma classe. Para obter acesso a
ela, pode-se usar a expressão &quot;&lt;code&gt;class &amp;lt;&amp;lt; obj; self; end&lt;/code&gt;&quot; (onde
&lt;code&gt;obj&lt;/code&gt; é o objeto do qual se quer a eigenclass). Quem pretende usar este
tipo de metaprogramação com freqüência pode fazer
&lt;a href=&quot;http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&quot;&gt;como o why&lt;/a&gt;
e guardar esta expressão num método em um arquivo qualquer para referência
futura:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class Object
  def eigenclass
    class &amp;lt;&amp;lt; self; self; end
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A eigenclass é única para cada objeto e diferente da classe a partir da qual o objeto foi criado.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;a = Object.new
b = Object.new
a.class == Object # =&amp;gt; true
a.eigenclass == a.class # =&amp;gt; false
a.eigenclass == b.eigenclass # =&amp;gt; false
a.eigenclass # =&amp;gt; #&amp;lt;Class:#&amp;lt;Object:0xb7ced878&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Isso quer dizer que métodos adicionados e/ou modificados a estas classes estarão
disponíveis para um objeto apenas. Isso é usado com alguma freqüência para
definir métodos de classe, algo que todo mundo já fez uma vez na vida. Classes
são objetos também, instâncias da classe &lt;code&gt;Class&lt;/code&gt;, e possuem uma eigenclass
associada como a maioria dos objetos em Ruby. Por isso podemos definir métodos
de classe:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MyClass = Class.new

MyClass.eigenclass.send :define_method, :instance_count do
  @count || 0
end

MyClass.eigenclass.send :define_method, :instance_count_inc do
  @count = instance_count + 1
end

MyClass.send :define_method, :initialize do
  self.class.instance_count_inc
end

a, b = MyClass.new, MyClass.new
MyClass.instance_count # =&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Muito para engolir de uma vez só? Eu também achei no início, mas descobri que
fica mais fácil quando se tenta entender uma coisa de cada vez. A primeira é o
método &lt;code&gt;define_method&lt;/code&gt; da classe &lt;code&gt;Module&lt;/code&gt; (lembre que a classe &lt;code&gt;Class&lt;/code&gt; herda de
&lt;code&gt;Module&lt;/code&gt;, portanto este método também está disponível para classes). Este método
pode ser usado no lugar da palavra-chave &lt;code&gt;def&lt;/code&gt; para (re)definir métodos
&lt;em&gt;de instância&lt;/em&gt; dinamicamente. Ele recebe um nome e um bloco para ser
usado como corpo do método. Este é um método privativo, ou seja, só pode ser chamado sobre um
objeto por ele mesmo. Para contornarmos esta limitação usamos o &lt;code&gt;send&lt;/code&gt; (por
isso ele aparece ali em cima).&lt;/p&gt;

&lt;p&gt;Uma sutileza do &lt;code&gt;define_method&lt;/code&gt; é que ele define métodos acessíveis a partir
&lt;em&gt;das instâncias&lt;/em&gt; da classe, &lt;em&gt;não da classe&lt;/em&gt; em si. A classe &lt;code&gt;MyClass&lt;/code&gt; é instância de outra
classe diferente (a classe &lt;code&gt;Class&lt;/code&gt;, como está explícito na primeira linha do bloco de código anterior) e se quisermos definir um método para ela,
podemos chamar o &lt;code&gt;define_method&lt;/code&gt; em &lt;code&gt;Class&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Class.send :define_method, :instance_count do
  @count || 0
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O problema dessa abordagem é que define o método para &lt;em&gt;todas&lt;/em&gt; as instâncias da classe &lt;code&gt;Class&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;MyClass.instance_count # =&amp;gt; 2
Object.instance_count # =&amp;gt; 0
Module.instance_count # =&amp;gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obviamente existem instâncias da classe Object (posso contar pelo menos sete só
nos dois trechos de código acima), mas o contador de instâncias não funciona direito porque precisa ser incrementado durante a inicialização dos objetos. Isso pode causar um
pouco de confusão e polui o código das classes que não precisam do recurso de
contagem. Uma coisa que realmente não queremos é poluir os programas dos
outros sem necessidade, então é melhor darmos um jeito de definir o método somente
para as classes em que vamos usá-lo.&lt;/p&gt;

&lt;p&gt;O problema é que se chamarmos &lt;code&gt;define_method&lt;/code&gt; nas classes em si, estaremos
definindo métodos para as instâncias delas e o contador não vai ter muita
utilidade. Por outro lado, se usarmos o &lt;code&gt;define_method&lt;/code&gt; de &lt;code&gt;Class&lt;/code&gt;, vamos
injetar código em classes demais. Para nos tirar dessa sinuca de bico, eis que surge a magnânima eigenclass. Antes de entender o que está acontecendo, vamos limpar a
sujeira:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Class.send :remove_method, :instance_count
Object.instance_count # NoMethodError
MyClass.instance_count # =&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Como pode ver, isso remove o método &lt;code&gt;instance_count&lt;/code&gt; de todas as classes, exceto
da &lt;code&gt;MyClass&lt;/code&gt;. Ela é poupada porque tem o método definido na sua eigenclass, uma
classe intermediária que não aparece na hierarquia de classes, mas que é
consultada antes da classe real e das superclasses quando uma chamada de método
é recebida. Por isso que no trecho de código original em que definimos o
&lt;code&gt;instance_count&lt;/code&gt; as duas primeiras definições são solicitadas à eigenclass, não
à classe. Por outro lado, a última definição é feita para a própria classe
&lt;code&gt;MyClass&lt;/code&gt;, para redefinir o método de inicialização de suas instâncias de modo a
aumentar o contador.&lt;/p&gt;

&lt;p&gt;Tudo isto poderia ter sido feito com o uso da palavra-chave &lt;code&gt;def&lt;/code&gt; e do atalho
&lt;code&gt;def objeto.nome_do_metodo&lt;/code&gt;, mas resolvi usar &lt;code&gt;define_method&lt;/code&gt; porque ilustra
como gerar métodos dinamicamente (e também porque é mais divertido, ora bolas).
A palavra-chave &lt;code&gt;def&lt;/code&gt; pode ser usada para definir métodos em qualquer objeto
(não só classes) e o &lt;code&gt;define_method&lt;/code&gt; também, mas por que alguém em sã
consciência iria querer fazer isso?&lt;/p&gt;

&lt;p&gt;Bom, há várias razões, mas vou descrever apenas o uso que citei no início do
texto. No &lt;a href=&quot;http://mediacloth.rubyforge.org&quot;&gt;Mediacloth&lt;/a&gt; há uma classe
responsável por resolver nomes de página wiki para URLs que geralmente é usada
somente para ter um dos métodos sobre-escritos. Sem a magia negra de eigenclass
os clientes vão normalmente estender esta classe e definir um trecho
de código personalizado para este método:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class MyLinkHandler &amp;lt; MediaWikiLinkHandler
  def link_attributes_for(page)
    { :href =&amp;gt; &quot;http://example.com/wiki/#{page}&quot;, :class =&amp;gt; &quot;internal&quot; }
  end
end

generator = MediaWikiHTMLGenerator.new
generator.link_handler = MyLinkHandler.new
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Não seria bom se o resolvedor de referências pudesse ser definido com uma
chamada de construtor apenas?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;generator = MediaWikiHTMLGenerator.new
generator.link_handler = MediaWikiLinkHandler.new do |page|
  { :href =&amp;gt; &quot;http://example.com/wiki/#{page}&quot;, :class =&amp;gt; &quot;internal&quot; }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Esse efeito pode ser obtido com uma alteração simples no &lt;code&gt;initialize&lt;/code&gt; da classe
original. O código fica parecido com o que está aí embaixo:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class MediaWikiLinkHandler
  def initialize(&amp;amp;block)
    eigenclass.send(:define_method, :link_attributes_for, block) if block
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Com Ruby 1.9 tudo isso vai ficar muito mais fácil, já que o método
&lt;code&gt;define_singleton_method&lt;/code&gt; (que já é usado por muita gente) será incluído na
distribuição padrão, como o
&lt;a href=&quot;http://eustaquiorangel.com/blog/show/454&quot;&gt;Taq já notou&lt;/a&gt;. De qualquer modo, este
exercício ainda continua válido como forma de aprendizado. É para isto que
estamos aqui, não?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://minerama.net/">
    <author>
      <name>thiago.arrais</name>
    </author>
    <id>tag:minerama.net,2007-11-14:3</id>
    <published>2007-11-14T14:42:00Z</published>
    <updated>2009-08-21T12:24:17Z</updated>
    <link href="http://minerama.net/2007/11/14/vamos-minerar" rel="alternate" type="text/html"/>
    <title>Vamos minerar...</title>
<content type="html">
            &lt;p&gt;Você tem garimpado ultimamente?&lt;/p&gt;


	&lt;p&gt;Não, apesar de não ser uma idéia ruim para garantir uma graninha extra, esse texto não é sobre gente que procura ouro nas impurezas no leito de um rio nem sobre minas de diamante. O garimpo de que estamos falando é em busca de algo que é tão valioso quanto ouro e é muito mais fácil de conseguir, mas que é muito mais difícil de guardar: conhecimento.&lt;/p&gt;


	&lt;p&gt;Conhecimento não pode ser depositado num cofre de banco nem esquecido no fundo de uma gaveta junto com alguns papéis velhos. Assim que se tenta fazer isso, ele começa a se desmanchar. Ele não pode ser guardado e recuperado facilmente depois de um tempo, precisa estar em constante evolução. Precisamos sempre ter certeza de que nosso conhecimento está evoluindo, porque se não estiver, estará diminuindo. Funciona mais ou menos como uma motocicleta: quando está indo em frente, está tudo bem, mas começa a cair no instante que pára. Conhecimento que não é usado e exercitado também começa a se desmanchar, desaparecer. Você lembra das aulas de biologia de quando tinha 13 anos?&lt;/p&gt;


	&lt;p&gt;Não? Então acho que deu para entender&#8230;&lt;/p&gt;


	&lt;p&gt;Porém, diferentemente dos bens materiais, o conhecimento não precisa ser fisicamente transferido para ser repassado. Se você der um pouco do seu ouro para um amigo, no final terá necessariamente menos ouro do que antes. Mas se você ensinar algo a ele, não deixa de saber nada do que já sabia. Na verdade é bem possível que passe a entender melhor o assunto depois de ter ensinado outra pessoa.&lt;/p&gt;


	&lt;p&gt;Por isso uma das melhores formas de garantir que o conhecimento não fique parado minguando é distribuí-lo. Quando você ensina outra pessoa, acaba aprendendo mais. Não porque acontece alguma mágica inexplicável, mas porque mais pessoas geram mais idéias e o conhecimento se alimenta de idéias. Quanto maior e mais diversa for a comunidade em torno de um assunto, mais conhecimento é gerado. Isso acaba formando um ciclo de crescimento exponencial: mais pessoas geram mais idéias e mais idéias atraem mais pessoas. Muita gente já aprendeu isso e inventa todo tipo de esquema milaborante para aproveitar este efeito.&lt;/p&gt;


	&lt;p&gt;O Minerama (este blog que você está lendo agora, se ainda não notou) é uma tentativa egoísta e despudorada de tirar proveito deste ciclo de aprendizado por parte de &lt;a href=&quot;http://www.workingwithrails.com/recommendation/new/person/9183-jo-o-paulo-lins&quot;&gt;João Paulo Lins&lt;/a&gt; e &lt;a href=&quot;http://thiagoarrais.wordpress.com&quot;&gt;Thiago Arrais&lt;/a&gt;, dois programadores que se encontraram por meio do grupo &lt;a href=&quot;http://groups.google.com/group/recife-rb&quot;&gt;recife.rb&lt;/a&gt;. Este blog é apenas mais um esquema para multiplicar conhecimento. Como diria o famoso médico Dráuzio Varella, &#8220;podemos [...] afirmar que escrever é uma forma salutar de ampliar nosso banco de dados.&#8221; Por meio da escrita tentamos registrar um pouco do nosso conhecimento para que possamos esquecê-lo temporariamente e permitirmos que um conjunto de informações dê lugar a outro. Além disso, a escrita tem um efeito colateral de facilitar o compartilhamento. Com o tipo de comunicação escrita que vai ser usada aqui não precisamos estar reunidos no mesmo lugar para ensinarmos uns aos outros.&lt;/p&gt;


	&lt;p&gt;Esta iniciativa não é nada altruísta. Solidariedade não é o objetivo principal aqui, mas simplesmente sabemos que é mais fácil e mais rápido aprender em conjunto do que tentar sozinho. Apesar do blog ter sido criado para proveito próprio, talvez este pequeno púlpito seja interessante para outras pessoas também. Nossa idéia é que compartilhemos aqui um pouco do que aprendermos e que possamos aprender com quem se dispuser a oferecer um pouco de sabedoria. Assim todo mundo vai poder se fartar nesse grande banquete de conhecimento que estamos tentando criar.&lt;/p&gt;


	&lt;p&gt;O assunto de todos os dias por aqui vai ser Ruby e coisas rúbicas em geral. Para quem não conhece Ruby,  poderíamos dizer que é uma linguagem de programação dinâmica, com duck typing e continuar falando por horas. Mas isto não seria mais interessante do que &lt;a href=&quot;http://tryruby.hobix.com/&quot;&gt;experimentar você mesmo&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
</feed>

