<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:posterous="http://posterous.com/help/rss/1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
  <channel>
    <title>MushMad!</title>
    <link>http://mushmad.posterous.com</link>
    <description>by Felipe Elias</description>
    <generator>posterous.com</generator>
    <link xmlns="http://www.w3.org/2005/Atom" href="http://posterous.com/api/sup_update#a954ec9fe" type="application/json" rel="http://api.friendfeed.com/2008/03#sup" />
    
    
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/MushroomMadness" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="mushroommadness" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://posterous.superfeedr.com/" /><item>
      <pubDate>Tue, 01 Mar 2011 04:15:00 -0800</pubDate>
      <title>First impressions of Redis</title>
      <link>http://mushmad.posterous.com/first-impressions-of-redis</link>
      <guid>http://mushmad.posterous.com/first-impressions-of-redis</guid>
      <description>
        <![CDATA[<p>
	<p><em>In my spare time (1h per day), I&rsquo;ll try to study a new thing every day and after that, create a post about it in this blog. The &ldquo;new&rdquo; thing of the week is Redis. At the same time, I&rsquo;ll practice my writing (and english) skills, so if something is unclear, just leave a comment. I&rsquo;ll appreciate it.</em></p>

<h2>Goals</h2>

<p>To not forget why I&rsquo;m spending this hour, I set some goals before I start. And they are:</p>

<ul>
<li>What is <a href="http://redis.io/">Redis</a>?</li>
<li>How can I use <a href="http://redis.io/">Redis</a>?</li>
<li>What can I use <a href="http://redis.io/">Redis</a> for?</li>
</ul>


<h2>What is Redis?</h2>

<p><a href="http://redis.io/">Redis</a> is a key-value store, also known as NoSQL database. Basically it stores data as &lsquo;value&rsquo; inside a &lsquo;key&rsquo;. This data can later be retrieved only if we know the exact key used to store it.</p>

<h2>Installation</h2>

<p>I don&rsquo;t want to detail the installation process, but if you&rsquo;re using a Mac and <a href="https://github.com/mxcl/homebrew">Homebrew</a>, just type <code>brew install redis</code> and that&rsquo;s it!</p>

<h2>How to use Redis</h2>

<p>The basic commands are SET and GET.</p>

<p>SET stores the data into a key. For example:</p>

<div class="CodeRay">
  <div class="code"><pre>SET server:name &quot;fido&quot;</pre></div>
</div>


<p>will store the value &ldquo;fido&rdquo; inside the &ldquo;server:name&rdquo; key and we can retrieve that key later with the GET command:</p>

<div class="CodeRay">
  <div class="code"><pre>GET server:name
=&gt; &quot;fido&quot;</pre></div>
</div>


<p>If you try to retrieve a non existent key, <a href="http://redis.io/">Redis</a> will return null:</p>

<div class="CodeRay">
  <div class="code"><pre>GET server:ip
=&gt; null</pre></div>
</div>


<p>And the opposite of SET is DEL, that deletes the given key from the database.</p>

<p><a href="http://redis.io/">Redis</a> also has other cool stuff like Lists, Sets, Hashs and Ordered Sets. You can try this stuff online on <a>http://try.redis-db.com</a> (highly recommended) or check out the documentation online on <a href="http://redis.io/documentation">http://redis.io/documentation</a>.</p>

<h2>What can I use Redis for?</h2>

<p>Anything? I don&rsquo;t think so, but there is collection of <a href="http://redis.io/">Redis</a> use cases in this <a href="http://www.paperplanes.de/2010/2/16/a_collection_of_redis_use_cases.html">post</a>. Some of them I like the most are <a href="http://sunilarora.org/url-shortener-service-using-redis">URL Shortener Service</a> and <a href="http://www.lukemelia.com/blog/archives/2010/01/17/redis-in-practice-whos-online/">Who is online</a>.</p>

<h2>Conclusion</h2>

<p>I&rsquo;m still thinking on what will be my <a href="http://redis.io/">Redis</a> use case. Anyway, I see a lot of projects using Redis to manage background tasks, but what I can conclude now is that <a href="http://redis.io/">Redis</a> is <strong>fast!!!</strong>. Try to run <code>redis-benchmark -q -n 100000</code> in the command line and you&rsquo;ll see how fast it is.</p>

<p>And that&rsquo;s it. The next post will be about <a href="http://redis.io/">Redis</a> as well, probably about <a href="https://github.com/defunkt/resque">resque</a>, or something related.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/first-impressions-of-redis">Permalink</a> 

	| <a href="http://mushmad.posterous.com/first-impressions-of-redis#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Mon, 03 Jan 2011 10:17:00 -0800</pubDate>
      <title>A few terminal tips</title>
      <link>http://mushmad.posterous.com/a-few-terminal-tips</link>
      <guid>http://mushmad.posterous.com/a-few-terminal-tips</guid>
      <description>
        <![CDATA[<p>
	<h2>Lists</h2>

<p>Lists are very useful. Take a look a this example:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="other">$</span> mv README<span class="other">.</span>txt README<span class="other">.</span>markdown</pre></div>
</div>


<p>A better way to do this using lists is:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="other">$</span> mv README<span class="other">.</span><span class="other">{</span>txt<span class="other">,</span>markdown<span class="other">}</span></pre></div>
</div>


<p>This will do the same thing as the first example.</p>

<h2>Bang-bang</h2>

<p>&ldquo;!!&rdquo; repeats the last command. This is useful in situations like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="other">$</span> cp some_file<span class="other">.</span>txt <span class="other">/</span>some_directory_you_do_not_have_permission
cp<span class="other">:</span> some_file<span class="other">.</span>txt<span class="other">:</span> Permission denied</pre></div>
</div>


<p>Aw crap! Instead of typing everything again or type combos like <code>up-arrow + crtl-A + sudo</code>, just type:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="other">$</span> sudo <span class="other">!</span><span class="other">!</span></pre></div>
</div>


<p>Bang-bang! Problem solved.</p>

<p>Another bang-like thing is the <code>!$</code>. This repeats the very last argument of the previous command. For example:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="other">$</span> touch README<span class="other">.</span>txt
<span class="other">$</span> mate README<span class="other">.</span>txt</pre></div>
</div>


<p>Too much typing. Why not use !$ instead?</p>

<div class="CodeRay">
  <div class="code"><pre><span class="other">$</span> touch README<span class="other">.</span>txt
<span class="other">$</span> mate <span class="other">!</span><span class="other">$</span></pre></div>
</div>


<p>Done.</p>

<p>And you, what are your terminal tricks?</p>
	
</p>

<p><a href="http://mushmad.posterous.com/a-few-terminal-tips">Permalink</a> 

	| <a href="http://mushmad.posterous.com/a-few-terminal-tips#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Tue, 02 Nov 2010 10:55:00 -0700</pubDate>
      <title>A better Javascript confirmation message</title>
      <link>http://mushmad.posterous.com/a-better-javascript-confirmation-message</link>
      <guid>http://mushmad.posterous.com/a-better-javascript-confirmation-message</guid>
      <description>
        <![CDATA[<p>
	<p>I really don&rsquo;t like the way we write normal Javascript confirmation messages, like this:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="kw">if</span> ( confirm(<span class="s"><span class="dl">'</span><span class="k">Are you sure?</span><span class="dl">'</span></span>) ) {
  <span class="c">// do the stuff</span>
}</pre></div>
</div>


<p>So, I was wondering if this could be done in a more &lsquo;functional&rsquo; way, like this:</p>

<div class="CodeRay">
  <div class="code"><pre>confirmIf(<span class="s"><span class="dl">'</span><span class="k">Are you sure?</span><span class="dl">'</span></span>, <span class="kw">function</span>() {
  <span class="c">// do the stuff</span>
});</pre></div>
</div>


<p>Much better I think. Here is the function:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="kw">function</span> <span class="fu">confirmIf</span> ( message, callback ) {       
  <span class="kw">if</span> ( confirm(message) ) {
    <span class="kw">return</span> callback();
  }
  <span class="kw">return</span> <span class="pc">false</span>;
}</pre></div>
</div>


<p>What do you think?</p>
	
</p>

<p><a href="http://mushmad.posterous.com/a-better-javascript-confirmation-message">Permalink</a> 

	| <a href="http://mushmad.posterous.com/a-better-javascript-confirmation-message#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Fri, 22 Oct 2010 08:33:00 -0700</pubDate>
      <title>I - Jogos em Javascript - Desenhando com canvas</title>
      <link>http://mushmad.posterous.com/i-jogos-em-javascript-desenhando-com-canvas</link>
      <guid>http://mushmad.posterous.com/i-jogos-em-javascript-desenhando-com-canvas</guid>
      <description>
        <![CDATA[<p>
	<p>Estou iniciando meus estudos com desenvolivmento de jogos em Javascript e pretendo iniciar uma série de posts relacionados ao que aprendi durante esse tempo.</p>

<p>Para começar, veremos um pouco da API do <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> e de como ela pode nos ajudar a desenvolver jogos em Javascript.</p>

<h2>Porque canvas?</h2>

<p>Falando em jogos no browser, um elemento fundamental a se entender é o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a>. Ele que vai nos permitir desenhar objetos na tela e também movimentá-los, criar animações e etc&hellip;</p>

<p>Além do mais, ele é compatível com os browsers mais modernos (IE9, Firefox, Safari, Chrome), e para os mais antigos, existe uma <a href="http://excanvas.sourceforge.net/">biblioteca que contorna esse problema</a>.</p>

<h2>Desenhos simples</h2>

<p>Para desenhar com o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a>, primeiro precisamos do elemento no nosso HTML, como esse aqui:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="dt">&lt;!DOCTYPE html&gt;</span>
<span class="ta">&lt;html&gt;</span>
  <span class="ta">&lt;head&gt;</span>
    <span class="ta">&lt;title&gt;</span>Canvas<span class="ta">&lt;/title&gt;</span>
  <span class="ta">&lt;/head&gt;</span>
  <span class="ta">&lt;body&gt;</span>
    <span class="ta">&lt;canvas</span> <span class="an">id</span>=<span class="s"><span class="dl">&quot;</span><span class="k">canvas</span><span class="dl">&quot;</span></span> <span class="an">width</span>=<span class="s"><span class="dl">&quot;</span><span class="k">960</span><span class="dl">&quot;</span></span> <span class="an">height</span>=<span class="s"><span class="dl">&quot;</span><span class="k">480</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>
    <span class="ta">&lt;/canvas&gt;</span>
    <span class="ta">&lt;script</span> <span class="an">type</span>=<span class="s"><span class="dl">&quot;</span><span class="k">text/javascript</span><span class="dl">&quot;</span></span> <span class="an">charset</span>=<span class="s"><span class="dl">&quot;</span><span class="k">utf-8</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>
      // Codigo aqui
    <span class="ta">&lt;/script&gt;</span>
  <span class="ta">&lt;/body&gt;</span>
<span class="ta">&lt;/html&gt;</span></pre></div>
</div>


<p>Feito isso, podemos manipular o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> através do Javascript, veja esse exemplo:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="kw">var</span> canvas = document.getElementById(<span class="s"><span class="dl">&quot;</span><span class="k">canvas</span><span class="dl">&quot;</span></span>);
<span class="kw">var</span> paper = canvas.getContext(<span class="s"><span class="dl">&quot;</span><span class="k">2d</span><span class="dl">&quot;</span></span>);

<span class="kw">function</span> <span class="fu">draw</span>() {
  paper.fillRect(<span class="i">10</span>, <span class="i">10</span>, <span class="i">100</span>, <span class="i">100</span>);
}

draw();</pre></div>
</div>


<p>Algumas coisas que temos que entender aqui. Primeiro, existe o elemento HTML do <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> na primeira linha. Depois, escolhemos um contexto para o nosso <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> (no caso 2d) com o getContext(). Esse contexto 2d que vai definir qual a <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">API</a> a ser utilizada nos nossos desenhos.</p>

<p>Um método dessa API é o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-fillrect">fillRect</a>, que basicamente desenha um retângulo na tela. Os dois primeiros parâmetros são a posição na tela, no caso X e Y, e os dois últimos são o tamanho do nosso retângulo (um quadrado, na verdade). Todos os parâmetros são em pixels.</p>

<p>Não vou entrar em detalhes de toda a API de desenho do <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a>, mais informações você pode conferir <a href="http://sixrevisions.com/html/canvas-element/">aqui</a>. Mas existe uma em especial que quero dar mais foco. Veja o exemplo abaixo:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="kw">function</span> <span class="fu">draw</span>() {
  paper.beginPath();
  paper.moveTo(<span class="i">10</span>, <span class="i">0</span>);
  paper.lineTo(<span class="i">20</span>, <span class="i">30</span>);
  paper.lineTo(<span class="i">0</span>, <span class="i">30</span>);
  paper.closePath();
  paper.stroke();
}

draw();</pre></div>
</div>


<p>No exemplo acima, estamos criando um desenho mais customizado. O método <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-beginpath">beginPath()</a> diz ao <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> que vamos começar um desenho usando as APIs do PATH, que podemos associar a um &ldquo;lápis&rdquo; na tela.</p>

<p>O <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-moveto">moveTo()</a> move nosso &ldquo;lápis&rdquo; para o ponto 10,0 (x,y). A partir do ponto 10,0, desenhamos uma linha com o método <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-lineto">lineTo()</a> para o ponto 20,30. Neste momento, é como se fosse desenhada uma linha mesmo. O mesmo fazemos depois para o ponto 0,30. O método <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-closepath">closePath()</a> fecha automaticamente nosso desenho para o ponto inicial, no caso 10,0.</p>

<p>O método <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-stroke">stroke()</a> finaliza o desenho. Se você não chamá-lo ao final, seu desenho não aparecerá na tela. Isso porque o método <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-lineto">lineTo()</a> apenas adiciona as coordenadas numa fila, que depois são finalmente desenhadas com o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-stroke">stroke()</a>.</p>

<h2>Animando</h2>

<p>Para darmos mais vida ao nosso player, utilizaremos dois métodos do <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a>: translate e rotate.</p>

<div class="CodeRay">
  <div class="code"><pre><span class="kw">function</span> <span class="fu">draw</span>() {
  paper.translate(<span class="i">30</span>, <span class="i">30</span>);
  paper.rotate(<span class="fl">0.1</span>);
  <span class="c">//...</span>
}</pre></div>
</div>


<p>O método <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-translate">translate()</a> move o <strong><a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> inteiro</strong> para a posição X,Y passada nos argumentos. Já o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-rotate">rotate()</a>, gira o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> inteiro para o ângulo passado (em radianos). Essas duas chamadas dos métodos devem ser colocadas <strong>antes</strong> do <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-beginpath">beginPath()</a>. Se colocarmos as chamadas depois do <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-stroke">stroke()</a>, nada vai acontecer, porque as transformações com <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-translate">translate()</a> e <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-rotate">rotate()</a> só afetam os próximos desenhos.</p>

<p>Vamos trocar a chamada do draw() no fim do nosso script para isso:</p>

<div class="CodeRay">
  <div class="code"><pre>setInterval(draw, <span class="i">200</span>);</pre></div>
</div>


<p>Agora você deve ter visto que nosso player se &ldquo;move&rdquo; na tela, mas não do jeito que esperávamos, porque o desenho antigo não é apagado da tela. Isso porque a cada 200 milisegundos estamos criando um novo desenho e não movendo o player de verdade. Para corrigir isso, chamamos o método <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html#dom-context-2d-clearrect">clearRect(x, y, width, height)</a> no início do método draw(). Esse método limpa todos os pixels dentro do retângulo passado.</p>

<p>O código final você pode ver abaixo:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="kw">var</span> canvas = document.getElementById(<span class="s"><span class="dl">&quot;</span><span class="k">canvas</span><span class="dl">&quot;</span></span>);
<span class="kw">var</span> paper = canvas.getContext(<span class="s"><span class="dl">&quot;</span><span class="k">2d</span><span class="dl">&quot;</span></span>);

<span class="kw">function</span> <span class="fu">draw</span>() {
  paper.clearRect(<span class="i">0</span>, <span class="i">0</span>, <span class="i">960</span>, <span class="i">480</span>);
  paper.translate(<span class="i">30</span>, <span class="i">30</span>);
  paper.rotate(<span class="fl">0.1</span>);
  paper.beginPath();
  paper.moveTo(<span class="i">10</span>, <span class="i">0</span>);
  paper.lineTo(<span class="i">20</span>, <span class="i">30</span>);
  paper.lineTo(<span class="i">0</span>, <span class="i">30</span>);
  paper.closePath();
  paper.stroke();
}

setInterval(draw, <span class="i">200</span>);</pre></div>
</div>


<p>Essa ainda não é a forma ideal de movermos nosso player na tela, principalmente porque estamos movendo o <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a> inteiro e não só o player. Se tivermos outros desenhos na tela, você vai ver que eles se moverão junto com o nosso player, e isso não é o ideal. Falarei mais sobre este problema e como evitá-lo no próximo post da série.</p>

<h2>Concluindo</h2>

<p>Até aqui conseguimos entender um pouco do <a href="http://dev.w3.org/html5/canvas-api/canvas-2d-api.html">canvas</a>, e de como sua API nos permite fazer coisas bem interessantes. Também já conseguimos ter uma boa idéia de como vai ser nosso jogo e de como podemos estruturá-lo.</p>

<p>No próximo post continuaremos nossa série, falando mais sobre a estrutura do nosso jogo e de como manipular nosso player com o teclado.</p>

<p>Até lá!</p>
	
</p>

<p><a href="http://mushmad.posterous.com/i-jogos-em-javascript-desenhando-com-canvas">Permalink</a> 

	| <a href="http://mushmad.posterous.com/i-jogos-em-javascript-desenhando-com-canvas#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Thu, 05 Aug 2010 15:56:00 -0700</pubDate>
      <title>HTML5 contenteditable + jQuery</title>
      <link>http://mushmad.posterous.com/html5-contenteditable-jquery</link>
      <guid>http://mushmad.posterous.com/html5-contenteditable-jquery</guid>
      <description>
        <![CDATA[<p>
	<p>O <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">contenteditable</a> é uma das novas funcionalidades do <a href="http://dev.w3.org/html5/spec/Overview.html">HTML5</a>. Ela permite que o usuário consiga editar o conteúdo do elemento, como se fosse um daquels editores WYSIWYG. Para utilizar, basta adicionar o atributo <code>contenteditable="true"</code> no elemento:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="ta">&lt;ul</span> <span class="an">contenteditable</span>=<span class="s"><span class="dl">&quot;</span><span class="k">true</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>
  <span class="ta">&lt;li&gt;</span>Item 1<span class="ta">&lt;/li&gt;</span>
  <span class="ta">&lt;li&gt;</span>Item 2<span class="ta">&lt;/li&gt;</span>
<span class="ta">&lt;/ul&gt;</span></pre></div>
</div>


<p>Neste exemplo, ao clicar na lista, aparecerá algo parecido com uma <code>textarea</code>, tornando o conteúdo editável, como se fosse um editor de textos.</p>

<h2>Adicionando eventos</h2>

<p>Como saber o momento que o usuário terminou de editar o texto dentro do nosso conteúdo editável? Simples. Como o elemento se transforma em uma &ldquo;<code>textarea</code>&rdquo;, podemos utilizar os mesmos eventos de um input padrão do HTML. Veja este exemplo:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="dt">&lt;!DOCTYPE html&gt;</span>
<span class="ta">&lt;html&gt;</span>
  <span class="ta">&lt;head&gt;</span>
    <span class="ta">&lt;title&gt;</span>contenteditable<span class="ta">&lt;/title&gt;</span>
    <span class="ta">&lt;style</span> <span class="an">type</span>=<span class="s"><span class="dl">&quot;</span><span class="k">text/css</span><span class="dl">&quot;</span></span> <span class="an">media</span>=<span class="s"><span class="dl">&quot;</span><span class="k">screen</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>
      *[contenteditable]:hover {
        background-color: #F9F9F9;
      }
    <span class="ta">&lt;/style&gt;</span>
  <span class="ta">&lt;/head&gt;</span>
  <span class="ta">&lt;body&gt;</span>
    <span class="ta">&lt;div</span> <span class="an">contenteditable</span>=<span class="s"><span class="dl">&quot;</span><span class="k">true</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>Edit me!<span class="ta">&lt;/div&gt;</span>
    <span class="ta">&lt;ul</span> <span class="an">contenteditable</span>=<span class="s"><span class="dl">&quot;</span><span class="k">true</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>
      <span class="ta">&lt;li&gt;</span>Item 1<span class="ta">&lt;/li&gt;</span>
      <span class="ta">&lt;li&gt;</span>Item 2<span class="ta">&lt;/li&gt;</span>
    <span class="ta">&lt;/ul&gt;</span>
    <span class="ta">&lt;div</span> <span class="an">id</span>=<span class="s"><span class="dl">&quot;</span><span class="k">log</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span><span class="ta">&lt;/div&gt;</span>
    <span class="ta">&lt;script</span> <span class="an">type</span>=<span class="s"><span class="dl">&quot;</span><span class="k">text/javascript</span><span class="dl">&quot;</span></span> <span class="an">src</span>=<span class="s"><span class="dl">&quot;</span><span class="k">http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span><span class="ta">&lt;/script&gt;</span>
    <span class="ta">&lt;script</span> <span class="an">type</span>=<span class="s"><span class="dl">&quot;</span><span class="k">text/javascript</span><span class="dl">&quot;</span></span> <span class="an">charset</span>=<span class="s"><span class="dl">&quot;</span><span class="k">utf-8</span><span class="dl">&quot;</span></span><span class="ta">&gt;</span>
      $(function() {
        $(&quot;[contenteditable]&quot;).bind('focus', function() {
          $(this).data('original-text', $(this).text());
          log(this, 'focus');
        });

        $(&quot;[contenteditable]&quot;).bind('blur', function() {
          log(this, 'texto alterado de &quot;' + $(this).data('original-text') + '&quot; para &quot;' + $(this).text());
        });
      });

      function log (el, msg) {
        console.log(el, msg);
        $(&quot;#log&quot;).append(&quot;-<span class="er">&gt;</span> &quot; + msg + &quot;<span class="ta">&lt;br</span><span class="ta">/&gt;</span>&quot;);
      }
    <span class="ta">&lt;/script&gt;</span>
  <span class="ta">&lt;/body&gt;</span>
<span class="ta">&lt;/html&gt;</span></pre></div>
</div>


<p>Ao clicar na <code>div</code> com o atributo <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">contenteditable</a> por exemplo, é disparado o evento <code>onfocus</code>. Se logo após clicarmos em outra área do HTML (fora da nossa <code>div</code>), é disparado o evento <code>onblur</code>. Isso você pode acompanhar no log logo abaixo.</p>

<p>No Javascript logo no fim do arquivo, estamos adicionando eventos (com <a href="http://jquery.com/">jQuery</a>) a todos os elementos que tiverem o atributo <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">contenteditable</a>. Os eventos são <code>focus</code> e <code>blur</code>, respectivamente relacionados aos eventos nativos do Javascript <code>onfocus</code> e <code>onblur</code>. Um outro exemplo pode ser <a href="http://html5demos.com/contenteditable">visto aqui</a>.</p>

<p>Um curiosidade é que esta funcionalidade existe desde o IE 5.5, inclusive foi a Microsoft que padronizou e implementou esta funcionalidade. Mas como a documentação era apenas superficial, só agora esta funcionalidade está sendo padronizada pelo <a href="http://www.w3.org">W3C</a>.</p>

<p>Outro detalhe é que é possível executar coisas como <code>execCommand</code> dentro de elementos com <a href="http://www.w3.org/TR/html5/editing.html#contenteditable">contenteditable</a>. Essass funções são utilizadas pelos editores WYSIWYG, para adicionar negrito, itálico, etc&hellip; essas coisas.</p>

<p>Mais detalhes sobre o atributo podem ser conferidos <a href="http://blog.whatwg.org/the-road-to-html-5-contenteditable">neste post</a>.</p>

<p><strong>Update</strong>: O <a href="http://posterous.com/people/5emgkux1ez2p">Juan Maiz</a> deu uma dica legal de um editor WYSIWYG totalmente em HTML5, segue o link: <a href="http://aloha-editor.com/">http://aloha-editor.com/</a></p>
	
</p>

<p><a href="http://mushmad.posterous.com/html5-contenteditable-jquery">Permalink</a> 

	| <a href="http://mushmad.posterous.com/html5-contenteditable-jquery#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Tue, 03 Aug 2010 15:06:00 -0700</pubDate>
      <title>Notas sobre Struct</title>
      <link>http://mushmad.posterous.com/notas-sobre-struct</link>
      <guid>http://mushmad.posterous.com/notas-sobre-struct</guid>
      <description>
        <![CDATA[<p>
	<p>Existem duas formas de se criar uma <a href="http://ruby-doc.org/core-1.8.7/index.html">Struct</a> em <a href="http://www.ruby-lang.org/en/">Ruby</a>. Uma delas é simplesmente atribuindo a uma constante:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="co">Color</span> = <span class="co">Struct</span>.new(<span class="sy">:color</span>, <span class="sy">:hex</span>) <span class="r">do</span>
  <span class="r">def</span> <span class="fu">metodo</span>
  <span class="r">end</span>
<span class="r">end</span></pre></div>
</div>


<p>E a outra seria com herança:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="r">class</span> <span class="cl">ComplexColor</span> &lt; <span class="co">Struct</span>.new(<span class="sy">:color</span>, <span class="sy">:hex</span>)
  <span class="r">def</span> <span class="fu">metodo</span>
  <span class="r">end</span>
<span class="r">end</span></pre></div>
</div>


<p>Notei que muita gente ou fazia de um jeito, ou fazia de outro, e fui atrás pra ver se realmente tinha alguma diferença, ou se era apenas uma questão de &ldquo;sintax sugar&rdquo;. E tem diferença!</p>

<p>A diferença principal é que, quando criamos uma struct com herança, estamos colocando uma <a href="http://ruby-doc.org/core-1.8.7/index.html">struct</a> anônima na hierarquia de ancestrais do nosso objeto:</p>

<div class="CodeRay">
  <div class="code"><pre>&gt;&gt; Color<span class="other">.</span>ancestors
<span class="other">=</span>&gt; <span class="other">[</span>Color<span class="other">,</span> Struct<span class="other">,</span> Enumerable<span class="other">,</span> Object<span class="other">,</span> Kernel<span class="other">]</span> <span class="c"># herança normal</span>

&gt;&gt; ComplexColor<span class="other">.</span>ancestors
<span class="other">=</span>&gt; <span class="other">[</span>ComplexColor<span class="other">,</span> <span class="c">#&lt;Class:0x100cb7838&gt;, Struct, Enumerable, Object, Kernel] # ahá!</span></pre></div>
</div>


<p>E isso faz também com que os membros (métodos getters e setters) da <a href="http://ruby-doc.org/core-1.8.7/index.html">struct</a> fiquem na classe pai:</p>

<div class="CodeRay">
  <div class="code"><pre>&gt;&gt; Color<span class="other">.</span>instance_methods<span class="other">(</span><span class="fu">false</span><span class="other">)</span>
<span class="other">=</span>&gt; <span class="other">[</span><span class="s"><span class="dl">&quot;</span><span class="k">color</span><span class="dl">&quot;</span></span><span class="other">,</span> <span class="s"><span class="dl">&quot;</span><span class="k">hex</span><span class="dl">&quot;</span></span><span class="other">,</span> <span class="s"><span class="dl">&quot;</span><span class="k">color=</span><span class="dl">&quot;</span></span><span class="other">,</span> <span class="s"><span class="dl">&quot;</span><span class="k">hex=</span><span class="dl">&quot;</span></span><span class="other">,</span> <span class="s"><span class="dl">&quot;</span><span class="k">description</span><span class="dl">&quot;</span></span><span class="other">]</span> <span class="c"># normal</span>

&gt;&gt; ComplexColor<span class="other">.</span>instance_methods<span class="other">(</span><span class="fu">false</span><span class="other">)</span>
<span class="other">=</span>&gt; <span class="other">[</span><span class="s"><span class="dl">&quot;</span><span class="k">description</span><span class="dl">&quot;</span></span><span class="other">]</span> <span class="c"># ops?</span>

&gt;&gt; ComplexColor<span class="other">.</span>superclass<span class="other">.</span>instance_methods<span class="other">(</span><span class="fu">false</span><span class="other">)</span>
<span class="other">=</span>&gt; <span class="other">[</span><span class="s"><span class="dl">&quot;</span><span class="k">color</span><span class="dl">&quot;</span></span><span class="other">,</span> <span class="s"><span class="dl">&quot;</span><span class="k">hex</span><span class="dl">&quot;</span></span><span class="other">,</span> <span class="s"><span class="dl">&quot;</span><span class="k">color=</span><span class="dl">&quot;</span></span><span class="other">,</span> <span class="s"><span class="dl">&quot;</span><span class="k">hex=</span><span class="dl">&quot;</span></span><span class="other">]</span> <span class="c"># ahá!</span></pre></div>
</div>


<p>Claro que isso não faz muita diferença, afinal ao chamar qualquer método dos membros da <a href="http://ruby-doc.org/core-1.8.7/index.html">struct</a>, o <a href="http://www.ruby-lang.org/en/">Ruby</a> vai subir um nível na hierarquia se ele não achar o método na classe atual.</p>

<p>Agora se você gosta de fazer micro-otimizações, talvez isso faça algum sentido, já que estamos economizando alguns pentelhésimos de segundo nas execuções sem herança.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/notas-sobre-struct">Permalink</a> 

	| <a href="http://mushmad.posterous.com/notas-sobre-struct#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Sun, 01 Aug 2010 18:33:00 -0700</pubDate>
      <title>Atualizando o ZSH no OS X com homebrew</title>
      <link>http://mushmad.posterous.com/atualizando-o-zsh-no-os-x-com-homebrew</link>
      <guid>http://mushmad.posterous.com/atualizando-o-zsh-no-os-x-com-homebrew</guid>
      <description>
        <![CDATA[<p>
	<p>Recentemente tive que atualizar a versão do meu <a href="http://www.zsh.org/">zsh</a> com o <a href="http://mxcl.github.com/homebrew/">homebrew</a>, e não foi tão fácil como eu imaginei. Isso porque a versão instalada pelo <a href="http://mxcl.github.com/homebrew/">homebrew</a>, não é instalada no diretório padrão <code>/bin</code>.</p>

<p>Encontrei a solução e fiz um tutorial rápido, caso você também encontre esse problema.</p>

<p>Instale o <a href="http://www.zsh.org/">zsh</a> com o <a href="http://mxcl.github.com/homebrew/">homebrew</a></p>

<div class="CodeRay">
  <div class="code"><pre>brew install zsh</pre></div>
</div>


<p>Depois de tudo compilado e instalado (thanks <a href="http://mxcl.github.com/homebrew/">homebrew</a>), você terá que alterar o shell padrão para usar o novo <a href="http://www.zsh.org/">zsh</a> com o comando:</p>

<div class="CodeRay">
  <div class="code"><pre>chsh -s /usr/local/bin/zsh</pre></div>
</div>


<p>Neste momento aparece a mensagem &ldquo;<code>chsh: /usr/local/bin/zsh: non-standard shell</code>&rdquo;. Isso acontece porque a versão do <a href="http://mxcl.github.com/homebrew/">homebrew</a> não está habilitada para ser usada como shell. Para habilitar, adicione a seguinte linha no fim do arquivo <code>/etc/shells</code>:</p>

<div class="CodeRay">
  <div class="code"><pre># /etc/shells
/usr/local/bin/zsh</pre></div>
</div>


<p>Feito isso, altere o shell padrão com:</p>

<div class="CodeRay">
  <div class="code"><pre>chsh -s /usr/local/bin/zsh</pre></div>
</div>


<p>Feche e abra novamente o terminal e o zsh está instalado.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/atualizando-o-zsh-no-os-x-com-homebrew">Permalink</a> 

	| <a href="http://mushmad.posterous.com/atualizando-o-zsh-no-os-x-com-homebrew#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Wed, 09 Jun 2010 20:27:00 -0700</pubDate>
      <title>Métricas no Rails com metric_fu</title>
      <link>http://mushmad.posterous.com/metricas-no-rails-com-metricfu</link>
      <guid>http://mushmad.posterous.com/metricas-no-rails-com-metricfu</guid>
      <description>
        <![CDATA[<p>
	<p><em><em>Update:</em> Parece que a gem <code>Saikuro</code> original não funciona bem com a <code>metric_fu</code>, por isso é necessário instalar o fork do <a href="http://github.com/devver/saikuro">devver</a> e também atualizar a configuração do metric_fu na linha 10. Confira logo abaixo.</em></p>

<p><em>Update2: Atualizado para a versão 1.4.0 da gem metric_fu.</em></p>

<p><code>metric_fu</code> é uma gem que serve pra analisar o código da sua aplicação. Ela faz a análise utilizando diversas <a href="http://en.wikipedia.org/wiki/Software_metric">métricas</a> conhecidas, como por exemplo, <a href="http://en.wikipedia.org/wiki/Code_coverage">cobertura de testes</a>, <a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity">complexidade ciclomática</a>, <a href="http://en.wikipedia.org/wiki/Code_smell">code smells</a> e etc&hellip;</p>

<p>Essa gem é um conjunto de outras gems, em que cada uma delas é responsável por um tipo de métrica. O que a <code>metric_fu</code> faz, é agrupar todas em um lugar só, provendo um html único para acessar as métricas geradas.</p>

<h2>Instalando</h2>

<p>Para instalar a gem e suas dependências, basta rodar o comando <code>gem install</code>.</p>

<div class="CodeRay">
  <div class="code"><pre>gem install metric_fu
=&gt; <span class="co">Successfully</span> installed metric_fu-<span class="fl">1.4</span>.<span class="i">0</span>
=&gt; <span class="i">1</span> gem installed</pre></div>
</div>


<p>Depois de alguns testes, descobri que a gem Saikuro original não funciona bem com o <code>metric_fu</code> (sequer rodou as análises do código), para corrigir isso, instale o fork do <code>devver</code> (<a href="http://github.com/devver/saikuro">link no github</a>):</p>

<div class="CodeRay">
  <div class="code"><pre>gem install devver-<span class="co">Saikuro</span>
=&gt; <span class="co">Successfully</span> installed devver-<span class="co">Saikuro</span>-<span class="fl">1.2</span>.<span class="i">0</span></pre></div>
</div>


<p>Na versão 1.4, foi adicionado suporte a gem <a href="http://github.com/flyerhzm/rails_best_practices">rails_best_practices</a>, que verifica a qualidade do código da sua aplicação de acordo com as melhores práticas. Mais informações <a href="http://www.slideshare.net/ihower/rails-best-practices">nessa apresentação</a>.</p>

<div class="CodeRay">
  <div class="code"><pre>gem install rails_best_practices
=&gt; <span class="co">Successfully</span> installed rails_best_practices</pre></div>
</div>


<h2>Gerando as métricas</h2>

<p>A <code>metric_fu</code> utiliza o Rake para gerar as métricas e por isso, recomendo criar o arquivo <code>metric_fu.rakefile</code> dentro de <code>lib/tasks</code> com o seguinte conteúdo (<a href="http://gist.github.com/431709#file_metric_fu.rake">gist aqui</a>):</p>

<div class="CodeRay">
  <div class="code"><pre>require <span class="s"><span class="dl">'</span><span class="k">metric_fu</span><span class="dl">'</span></span>

<span class="co">MetricFu</span>::<span class="co">Configuration</span>.run <span class="r">do</span> |config|
  config.metrics  = [<span class="sy">:churn</span>, <span class="sy">:saikuro</span>, <span class="sy">:stats</span>, <span class="sy">:flog</span>, <span class="sy">:flay</span>, <span class="sy">:reek</span>, <span class="sy">:roodi</span>, <span class="sy">:rcov</span>, <span class="sy">:rails_best_practices</span>]
  config.graphs   = [<span class="sy">:flog</span>, <span class="sy">:flay</span>, <span class="sy">:reek</span>, <span class="sy">:roodi</span>, <span class="sy">:rcov</span>, <span class="sy">:stats</span>, <span class="sy">:rails_best_practices</span>]
  config.flay     = { <span class="sy">:dirs_to_flay</span> =&gt; [<span class="s"><span class="dl">'</span><span class="k">app</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">lib</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">spec</span><span class="dl">'</span></span>], <span class="sy">:minimum_score</span> =&gt; <span class="i">10</span>, <span class="sy">:filetypes</span> =&gt; [<span class="s"><span class="dl">'</span><span class="k">rb</span><span class="dl">'</span></span>] } 
  config.flog     = { <span class="sy">:dirs_to_flog</span> =&gt; [<span class="s"><span class="dl">'</span><span class="k">app</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">lib</span><span class="dl">'</span></span>]  }
  config.reek     = { <span class="sy">:dirs_to_reek</span> =&gt; [<span class="s"><span class="dl">'</span><span class="k">app</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">lib</span><span class="dl">'</span></span>]  }
  config.roodi    = { <span class="sy">:dirs_to_roodi</span> =&gt; [<span class="s"><span class="dl">'</span><span class="k">app</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">lib</span><span class="dl">'</span></span>] }
  config.saikuro  = { <span class="sy">:output_directory</span> =&gt; <span class="s"><span class="dl">'</span><span class="k">tmp/metric_fu/scratch/saikuro</span><span class="dl">'</span></span>, 
                      <span class="sy">:input_directory</span> =&gt; [<span class="s"><span class="dl">'</span><span class="k">app</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">lib</span><span class="dl">'</span></span>],
                      <span class="sy">:cyclo</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="dl">&quot;</span></span>,
                      <span class="sy">:filter_cyclo</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">0</span><span class="dl">&quot;</span></span>,
                      <span class="sy">:warn_cyclo</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">5</span><span class="dl">&quot;</span></span>,
                      <span class="sy">:error_cyclo</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">7</span><span class="dl">&quot;</span></span>,
                      <span class="sy">:formater</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">text</span><span class="dl">&quot;</span></span>
                    }
  config.churn    = { <span class="sy">:start_date</span> =&gt; <span class="s"><span class="dl">&quot;</span><span class="k">1 year ago</span><span class="dl">&quot;</span></span>, <span class="sy">:minimum_churn_count</span> =&gt; <span class="i">10</span> }
  config.rcov     = { <span class="sy">:environment</span> =&gt; <span class="s"><span class="dl">'</span><span class="k">test</span><span class="dl">'</span></span>,
                      <span class="sy">:test_files</span> =&gt; [<span class="s"><span class="dl">'</span><span class="k">test/**/*_test.rb</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">spec/**/*_spec.rb</span><span class="dl">'</span></span>],
                      <span class="sy">:rcov_opts</span> =&gt; [<span class="s"><span class="dl">&quot;</span><span class="k">--sort coverage</span><span class="dl">&quot;</span></span>, 
                                     <span class="s"><span class="dl">&quot;</span><span class="k">--no-html</span><span class="dl">&quot;</span></span>, 
                                     <span class="s"><span class="dl">&quot;</span><span class="k">--text-coverage</span><span class="dl">&quot;</span></span>,
                                     <span class="s"><span class="dl">&quot;</span><span class="k">--no-color</span><span class="dl">&quot;</span></span>,
                                     <span class="s"><span class="dl">&quot;</span><span class="k">--profile</span><span class="dl">&quot;</span></span>,
                                     <span class="s"><span class="dl">&quot;</span><span class="k">--rails</span><span class="dl">&quot;</span></span>,
                                     <span class="s"><span class="dl">&quot;</span><span class="k">-Itest:spec</span><span class="dl">&quot;</span></span>,
                                     <span class="s"><span class="dl">&quot;</span><span class="k">--exclude /gems/,/Library/,spec</span><span class="dl">&quot;</span></span>],
                       <span class="sy">:external</span> =&gt; <span class="pc">nil</span>
                    }
  config.graph_engine = <span class="sy">:bluff</span>
<span class="r">end</span></pre></div>
</div>


<p>Feito isso, basta rodar o comando <code>rake metrics:all</code>.</p>

<div class="CodeRay">
  <div class="code"><pre>rake metrics<span class="sy">:all</span></pre></div>
</div>


<p>O comando Rake irá abrir automaticamete o browser depois de rodar as métricas, e você pode encontrá-las dentro do diretório <code>temp/metric_fu/output/index.html</code>.</p>

<p>Vale ressaltar que as configurações estão utilizando o <code>Rspec</code> e o <code>Test::Unit</code>. Caso não existam algum deles, basta remover do <code>config.rcov</code> (linhas 20 e 27) as referências ao framework de testes que você não está utilizando. Mais configurações podem ser encontradas aqui.</p>

<h2>Concluindo</h2>

<p>Pelo que notei, as métricas só são armazenadas uma vez por dia, não tenho certeza se isso é configurável (se você conhece alguma configuração que mude isso, por favor poste nos comentários).</p>

<p>Vale a pena dar uma olhada nas gems que a <code>metric_fu</code> engloba (<a href="http://saikuro.rubyforge.org/">Saikuro</a>, <a href="http://ruby.sadi.st/Flog.html">Flog</a>, <a href="http://ruby.sadi.st/Flay.html">Flay</a>, <a href="http://eigenclass.org/hiki.rb?rcov">Rcov</a>, <a href="http://github.com/kevinrutherford/reek">Reek</a>, <a href="http://github.com/martinjandrews/roodi">Roodi</a>, <a href="http://github.com/danmayer/churn">Churn</a> e <a href="http://github.com/flyerhzm/rails_best_practices">rails_best_practices</a>) para entender mais o que é cada métrica e se quiser, rodá-las em separado.</p>

<p>Métricas geralmente são boas, mas não se deve usá-las como regra, apenas como referência. Muitas métricas podem acabar não sendo totalmente verdade (como 100% de cobertura de testes, por exemplo), por isso devem ser usadas apenas como um aviso.</p>

<p>Para mais informações sobre a gem, acesse o site <a href="http://metric-fu.rubyforge.org">aqui</a>.</p>

<h3>Links</h3>

<ul>
<li>Configuração utilizada no artigo: <a href="http://gist.github.com/431709#file_metric_fu.rake">link</a></li>
<li>Artigo sobre complexidade ciclomática: <a href="http://logbr.reflectivesurface.com/2008/11/12/conceitos-de-programacao-complexidade-ciclomatica/">link</a></li>
</ul>
	
</p>

<p><a href="http://mushmad.posterous.com/metricas-no-rails-com-metricfu">Permalink</a> 

	| <a href="http://mushmad.posterous.com/metricas-no-rails-com-metricfu#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Tue, 08 Jun 2010 06:09:00 -0700</pubDate>
      <title>jQuery Plugin - replaceClass</title>
      <link>http://mushmad.posterous.com/replaceclass-para-jquery</link>
      <guid>http://mushmad.posterous.com/replaceclass-para-jquery</guid>
      <description>
        <![CDATA[<p>
	<p>Já me peguei várias vezes fazendo algo parecido com isso:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="pd">$</span>(<span class="s"><span class="dl">'</span><span class="k">td</span><span class="dl">'</span></span>).removeClass(<span class="s"><span class="dl">'</span><span class="k">normal</span><span class="dl">'</span></span>);
<span class="pd">$</span>(<span class="s"><span class="dl">'</span><span class="k">td</span><span class="dl">'</span></span>).addClass(<span class="s"><span class="dl">'</span><span class="k">selecionado</span><span class="dl">'</span></span>);</pre></div>
</div>


<p>Então, para facilitar, criei um <a href="http://gist.github.com/430000">plugin</a>:</p>

<div class="CodeRay">
  <div class="code"><pre>jQuery.fn.extend({
  <span class="fu">replaceClass</span>: <span class="kw">function</span>(original, replace) {
    <span class="kw">return</span> <span class="lv">this</span>.each(<span class="kw">function</span>() {
      jQuery(<span class="lv">this</span>).removeClass(original);
      jQuery(<span class="lv">this</span>).addClass(replace);
    });
  }
});</pre></div>
</div>


<p>Agora consigo fazer:</p>

<div class="CodeRay">
  <div class="code"><pre><span class="pd">$</span>(<span class="s"><span class="dl">'</span><span class="k">td</span><span class="dl">'</span></span>).replaceClass(<span class="s"><span class="dl">'</span><span class="k">normal</span><span class="dl">'</span></span>, <span class="s"><span class="dl">'</span><span class="k">selecionado</span><span class="dl">'</span></span>);</pre></div>
</div>


<p>Espero que sejá útil.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/replaceclass-para-jquery">Permalink</a> 

	| <a href="http://mushmad.posterous.com/replaceclass-para-jquery#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Tue, 11 May 2010 19:26:00 -0700</pubDate>
      <title>jQuery Iterators - Simples como deve ser</title>
      <link>http://mushmad.posterous.com/jquery-iterators-simples-como-deve-ser</link>
      <guid>http://mushmad.posterous.com/jquery-iterators-simples-como-deve-ser</guid>
      <description>
        <![CDATA[<p>
	<p>O <a href="http://jquery.com/">jQuery</a> possui algumas formas para iterar sobre coleções (arrays, objetos e elementos) utilizando os métodos <code>$.each</code>, <code>$.map</code> e <code>$.grep</code>. Esses métodos são bem parecidos, porém cada um tem um uso específico.</p>
<h2><code>$.each</code></h2>
<p>O método <code>$.each</code> serve para passar (iterar) por cada elemento de um objeto e fazer uma determinada ação. Essa ação é feita com um <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> (função anônima), que é chamada em cada elemento. O <code>$.each<span style="font-family: Arial, Helvetica, sans-serif;"> espera dois parâmetros: o primeiro é o objeto e o segundo é o <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a>, este que, fornece dois parâmetros, o primeiro é o índice (se for um array) ou propriedade (se for objeto), e o segundo o próprio elemento:</span></code></p>
<div class="CodeRay">
  <div class="code"><pre>// Iterando em um array
$.each(['a','b','c'], function(index, element) { 
    console.log(index, element);
});
=&gt; 0, 'a'
=&gt; 1, 'b'
=&gt; 2, 'c'

// Da mesma forma com objetos
$.each({ 'nome': 'Edward Hill', 'musica': 'Trolololo' }, function(key, value) { 
    console.log(key, value);
});
=&gt; 'nome', 'Edward Hill'
=&gt; 'musica', 'Trolololo'</pre></div>
</div>

<p>Duas dicas: para parar em qualquer momento a execução do <code>$.each</code>, o <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> deve retornar <code>false</code>, já se for preciso apenas "pular" um elemento e continuar a execução, o <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> deve retornar <code>true</code>:</p>
<div class="CodeRay">
  <div class="code"><pre>// Para a execução se encontrou um 'b' no array
$.each(['a','b','c'], function(index, element) { 
    if(element === 'b') { 
        return false; 
    }
    console.log(element) 
});
=&gt; 'a'

// Já aqui, ele 'pula' a execução se encontrou um 'b', e continua para os outros elementos do array
$.each(['a','b','c'], function(index, element) { 
    if(element === 'b') { 
        return true; // observe o true aqui
    }
    console.log(element) 
});
=&gt; 'a'
=&gt; 'c'</pre></div>
</div>

<p>Uma forma de usar o <code>$.each</code> (talvez a mais utilizada), é com elementos do <a href="http://en.wikipedia.org/wiki/Document_Object_Model">DOM</a>, e aqui que a coisa fica mais interessante. A estrutura e o funcionamento são os mesmos, a diferença é que o <code>$.each</code> é executado a partir de uma coleção de elementos do <a href="http://jquery.com/">jQuery</a>:</p>
<div class="CodeRay">
  <div class="code"><pre>// Itera sobre todos os elementos forms encontrados
$('form').each(function(index, element) { 
    console.log(this);
};
=&gt; &lt;form ...&gt;
=&gt; &lt;form ...&gt;
=&gt; &lt;form ...&gt;</pre></div>
</div>

<h2><code>$.map</code></h2>
<p>O método <code>$.map</code> tem um objetivo diferente do <code>$.each</code>. Ele também executa um <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> para cada elemento, porém só retorna o que for especificado no retorno. Se não for preciso retornar alguma coisa, o <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> deve retornar <code>null</code>:</p>
<div class="CodeRay">
  <div class="code"><pre>// Retorna somente os elementos pares
$.map([4, 5, 6], function(element, index) { 
    return element + 4;
});
=&gt; [8, 9, 10]

// Retorna somente os elementos pares. Funciona como um 'filtro' no array
$.map([4, 5, 6], function(element, index) { 
    return element % 2 === 0 ? element : null;
});
=&gt; [4, 6]</pre></div>
</div>

<p>Assim como o <code>$.each</code>, o <code>$.map</code> pode ser usado com elementos do <a href="http://en.wikipedia.org/wiki/Document_Object_Model">DOM</a>. Aqui as possibilidades são infinitas, vai da criatividade de cada programador. Algumas formas de uso:</p>
<div class="CodeRay">
  <div class="code"><pre>// Cria um array com todos os atributos &quot;method&quot; dos formulários
$('form').map(function() { 
    return $(this).attr(&quot;method&quot;); 
});
=&gt; [&quot;get&quot;, &quot;post&quot;, &quot;post&quot;, &quot;get&quot;]

// Retorna todos os forms que o método form igual a GET
$('form').map(function() { 
    return $(this).attr(&quot;method&quot;).toLowerCase() === &quot;get&quot; ? this : null; 
});
=&gt; [&lt;form method=&quot;get&quot;&gt;, &lt;form method=&quot;get&quot;&gt;]</pre></div>
</div>

<p>Resumindo, qualquer coisa diferente de <code>null</code>, será retornada pelo método <code>$.map</code>.</p>
<h2><code>$.grep</code></h2>
<p>O método <code>$.grep</code> é praticamente um <code>$.map</code>, porém mais específico. A idéia do <code>$.grep</code> é utilizar o <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> como um filtro para o array, mais ou menos como o <code>$.map</code> faz, porém tem duas diferenças: a) só funciona com arrays; b) só retorna os elementos que passarem em uma determinada condição. Em outras palavaras, o <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> deve retornar <code>true</code> ou <code>false</code>, e se o retorno for <code>true</code>, o elemento do array é retornado:</p>
<div class="CodeRay">
  <div class="code"><pre>$.grep([1, 2, 3, 4], function(elemento) { 
  return elemento &gt; 2;
});
=&gt; [3, 4]</pre></div>
</div>

<p>Uma forma de fazer isso com elementos do DOM é com o método <code>filter</code> do <a href="http://jquery.com/">jQuery</a>:</p>
<div class="CodeRay">
  <div class="code"><pre>// HTML
&lt;ul&gt;
  &lt;li&gt;Item 1&lt;/li&gt;
  &lt;li&gt;Item 2&lt;/li&gt;
  &lt;li&gt;Item 3&lt;/li&gt;
  &lt;li&gt;Item 4&lt;/li&gt;
&lt;/ul&gt;

// o filter funciona como um $.grep, só que para elementos do DOM
$('li').filter(function() {
  return $(this).text() === &quot;Item 2&quot;;
}).addClass('red');

// HTML depois
&lt;ul&gt;
  &lt;li&gt;Item 1&lt;/li&gt;
  &lt;li class=&quot;red&quot;&gt;Item 2&lt;/li&gt;
  &lt;li&gt;Item 3&lt;/li&gt;
  &lt;li&gt;Item 4&lt;/li&gt;
&lt;/ul&gt;</pre></div>
</div>

<h2>Conclusão</h2>
<p>Para não se confundir em quando usar cada método, tenha em mente isso:</p>
<ul>
<li>O <code>$.each</code> executa um <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> em cada elemento (array, objeto, ou elemento do <a href="http://en.wikipedia.org/wiki/Document_Object_Model">DOM</a>), e sempre retornará todos os elementos;</li>
<li>O <code>$.map</code> funciona da mesma forma que o <code>$.each</code>, com a diferença que você pode especificar o que será retornado;</li>
<li>O <code>$.grep</code> só funciona com arrays, e para retornar um elemento do array, o <a href="http://en.wikipedia.org/wiki/Callback_(computer_science)">callback</a> deve retornar <code>true</code>;</li>
<li>Para usar algo similar ao <code>$.grep</code>, mas como elementos do <a href="http://en.wikipedia.org/wiki/Document_Object_Model">DOM</a>, o <a href="http://jquery.com/">jQuery</a> disponibiliza o método <code>filter</code>;</li>
</ul>
<p>Documentação</p>
<ul>
<li>Documentação do <a href="http://api.jquery.com/jQuery.each/">$.each com qualquer tipo de elemento</a> e o <a href="http://api.jquery.com/each/">each com elementos do DOM</a>;</li>
<li>Documentação do <a href="http://api.jquery.com/jQuery.map/">$.map com qualquer tipo de elemento</a> e o <a href="http://api.jquery.com/map/">map com elementos do DOM</a>;</li>
<li>Documentação do <a href="http://api.jquery.com/jQuery.grep/">$.grep</a>;</li>
<li>Documentação do <a href="http://api.jquery.com/grep/">filter</a>;</li>
</ul>
	
</p>

<p><a href="http://mushmad.posterous.com/jquery-iterators-simples-como-deve-ser">Permalink</a> 

	| <a href="http://mushmad.posterous.com/jquery-iterators-simples-como-deve-ser#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Thu, 18 Feb 2010 07:33:00 -0800</pubDate>
      <title>Testando Javascript com QUnit</title>
      <link>http://mushmad.posterous.com/testando-javascript-com-qunit</link>
      <guid>http://mushmad.posterous.com/testando-javascript-com-qunit</guid>
      <description>
        <![CDATA[<p>
	<p>J&aacute; faz um tempo que venho procurando uma biblioteca para testes unit&aacute;rios em Javascript que seja f&aacute;cil de utilizar. Uns posts atr&aacute;s, falei um pouco sobre a&nbsp;<a href="http://jsunittest.com/" target="_blank">JsUnitTest</a>, que voc&ecirc; pode conferir&nbsp;<a href="http://mushmad.posterous.com/test-driven-development-em-javascript" target="_blank">aqui</a>&nbsp;e&nbsp;<a href="http://mushmad.posterous.com/testando-funcoes-assincronas-em-javascript-co" target="_blank">aqui</a>.</p>
<p>Neste post pretendo mostrar um pouco da biblioteca&nbsp;<a href="http://docs.jquery.com/QUnit" target="_blank">QUnit</a>.</p>
<h2>O que &eacute; QUnit</h2>
<p>De acordo com o site do projeto: "<a href="http://docs.jquery.com/QUnit" target="_blank">QUnit</a>&nbsp;&eacute; uma suite de testes em Javascript, poderosa e simples de usar". Est&aacute; sendo utilizada principalmente para testar o projeto&nbsp;<a href="http://jquery.com/" target="_blank">jQuery</a>&nbsp;e alguns plugins, mas &eacute; capaz de testar qualquer c&oacute;digo Javascript gen&eacute;rico.</p>
<h2>Usando QUnit</h2>
<p><a href="http://docs.jquery.com/QUnit" target="_blank">QUnit</a>&nbsp;&eacute; realmente simples de usar. Voc&ecirc; precisa basciamente incluir os arquivos&nbsp;<a href="http://github.com/jquery/qunit/raw/master/qunit/qunit.js" target="_blank">qunit.js</a>&nbsp;e&nbsp;<a href="http://github.com/jquery/qunit/raw/master/qunit/qunit.css" target="_blank">qunit.css</a>&nbsp;e ter uma estrutura b&aacute;sica de HTML para que a biblioteca funcione corretamente. Um exemplo pode ser conferido <a href="http://pastie.org/830873" target="_blank">aqui</a>.</p>
<p>Ao abrir este exemplo, voc&ecirc; deve ver uma tela parecida com essa:</p>
<p><div class='p_embed p_image_embed'>
<a href="http://posterous.com/getfile/files.posterous.com/mushmad/RZTp4Rxzyoy8W2JmUD2plh3OVqFYNk1wj9l04gcMBEqLCHb6KE7DZ5dJk1yj/Screen_shot_2010-02-17_at_10.2.png"><img alt="Screen_shot_2010-02-17_at_10" height="220" src="http://posterous.com/getfile/files.posterous.com/mushmad/lK2vZoyU5vGwH8NJnhPOETjjqfB7WsTobygkMGZ9UsPghmQymWyzOIgBVgT9/Screen_shot_2010-02-17_at_10.2.png.scaled.500.jpg" width="500" /></a>
</div>
</p>
<h2>Exemplo de teste</h2>
<p>Os blocos de teste s&atilde;o feitos com o m&eacute;todo&nbsp;<a href="http://docs.jquery.com/QUnit/test" target="_blank">test</a>&nbsp;que espera 2 par&acirc;metros: o primeiro com o nome do teste e o segundo com uma fun&ccedil;&atilde;o contendo as asser&ccedil;&otilde;es:</p>
<div class="CodeRay">
  <div class="code"><pre>test(&quot;um teste simples&quot;, function() {
  ok(true, &quot;tem que passar&quot;);
});</pre></div>
</div>

<p>O que resulta isso:</p>
<p><div class='p_embed p_image_embed'>
<a href="http://posterous.com/getfile/files.posterous.com/mushmad/KIiofwkVDCFwtNntqtyfBHybCSS6jD5lDnxxUYDHvBmsQXwqHjP88VbNhbDa/Screen_shot_2010-02-17_at_10.3.png"><img alt="Screen_shot_2010-02-17_at_10" height="218" src="http://posterous.com/getfile/files.posterous.com/mushmad/btL6s8KnLXO6XKNVQxrim2Fm9bGgS5sWjJEm0GiswnEJtAdHq7VnzwsA5b13/Screen_shot_2010-02-17_at_10.3.png.scaled.500.jpg" width="500" /></a>
</div>
</p>
<p>O m&eacute;todo&nbsp;<a href="http://docs.jquery.com/QUnit/ok" target="_blank">ok</a>, verifica se o primeiro par&acirc;metro &eacute; <code>true</code>, similar ao <code>assert</code> da&nbsp;<a href="http://jsunittest.com/" target="_blank">JsUnitTest</a>. Se trocarmos para <code>false</code> o primeiro par&acirc;metro do&nbsp;<a href="http://docs.jquery.com/QUnit/ok" target="_blank">ok</a>, veremos essa tela:</p>
<p><div class='p_embed p_image_embed'>
<a href="http://posterous.com/getfile/files.posterous.com/mushmad/oNcTvf9gONwgv0IzfaLHuYbHCN1NeFvq0DtfG6R9IBPFPveJi6a3fqetCJmb/0Screen_shot_2010-02-17_at_10.3.png"><img alt="0screen_shot_2010-02-17_at_10" height="221" src="http://posterous.com/getfile/files.posterous.com/mushmad/F9O2pouvUKuQ7j4K6lfS0JIeu2SMrnBP00cdzcSYXmysDf443yr6OQwqwOPW/0Screen_shot_2010-02-17_at_10.3.png.scaled.500.jpg" width="500" /></a>
</div>
</p>
<p>Dica: Para ver qual asser&ccedil;&atilde;o falhou dentro do teste, &eacute; s&oacute; clicar no nome do teste.</p>
<p>Conhecendo o ambiente b&aacute;sico, podemos passar pra algo mais espec&iacute;fico.</p>
<h2>Outro exemplo</h2>
<p>Veja o exemplo abaixo:</p>
<div class="CodeRay">
  <div class="code"><pre>module(&quot;modulo simples&quot;, {
  // executa um código específico antes de cada teste
  setup: function() {
    this.setup_var = true;
  },
  // executa um código específico depois de cada teste
  teardown: function() {}
});
test(&quot;um teste com ok&quot;, function() {
  ok(this.setup_var, &quot;testa a variavel criada no setup&quot;);
});

test(&quot;um teste com equals&quot;, function() {
  equals($(&quot;h1&quot;).length, 1, &quot;deve ter um elemento h1&quot;);
  equals($(&quot;h2&quot;).length, 2, &quot;deve ter dois elementos h2&quot;);
});

module(&quot;outro modulo&quot;);

test(&quot;um teste com same&quot;, function() {
  same([1, 2, 3], [1, 2], &quot;same verifica todas as propriedades ou elementos recursivamente&quot;);
});</pre></div>
</div>

<p>O m&eacute;todo&nbsp;<a href="http://docs.jquery.com/QUnit/module" target="_blank">module</a>&nbsp;serve como um "agrupador" de testes, separando os testes em m&oacute;dulos (&oacute;bvio, d&atilde;&atilde;). &Eacute; poss&iacute;vel passar um par&acirc;metro adicional com as fun&ccedil;&otilde;es <code>setup</code> e <code>teardown</code>. A fun&ccedil;&atilde;o <code>setup</code> &eacute; executada&nbsp;<strong>antes de cada</strong>&nbsp;teste, j&aacute; a <code>teardown</code> &eacute; executada&nbsp;<strong>depois de cada teste</strong>.</p>
<p>Existem outros m&eacute;todos de asser&ccedil;&otilde;es que s&atilde;o o&nbsp;<a href="http://docs.jquery.com/QUnit/equals" target="_blank">equals(atual, esperado, mensagem)</a>&nbsp;e o&nbsp;<a href="http://docs.jquery.com/QUnit/same" target="_blank">same(atual, esperado, mensagem)</a>. Basicamente eles testam se o primeiro par&acirc;metro &eacute; igual ao segundo, com a diferen&ccedil;a que o&nbsp;<a href="http://docs.jquery.com/QUnit/same" target="_blank">same</a>&nbsp;&eacute; mais preciso, e testa todas as prorpiedades dos par&acirc;metros passados recursivamente, o que &eacute; &uacute;til principalmente com arrays e objetos.</p>
<h2>Conclus&atilde;o</h2>
<p>A biblioteca&nbsp;<a href="http://docs.jquery.com/QUnit" target="_blank">QUnit</a>&nbsp;se mostrou muito simples de usar nos testes que fiz, cumprindo sua promessa. Recomendo para quem quer iniciar algo com testes unit&aacute;rios em Javascript, principalmente por ela ser muito f&aacute;cil de usar e quem j&aacute; est&aacute; habituado com o mundo do&nbsp;<a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank">TDD</a>&nbsp;n&atilde;o vai ter nenhuma dificuldade em se adaptar.</p>
<h2>Gostei, quero me informar mais. O que fa&ccedil;o?</h2>
<p>Voc&ecirc; pode conferir a documenta&ccedil;&atilde;o mais detalhada no site do&nbsp;<a href="http://jquery.com/" target="_blank">jQuery</a>, ou pode acompanhar este blog, que em breve estarei postando mais artigos relacionados ao&nbsp;<a href="http://docs.jquery.com/QUnit" target="_blank">QUnit</a>&nbsp;e testes em geral.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/testando-javascript-com-qunit">Permalink</a> 

	| <a href="http://mushmad.posterous.com/testando-javascript-com-qunit#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Tue, 09 Feb 2010 17:49:00 -0800</pubDate>
      <title>Separando estimativas de compromissos</title>
      <link>http://mushmad.posterous.com/separando-estimativas-de-compromissos</link>
      <guid>http://mushmad.posterous.com/separando-estimativas-de-compromissos</guid>
      <description>
        <![CDATA[<p>
	<p><em>Este post &eacute; uma tradu&ccedil;&atilde;o livre do post "</em><a href="http://blog.mountaingoatsoftware.com/separate-estimating-from-committing" target="_blank"><em>Separate Estimating from Committing</em></a><em>" de Mike Cohn.</em></p>
<p>Um problema fundamental e comum em muitas organiza&ccedil;&otilde;es &eacute; que as estimativas e os compromissos s&atilde;o considerados equivalentes. A equipe de desenvolvimento (&aacute;gil ou n&atilde;o) estima que a entrega de um determinado conjunto de funcionalidades levar&aacute; sete meses com os recursos dispon&iacute;veis. Os membros da equipe informam essa estimativa para o seu gerente, que passa a estimativa ao vice-presidente, que ent&atilde;o informa o cliente. E, em alguns casos, a estimativa &eacute; "podada" ao longo do caminho para prover &agrave; equipe uma "meta el&aacute;stica".</p>
<p>O problema aqui n&atilde;o &eacute; que a estimativa da equipe de sete meses esteja certa ou errada. O problema &eacute; que a estimativa foi transformada em um compromisso. "Estimamos que isso levar&aacute; sete meses", foi traduzido para "Nos comprometemos a terminar em sete meses". Estimar e se comprometer s&atilde;o ambos importantes, mas devem ser vistos como atividades separadas.</p>
<p>Precisei buscar minha filha na nata&ccedil;&atilde;o esta noite. Perguntei a ela em que horas ela estaria pronta (o que n&oacute;s definimos como: t&eacute;rmino da nata&ccedil;&atilde;o, tomar banho, e estar pronta para ir para casa). Ela disse, "Eu devo estar pronta pelas 5:15". Essa era a sua estimativa. Se eu tivesse pedido para ela se comprometer - estar fora das instala&ccedil;&otilde;es at&eacute; aquela hora ou eu iria embora - ela poderia ter se comprometido para as 5:25, para dar tempo de resolver eventuais problemas, como uma pr&aacute;tica um pouco mais longa, o rel&oacute;gio do treinador estar atrasado em cinco minutos, fila nos chuveiros, e assim por diante. Para determinar um tempo no qual ela poderia se comprometer, ainda assim ela teria feito uma estimativa. Mas ao inv&eacute;s de me dizer sua estimativa diretamente, ela teria transformado-a em um prazo no qual poderia comprometer-se.</p>
<p>N&atilde;o deixe que suas estimativas se tornem compromissos. Lembre-se da diferen&ccedil;a entre uma estimativa e um compromisso e mantenha as duas atividades separadas, instruindo os gerentes e os clientes, se necess&aacute;rio. Eu falo muito mais sobre estimativa &aacute;gil e compromisso no meu novo livro, "<a href="http://www.mountaingoatsoftware.com/books/7--succeeding-with-agile" target="_blank">Succeeding with Agile</a>".</p>
	
</p>

<p><a href="http://mushmad.posterous.com/separando-estimativas-de-compromissos">Permalink</a> 

	| <a href="http://mushmad.posterous.com/separando-estimativas-de-compromissos#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Thu, 28 Jan 2010 07:53:00 -0800</pubDate>
      <title>O primeiro passo é admitir que você tem um problema</title>
      <link>http://mushmad.posterous.com/o-primeiro-passo-e-admitir-que-voce-tem-um-pr</link>
      <guid>http://mushmad.posterous.com/o-primeiro-passo-e-admitir-que-voce-tem-um-pr</guid>
      <description>
        <![CDATA[<p>
	<p><span style="color: #000000;"><em>Este post &eacute; uma tradu&ccedil;&atilde;o livre do artigo "<a href="http://37signals.com/svn/posts/2051-step-one-is-admitting-you-have-a-problem" target="_blank">Step one is admitting you have a problem</a>" de David Heinemeier Hansson</em></span></p>
<p>O mundo das startups est&aacute; repleto de pessoas viciadas em trabalho e esse v&iacute;cio muitas vezes tem um pre&ccedil;o caro: amizades perdidas, relacionamentos acabados, sa&uacute;de ruim, e falta de interesse em outros assuntos. Tudo o que importa &eacute; a pr&oacute;xima tarefa de trabalho, o pr&oacute;ximo neg&oacute;cio, a pr&oacute;xima etapa, a pr&oacute;xima rodada de financiamento.<p />Se voc&ecirc; tivesse um v&iacute;cio semelhante a coca&iacute;na ou o &aacute;lcool, as pessoas iriam cham&aacute;-lo de doente e aconselh&aacute;-lo a procurar ajuda. Mas no mundo das startups, esse v&iacute;cio &eacute; elogiado por muitos. Voc&ecirc; &eacute; considerado um her&oacute;i por apostar todas as suas fichas da vida na esperan&ccedil;a de que voc&ecirc; vai acertar um royal flush.<p />O pior &eacute; que a maioria desses viciados sabem conscientemente que a jornada de 14 horas de trabalho n&atilde;o &eacute; realmente uma forma muito produtiva de seguir em frente. Que mais tempo n&atilde;o significa trabalho mais valioso. Jason Cohen aborda este assunto em: "<a href="http://www.building43.com/blogs/2009/12/07/sacrifice-your-health-for-your-startup" target="_blank">Sacrifice your health for your startup</a>". Ele reconhece que a <a href="http://37signals.com/svn/posts/1006-sleep-deprivation-is-not-a-badge-of-honor" target="_blank">priva&ccedil;&atilde;o do sono n&atilde;o &eacute; muito &uacute;til, mas ainda v&ecirc; como um distintivo de honra</a>, que o trabalho extra provavelmente n&atilde;o faz produto de qualidade, mas de certa forma ainda precisa existir.<p />Ele fala com a voz da raz&atilde;o, mas age como um viciado. Desesperado para encontrar uma justificativa para os seus caminhos, ele diz: Voc&ecirc; n&atilde;o precisa ser nada al&eacute;m de trabalho porque voc&ecirc; j&aacute; tem que fazer muitos pap&eacute;is. Voc&ecirc; precisa ter uma obsess&atilde;o &uacute;nica com o trabalho porque o nirvana da "liberdade financeira" est&aacute; a apenas alguns passos &agrave; frente.<p />Ser viciado em seu trabalho pode ser um pouco melhor do que um v&iacute;cio em coca&iacute;na, mas segue o mesmo padr&atilde;o de abuso e de escapismo. E o mais importante, n&atilde;o &eacute; um requisito para o sucesso. Voc&ecirc; n&atilde;o precisa se tornar um viciado para abrir uma startup. Apenas seja apaixonado, obcecado, mas n&atilde;o deixe que isto seja uma desculpa para consumir a sua vida.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/o-primeiro-passo-e-admitir-que-voce-tem-um-pr">Permalink</a> 

	| <a href="http://mushmad.posterous.com/o-primeiro-passo-e-admitir-que-voce-tem-um-pr#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Wed, 09 Dec 2009 12:45:00 -0800</pubDate>
      <title>Testando funções assíncronas em Javascript com JsUnitTest</title>
      <link>http://mushmad.posterous.com/testando-funcoes-assincronas-em-javascript-co</link>
      <guid>http://mushmad.posterous.com/testando-funcoes-assincronas-em-javascript-co</guid>
      <description>
        <![CDATA[<p>
	<p>A biblioteca <a href="http://jsunittest.com/" target="_blank">JsUnitTest</a>, que mostrei no <a href="http://mushroommadness.tumblr.com/post/259015016" target="_blank">post anterior</a>, oferece uma forma simples para testar fun&ccedil;&otilde;es que s&atilde;o executadas de modo ass&iacute;ncrono - como <code>setInterval</code> e <code>setTimeout</code> - atrav&eacute;s do m&eacute;todo <code>wait</code></p>
<div class="CodeRay">
  <div class="code"><pre>wait(tempo_em_milisegundos, bloco_de_codigo);</pre></div>
</div>

<p>O m&eacute;todo <code>wait</code> espera o tempo determinado em milisegundos e executa o bloco de c&oacute;digo, que nada mais &eacute; do que uma fun&ccedil;&atilde;o an&ocirc;nima. Um exemplo de teste:</p>
<div class="CodeRay">
  <div class="code"><pre>testAsync: function() { with(this) {  var executou = false;  var timeout = setTimeout(function() {    executou = true;  }, 10);  wait(100, function() {    assert(executou);  });}}</pre></div>
</div>

<p>O teste &eacute; simples, depois de 10 milisegundos a vari&aacute;vel <code>executou</code> recebe <code>true</code>. A asser&ccedil;&atilde;o que ficou dentro do m&eacute;todo <code>wait</code> s&oacute; &eacute; executada depois de 100 milisegundos, um tempo um pouco maior, apenas para dar uma seguran&ccedil;a.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/testando-funcoes-assincronas-em-javascript-co">Permalink</a> 

	| <a href="http://mushmad.posterous.com/testando-funcoes-assincronas-em-javascript-co#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Thu, 26 Nov 2009 16:35:00 -0800</pubDate>
      <title>Test-driven Development em Javascript</title>
      <link>http://mushmad.posterous.com/test-driven-development-em-javascript</link>
      <guid>http://mushmad.posterous.com/test-driven-development-em-javascript</guid>
      <description>
        <![CDATA[<p>
	<p>Na busca por uma soul&ccedil;&atilde;o simples para <a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank">Test-driven Development</a> em Javascript, me deparei com o projeto <a href="http://jsunittest.com/" target="_blank">JsUnitTest ou JavaScript Unit Testing framework</a>.</p>
<p>O projeto foi criado pelo <a href="http://drnicwilliams.com/" target="_blank">Dr. Nic</a> e &eacute; extremamente simples e muito &uacute;til. Mais detalhes podem ser vistos <a href="http://jsunittest.com/" target="_blank">aqui</a>.</p>
<h2>Instala&ccedil;&atilde;o</h2>
<p>Fa&ccedil;a o download do projeto em <a href="http://jsunittest.com/dist/jsunittest-getting-started.tar.gz" target="_blank">tar</a> ou <a href="http://jsunittest.com/dist/jsunittest-getting-started.zip" target="_blank">zip</a> e descompacte. Podemos ver tr&ecirc;s arquivos:</p>
<div class="CodeRay">
  <div class="code"><pre>assets/jsunittest.js
assets/unittest.css
example_test.html</pre></div>
</div>

<p>Logo depois, abra o arquivo <code>example_test.html</code> no browser para checar se est&aacute; tudo ok.</p>
<p class="image"><div class='p_embed p_image_embed'>
<img alt="Media_httpmediatumblrcomtumblrktqxyiruj41qzq590png_ipgebbhaxjdeyry" height="311" src="http://posterous.com/getfile/files.posterous.com/import-wucv/yeoEbetkfjHHkhgzbEnnahnwEfDGvxdwFxyAatHiftmlilyHCjiiEkqjrFDr/media_httpmediatumblrcomtumblrktqxyirUJ41qzq590png_IpGebbhAxJDEyry.png.scaled500.png" width="459" />
</div>
</p>
<p>Agora &eacute; s&oacute; linkar o arquivo da sua biblioteca Javascript e sair testando.</p>
<h2>Criando testes</h2>
<p>No exemplo podemos ver o m&eacute;todo <code>testTruth</code> com uma asser&ccedil;&atilde;o e a&iacute; entra um detalhe importante: apenas os m&eacute;todos que iniciem com <code>test</code> ser&atilde;o executados pelo framework.</p>
<p>Podemos criar mais um teste logo abaixo:</p>
<div class="CodeRay">
  <div class="code"><pre>testColor: function() { with(this) {
  assertEqual('Green', Mushroom.color)
}}</pre></div>
</div>

<p>Obviamente este teste ir&aacute; falhar, ent&atilde;o vamos criar um objeto rapidamente s&oacute; para passar nos testes:</p>
<div class="CodeRay">
  <div class="code"><pre>var Mushroom = {
  color: 'Green'
}</pre></div>
</div>

<p>Agora os testes passaram e voc&ecirc; pode tomar seu ch&aacute; de cogumelo!</p>
<p>Bom, essa &eacute; apenas uma introdu&ccedil;&atilde;o. Pretendo cobrir mais pontos interessantes desse framework de testes nos pr&oacute;ximos posts.</p>
	
</p>

<p><a href="http://mushmad.posterous.com/test-driven-development-em-javascript">Permalink</a> 

	| <a href="http://mushmad.posterous.com/test-driven-development-em-javascript#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Thu, 19 Nov 2009 16:09:00 -0800</pubDate>
      <title>Utilizando setInterval e clearInterval em Javascript</title>
      <link>http://mushmad.posterous.com/utilizando-setinterval-e-clearinterval-em-jav</link>
      <guid>http://mushmad.posterous.com/utilizando-setinterval-e-clearinterval-em-jav</guid>
      <description>
        <![CDATA[<p>
	<p>﻿Digamos que voc&ecirc; precise executar uma determinada fun&ccedil;&atilde;o a cada 2 segundos, ou algo que precise ser repetido de tempos em tempos, como por exemplo um timer.</p>
<p>Em Javascript isso &eacute; poss&iacute;vel atrav&eacute;s das fun&ccedil;&otilde;es <code>setInterval</code> e <code>clearInterval</code>, e seu uso &eacute; bem simples, veja:</p>
<div class="CodeRay">
  <div class="code"><pre>var hello = setInterval(function() {
  console.log('Hello world!');
}, 2000);
// a cada 2 segundos (tempo em milisegundos), escreve no console 'Hello world!'</pre></div>
</div>

<p>O primeiro par&acirc;metro da fun&ccedil;&atilde;o <code>setInterval</code> recebe uma fun&ccedil;&atilde;o an&ocirc;nima que ser&aacute; executada de tempos em tempos, e o tempo entre cada execu&ccedil;&atilde;o &eacute; dado pelo segundo par&acirc;metro. Este tempo est&aacute; em milisegundos.</p>
<p>Note que atribu&iacute;mos o retorno da fun&ccedil;&atilde;o <code>setInterval</code> &agrave; vari&aacute;vel hello, por que isso? Porque a fun&ccedil;&atilde;o <code>setInterval</code> retorna um identificador - que &eacute; um n&uacute;mero qualquer - e este n&uacute;mero &eacute; usado na fun&ccedil;&atilde;o <code>clearInterval</code>, para interromper o timer associado.</p>
<div class="CodeRay">
  <div class="code"><pre>// para a execução
clearInterval(hello);</pre></div>
</div>

<p>A fun&ccedil;&atilde;o <code>clearInterval</code> interrompe o timer associado &aacute; variavel passada. Somente isso.</p>
<p>Podemos reaproveitar essa fun&ccedil;&atilde;o, passando-a por refer&ecirc;ncia:</p>
<div class="CodeRay">
  <div class="code"><pre>function hello() {
  console.log('Hello world!');
};
var intervalo = setInterval(hello, 2000);
var intervalo_longo = setInterval(hello, 5000);
// ...
clearInterval(intervalo);
clearInterval(intervalo_longo);</pre></div>
</div>

<p>Caso essa fun&ccedil;&atilde;o precise de par&acirc;metros, podemos pass&aacute;-los logo ap&oacute;s os dois primeiros:</p>
<div class="CodeRay">
  <div class="code"><pre>function mensagem(msg) {
  console.log(msg);
}
setInterval(mensagem, 2000, 'Hello World!');
setInterval(mensagem, 2000, 'Hello Moon?');</pre></div>
</div>

<p>Ou seja, todos os par&acirc;metros ap&oacute;s os dois primeiros, ser&atilde;o passados para fun&ccedil;&atilde;o mensagem.</p>
<h3>Aten&ccedil;&atilde;o</h3>
<p><strong>Nunca</strong> fa&ccedil;a algo assim:</p>
<div class="CodeRay">
  <div class="code"><pre>setInterval(&quot;alert('Hello World!')&quot;, 1000);</pre></div>
</div>

<p>Passando uma string para a fun&ccedil;&atilde;o <code>setInterval</code>, tem o mesmo comportamento que o <code>eval</code>, e como sabemos, <em>&lsquo;Eval is Evil&rsquo;</em>.</p>
<p>Tamb&eacute;m tome cuidado ao criar muitos timers, se houverem muitos simult&acirc;neos, o browser simplesmente trava!</p>
	
</p>

<p><a href="http://mushmad.posterous.com/utilizando-setinterval-e-clearinterval-em-jav">Permalink</a> 

	| <a href="http://mushmad.posterous.com/utilizando-setinterval-e-clearinterval-em-jav#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Thu, 19 Nov 2009 15:03:00 -0800</pubDate>
      <title>Algumas dicas de rubygems</title>
      <link>http://mushmad.posterous.com/algumas-dicas-de-rubygems</link>
      <guid>http://mushmad.posterous.com/algumas-dicas-de-rubygems</guid>
      <description>
        <![CDATA[<p>
	<h2>gem server</h2>
<p>Quer acessar a documenta&ccedil;&atilde;o (rdoc) das gems instaladas facilmente? Simples, v&aacute; ao terminal e digite:</p>
<div class="CodeRay">
  <div class="code"><pre>~$ gem server
=&gt; Starting gem server on http://localhost:8808/</pre></div>
</div>

<p>Pronto, voc&ecirc; acabou de subir um servidor de gems na sua m&aacute;quina! Acessando a url <a href="http://localhost:8808/">http://localhost:8808/</a> e voc&ecirc; ver&aacute; a documenta&ccedil;&atilde;o de todas as gems instaladas na sua m&aacute;quina.</p>
<p>E n&atilde;o &eacute; s&oacute; isso, outras pessoas podem baixar e instalar gems que est&atilde;o na sua m&aacute;quina, simplesmente digitando:</p>
<div class="CodeRay">
  <div class="code"><pre>~$ gem install SUA_INCRIVEL_GEM -s http://SUA_MAQUINA:8808</pre></div>
</div>

<h2>Mudando o tema do RDoc</h2>
<p>Eu particularmente n&atilde;o gosto muito do tema padr&atilde;o do RDoc, e se voc&ecirc; concorda comigo, siga os seguintes passos:</p>
<h3>Instale a gem &lsquo;hanna&rsquo;</h3>
<p>A gem hanna cria um tema diferente para a documenta&ccedil;&atilde;o das suas gems, e sua instala&ccedil;&atilde;o &eacute; simples:</p>
<div class="CodeRay">
  <div class="code"><pre>~$ sudo gem install hanna
=&gt; Successfully installed hanna-0.1.12</pre></div>
</div>

<h3>Mude o template padr&atilde;o</h3>
<p>Para trocar o template padr&atilde;o ao instalar uma gem (comando gem install), edite o arquivo .gemrc:</p>
<div class="CodeRay">
  <div class="code"><pre>rdoc: --inline-source --line-numbers --format=html --template=hanna</pre></div>
</div>

<h3>Atualize a documenta&ccedil;&atilde;o das suas gem com o novo template</h3>
<p>Para atualizar os arquivos de documenta&ccedil;&atilde;o com o novo template, digite no terminal:</p>
<div class="CodeRay">
  <div class="code"><pre>~$ sudo gem rdoc --all --no-ri</pre></div>
</div>

<p>Isto ir&aacute; gerar todos os arquivos de documenta&ccedil;&atilde;o das gems novamente (pode demorar um pouco).</p>
<h3>Gem Server novamente</h3>
<p>Agora se voc&ecirc; subir o servidor de gems novamente, ver&aacute; que o tema ficou muito mais interessante! (exceto pela primeira p&aacute;gina que ainda tem o tema antigo).</p>
<p>Mesmo assim ainda &eacute; muito chato ter que entrar no terminal o tempo todo e subir o servidor de gems. Pensando nisso, Jason Seifer postou uma forma muito legal de acessar o RDoc das suas gems <a href="http://jasonseifer.com/2009/02/22/offline-gem-server-rdocs" target="_blank">nesse tutorial</a> (alguns passos j&aacute; foram descritos aqui).</p>
	
</p>

<p><a href="http://mushmad.posterous.com/algumas-dicas-de-rubygems">Permalink</a> 

	| <a href="http://mushmad.posterous.com/algumas-dicas-de-rubygems#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/557857/profile.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/3sDFiiMirdh7</posterous:profileUrl>
        <posterous:firstName>Felipe Elias</posterous:firstName>
        <posterous:lastName>Philipp</posterous:lastName>
        <posterous:nickName>MushMad!</posterous:nickName>
        <posterous:displayName>Felipe Elias Philipp</posterous:displayName>
      </posterous:author>
    </item>
  </channel>
</rss>

