<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Simples Idéias. Por Nando Vieira.</title>
	
	<link>http://simplesideias.com.br</link>
	<description />
	<pubDate>Thu, 20 Nov 2008 02:48:22 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.3</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/simplesideias" type="application/rss+xml" /><feedburner:emailServiceId>535099</feedburner:emailServiceId><feedburner:feedburnerHostname>http://www.feedburner.com</feedburner:feedburnerHostname><item>
		<title>Compactando Javascript e CSS antes de fazer um commit no Git</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/459083724/</link>
		<comments>http://simplesideias.com.br/compactando-javascript-e-css-antes-de-fazer-um-commit-no-git/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 02:48:22 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[CSS]]></category>

		<category><![CDATA[Javascript]]></category>

		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[Compressão]]></category>

		<category><![CDATA[Otimização]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=267</guid>
		<description><![CDATA[
	O Git tem alguns hooks que permitem fazer coisas bem interessantes. 
	Eu, malandro que sou, escrevi um para compactar arquivos Javascript e CSS utilizando YUI Compressor,
	desenvolvido pelo Yahoo!.



	Em seu repositório Git, crie o arquivo &#034;.git/hooks/pre-commit&#034; com o conteúdo abaixo:


#!/bin/bash
cd &#34;$0/../../..&#34;
rake git:precommit


	Execute o comando chmod a+x .git/hooks/pre-commit. Se você não fizer isso,
	o Git não irá executar [...]]]></description>
			<content:encoded><![CDATA[<p>
	O Git tem alguns hooks que permitem fazer coisas bem interessantes. 
	Eu, malandro que sou, escrevi um para compactar arquivos Javascript e CSS utilizando YUI Compressor,
	desenvolvido pelo Yahoo!.
</p>

<p>
	Em seu repositório Git, crie o arquivo &#034;.git/hooks/pre-commit&#034; com o conteúdo abaixo:
</p>

<pre class="text"><code>#!/bin/bash
cd &quot;$0/../../..&quot;
rake git:precommit</code></pre>

<p>
	Execute o comando <code>chmod a+x .git/hooks/pre-commit</code>. Se você não fizer isso,
	o Git não irá executar este hook. Ele irá executar a tarefa Rake <code>git:precommit</code>.
</p>

<p>
	Acesse a <a href="http://developer.yahoo.com/yui/compressor/" title="Yahoo! UI Library: YUI Compressor" rel="external">Yahoo! Developer Network</a>
	e baixe o YUI Compressor. É um arquivo &#034;jar&#034;, o que significa que você precisa ter Java 1.4 ou superior instalado. Alternativamente, você pode
	executar os comandos abaixo à partir da raíz de seu projeto Ruby on Rails.
</p>

<pre class="text"><code>wget http://www.julienlecomte.net/yuicompressor/yuicompressor-2.4.2.zip -O yuicompressor.zip
unzip yuicompressor.zip
mkdir tools
cp yuicompressor-2.4.2/build/yuicompressor-2.4.2.jar tools/yuicompressor.jar
rm -rf yuicompressor-2.4.2/</code></pre>

<p>
	Agora, podemos fazer todo o trabalho sujo utilizando código Ruby. 
	Crie o arquivo <code>lib/tasks/dev.rake</code> e adicione o código abaixo:
</p>

<pre class="rails"><code><span class="kw3">require</span> <span class="st0">&quot;config/environment&quot;</span>
&nbsp;
<span class="kw1">def</span> run_compressor<span class="br0">&#40;</span>type, files, except=<span class="br0">&#91;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
  output_refs = <span class="br0">&#123;</span>:css =&gt; <span class="st0">&quot;stylesheets&quot;</span>, <span class="re3">:js</span> =&gt; <span class="st0">&quot;javascripts&quot;</span><span class="br0">&#125;</span>
  output_dir = <span class="st0">&quot;public/#{output_refs[type]}&quot;</span>
&nbsp;
  files.<span class="kw5">each</span> <span class="kw1">do</span> |input|
    output_name = <span class="kw4">File</span>.<span class="me1">basename</span><span class="br0">&#40;</span><span class="kw5">input</span><span class="br0">&#41;</span>
    output_name.<span class="kw3">gsub</span>!<span class="br0">&#40;</span>/\.<span class="me1"><span class="br0">&#40;</span>js</span>|css<span class="br0">&#41;</span>$/, <span class="st0">&quot;-min#{File.extname(output_name)}&quot;</span><span class="br0">&#41;</span>
    output = <span class="st0">&quot;#{output_dir}/#{output_name}&quot;</span>
&nbsp;
    <span class="kw3">system</span> <span class="st0">&quot;java -jar tools/yuicompressor.jar --type=#{type} #{input} &gt; #{output}&quot;</span>
&nbsp;
    original = file_size<span class="br0">&#40;</span><span class="kw5">input</span><span class="br0">&#41;</span>
    compressed = file_size<span class="br0">&#40;</span>output<span class="br0">&#41;</span>
&nbsp;
    <span class="kw3">puts</span> <span class="st0">&quot; - #{File.basename(input)} [#{original}] =&gt; #{output_name} [#{compressed}]&quot;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
<span class="kw1">def</span> file_size<span class="br0">&#40;</span>file<span class="br0">&#41;</span>
  <span class="re2">ActionController::Base</span>.<span class="me1">helpers</span>.<span class="me1">number_to_human_size</span><span class="br0">&#40;</span><span class="kw4">File</span>.<span class="kw5">size</span><span class="br0">&#40;</span>file<span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="kw1">end</span>
&nbsp;
namespace <span class="re3">:git</span> <span class="kw1">do</span>
  desc <span class="st0">&quot;Run before a Git commit&quot;</span>
  task <span class="re3">:precommit</span> <span class="kw1">do</span>
    <span class="re2">Rake::Task</span><span class="br0">&#91;</span><span class="st0">'compress:css'</span><span class="br0">&#93;</span>.<span class="me1">invoke</span>
    <span class="re2">Rake::Task</span><span class="br0">&#91;</span><span class="st0">'compress:javascript'</span><span class="br0">&#93;</span>.<span class="me1">invoke</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
namespace <span class="re3">:compress</span> <span class="kw1">do</span>
  desc <span class="st0">&quot;Compress all javascript files using YUI Compressor&quot;</span>
  task <span class="re3">:javascript</span> <span class="kw1">do</span>
    <span class="kw3">puts</span> <span class="st0">&quot;<span class="es0">\n</span>Compressing javascript files&quot;</span>
&nbsp;
    files = <span class="kw4">Dir</span><span class="br0">&#91;</span><span class="st0">'public/javascripts/*.js'</span><span class="br0">&#93;</span>.<span class="me1">reject</span> <span class="kw1">do</span> |f|
      f =~ /-min\.<span class="me1">js</span>$/ || f =~ /\/jquery\.<span class="me1">js</span>/
    <span class="kw1">end</span>
&nbsp;
    run_compressor<span class="br0">&#40;</span><span class="re3">:js</span>, files<span class="br0">&#41;</span>
  <span class="kw1">end</span>
&nbsp;
  desc <span class="st0">&quot;Compress all stylesheet files using YUI Compressor&quot;</span>
  task <span class="re3">:css</span> <span class="kw1">do</span>
    <span class="kw3">puts</span> <span class="st0">&quot;<span class="es0">\n</span>Compressing stylesheet files&quot;</span>
&nbsp;
    files = <span class="kw4">Dir</span><span class="br0">&#91;</span><span class="st0">'public/stylesheets/*.css'</span><span class="br0">&#93;</span>.<span class="me1">reject</span> <span class="kw1">do</span> |f|
      f =~ /-min\.<span class="me1">css</span>$/
    <span class="kw1">end</span>
&nbsp;
    run_compressor<span class="br0">&#40;</span><span class="re3">:css</span>, files<span class="br0">&#41;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>
	É um código bastante simples. Ele simplesmente pega todos os arquivos Javascript e 
	CSS que não possuem &#034;-min&#034; no nome e aplica a compactação. O arquivo &#034;jquery.js&#034; não
	é compactado pois sempre utilizado a versão reduzida.
</p>

<p>
	Como saber se está funcionando? Faça um commit! Se os arquivos compactados foram gerados,
	tudo saiu como esperado. Você receberá uma saída como esta:
</p>

<pre class="text"><code>Compressing stylesheet files
 - application.css [15.1 KB] =&gt; application-min.css [12.3 KB]
&nbsp;
Compressing javascript files
 - application.js [4.6 KB] =&gt; application-min.js [3.1 KB]
 - facebox.js [9.2 KB] =&gt; facebox-min.js [4.9 KB]
 - jquery.form.js [22.3 KB] =&gt; jquery.form-min.js [8.2 KB]
 - rails.js [1 KB] =&gt; rails-min.js [466 Bytes]</code></pre>

<p>
	Eu estou utilizando dois helpers que exibem a versão original 
	dos arquivos caso eu esteja no ambiente de desenvolvimento, tornando
	a tarefa de depurar erros de Javascript e CSS mais simples.
</p>

<pre class="rails"><code><span class="kw1">module</span> ApplicationHelper
  <span class="kw1">def</span> compressed_stylesheets<span class="br0">&#40;</span>*files<span class="br0">&#41;</span>
    files.<span class="me1">collect</span>! <span class="kw1">do</span> |f| 
      f.<span class="kw3">gsub</span>!<span class="br0">&#40;</span>/\.<span class="me1">css</span>$/, <span class="st0">''</span><span class="br0">&#41;</span>
      <span class="st0">&quot;#{f}-min.css&quot;</span>
    <span class="kw1">end</span> <span class="kw1">unless</span> Rails.<span class="me1">env</span> == <span class="st0">&quot;development&quot;</span>
&nbsp;
    <span class="kw5">stylesheet_link_tag</span> *files
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> compressed_javascripts<span class="br0">&#40;</span>*files<span class="br0">&#41;</span>
    files.<span class="me1">collect</span>! <span class="kw1">do</span> |f| 
      f.<span class="kw3">gsub</span>!<span class="br0">&#40;</span>/\.<span class="me1">js</span>$/, <span class="st0">''</span><span class="br0">&#41;</span>
      <span class="st0">&quot;#{f}-min.js&quot;</span>
    <span class="kw1">end</span> <span class="kw1">unless</span> Rails.<span class="me1">env</span> == <span class="st0">&quot;development&quot;</span>
&nbsp;
    <span class="kw5">javascript_include_tag</span> *files
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>
	Para utilizá-los, basta passar o nome dos arquivos compactados.
</p>

<pre class="text"><code>&lt;%= compressed_stylesheets 'application' %&gt;
&lt;%= compressed_javascripts 'rails', 'facebox', 'jquery.form.js', 'application'  %&gt;</code></pre>

<h3>Importante!</h3>

<p>
	Tenha sempre em mente que se seu Javascript for
	ruim &mdash; por ruim quero dizer nas coxas, mal-feito, gambiarra, tosco, nojento, um código que 
	nem seu pior inimigo deveria ter acesso &mdash; a compactação irá, provavelmente, gerar erros de Javascript (sintaxe inválida).
</p>

<p>
	Para garantir nada irá quebrar, siga os passos explicados na página do 
	<a href="http://www.jslint.com/" rel="external" title="JSLint, The JavaScript Verifier">JSLint</a>; eu já sigo há um bom
	tempo e nunca tive nenhum problema em versões compactadas de meus códigos! Veja os erros mais comuns:
</p>

<ul>
	<li>
		não finalizar linhas de código com ponto-e-vírgula
	</li>
	
	<li>
		não utilize <code>eval</code>; 
		as funções <code>setInterval</code> e <code>setTimeout</code> também
		devem ser evitadas se o argumento for uma string. Utilize algo como
		<code>setInterval(function(){ /* do something */ }, 1000)</code>.
	</li>
	
	<li>
		evite operadores de incremento (++) e decremento (--);
		prefira algo como <code>i += 1</code> e <code>i -= 1</code>
	</li>
</ul>

<p>
	Para ver muitas outras dicas, <a href="http://www.jslint.com/lint.html" title="jslint: The JavaScript Verifier" rel="external">leia a documentação</a>
	do JSLint.
</p>

<p>
	Infelizmente, não é possível garantir que bibliotecas de terceiros irão funcionar em 100% dos casos. Leia o código antes de aplicar a compactação, já que você pode estar lidando com algo bastante ruim.
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=ISfgud"><img src="http://feeds.feedburner.com/~a/simplesideias?i=ISfgud" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/459083724" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/compactando-javascript-e-css-antes-de-fazer-um-commit-no-git/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/compactando-javascript-e-css-antes-de-fazer-um-commit-no-git/</feedburner:origLink></item>
		<item>
		<title>Rails Summit Latin America</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/423678606/</link>
		<comments>http://simplesideias.com.br/rails-summit-latin-america/#comments</comments>
		<pubDate>Fri, 17 Oct 2008 12:42:30 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[Evento]]></category>

		<category><![CDATA[Rails Summit]]></category>

		<category><![CDATA[Webco]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=263</guid>
		<description><![CDATA[
	

	Nos dias 15 e 16 de outubro aconteceu o Rails Summit Latin America, 
	evento voltado aos desenvolvedores Ruby on Rails do Brasil e países hermanos.
	Muito bem organizado pelo Fabio Akita e Locaweb, 
	teve a participação de mais de 500 pessoas, que ouviram apresentações de 
	Obie Fernandez, 
	Dr. Nic, 
	Nihn Bui &#38; Hongli Lai, 
	Chad Fowler [...]]]></description>
			<content:encoded><![CDATA[<p class="align-right">
	<img src="http://m.simplesideias.com.br/rails-summit.png" alt="Logo do Rails Summit" />
<p>
	Nos dias 15 e 16 de outubro aconteceu o <a href="http://www.locaweb.com.br/railssummit/" rel="external">Rails Summit Latin America</a>, 
	evento voltado aos desenvolvedores Ruby on Rails do Brasil e <em>países hermanos</em>.
	Muito bem organizado pelo <a href="http://akitaonrails.com" rel="external">Fabio Akita</a> e <a href="http://locaweb.com.br" rel="external">Locaweb</a>, 
	teve a participação de mais de 500 pessoas, que ouviram apresentações de 
	<a href="http://blog.obiefernandez.com/" title="Obie Fernandez" rel="external">Obie Fernandez</a>, 
	<a href="http://drnicwilliams.com/" title="Dr Nic" rel="external">Dr. Nic</a>, 
	<a href="http://www.modrails.com/" title="Overview &#x2014; Phusion Passenger&trade; (a.k.a. mod_rails / mod_rack)" rel="external">Nihn Bui &amp; Hongli Lai</a>, 
	<a href="http://chadfowler.com/" title="ChadFowler.com  Rails, Ruby, Software, and Stuff" rel="external">Chad Fowler</a> e 
	<a href="http://errtheblog.com/" title="err.the_blog" rel="external">Chris Wanstrath</a>, 
	dentre outros.
</p>

<h3>Dia 1</h3>

<p>
	No primeiro dia do evento só pude chegar depois do almoço. Queria muito ter visto a palestra do Chad Fowler que, pelo que muitos disseram, foi excelente!
	Só queria lembrar que aquele não era o Chad Fowler; provavelmente era algum alienígena que engoliu o verdadeiro. Mais magro, sem barba e de cabelo curto, chocou
	muito quem esperava ver <a href="http://m.simplesideias.com.br/chad-fowler.jpg" alt="Foto do verdadeiro Chad Fowler">este cara</a>.
</p>

<p>
	Depois foi a vez de <a href="http://www.loudthinking.com/" title="Loud Thinking by David Heinemeier Hansson" rel="external">David Heinemeir Hansson</a>, 
	que respondeu perguntas dos participantes sobre Rails 2.2 and thread-safety, dentre outras coisas em sua apresentação remota.
</p>

<p>
	Quando cheguei, <a href="http://nutrun.com/" title="nutrun" rel="external">George Malamidis</a> e 
	<a href="http://www.dtsato.com/blog/" title="Danilo Sato" rel="external">Danilo Sato</a> falavam sobre REST. 
	Pelo pouco que pude assistir, pareceu-me ter sido uma palestra interessante, embora o assunto já seja um pouco batido.
</p>

<p>
	Assim que acabou a palestra de George Malamidis, subiu ao palco Dr. Nic Williams. Engraçado, demorou um pouco para cativar o público que não o conhecia,
	mas logo arrancou boas risadas de todos. Falou sobre como manter projetos opensource, utilizando ferramentas como Git, Blogs &amp; Rubyforge, dentre outras.
</p>

<p>
	Já no fim da tarde subiu ao palco Chris Wanstrath, criador do Github e um dos mais conhecidos desenvolvedores de Ruby on Rails. 
	Ele leu na íntegra <a href="https://gist.github.com/17164/8da2bfe03a822484c25858ad0bc6b67936c8c8dc" rel="external">seu próprio texto</a>, que também foi 
	apresentado no
	<a href="http://rubyhoedown2008.confreaks.com/08-chris-wanstrath-keynote.html" title="Confreaks: Ruby Hoedown 2008" rel="external">Ruby Hoedown 2008</a>. 
	Foi meio frustrante.
</p>

<p>
	Já no final, aconteceu o Birds of Feather (BOF), uma desconferência com diversas micro-palestras.
	Nihn Bui mostrou seu compilador para 
	<a href="http://en.wikipedia.org/wiki/Brainfuck" title="Brainfuck - Wikipedia, the free encyclopedia" rel="external">Brainfuck</a> escrito em Ruby 
	(alguém me explica como as tradutoras falaram &#034;Brainfuck&#034; em português?).
	
	Depois de muito jabá e posições (sic) políticas, subiu ao palco <a href="http://twitter.com/elomar" title="Twitter / elomar">Elomar</a>, 
	de <a href="http://twitter.com/fnando/statuses/963138571" rel="external">apenas 17 anos</a>. 
	Ele conseguiu arrancar risadas do público do começo ao fim! Falou sobre sua experiência em formar um grupo de estudos com seus amigos. 
	Leia mais <a href="http://www.spiceee.com/pensaletes/2008/10/16/rails-summit-2008" rel="external">neste post</a> 
	do <a href="http://spiceee.com/pensaletes/" title="spiceee.com &raquo; pensaletes">Spiceee</a>.
	Sem dúvida, foi a <strong>melhor apresentação</strong> de todo o dia!
</p>

<p>
	Para encerrar a noite, fomos para uma churrascaria com todos os palestrantes e mais uma galera bem legal! Sooo cool! ;)
</p>

<h3>Dia 2</h3>

<p>
	O dia começou muito bem com a excelente apresentação de Ninh Bui e Hongli Lai, da Phusion. Engraçados, 
	com uma apresentação cheia de efeitos especiais, conseguiram abordar um assunto que pode se tornar chato muito
	rapidamente: infra-estrutura e deployment.
</p>

<p>
	Logo após o coffee break-começou a palestra de
	<a href="http://blog.headius.com/" title="Headius" rel="external">Charles Nutter</a> e 
	Thomas Enebo, que falaram sobre JRuby.
</p>

<p>
	A palestra seguinte que assisti foi a de <a href="http://blog.georgeguimaraes.com/" title="George on Tech" rel="external">George Guimarães</a>, 
	do <a href="http://www.pagestacker.com" title="Pagestacker" rel="external">Pagestacker</a>, que mandou muito bem falando sobre 
	ferramentas de monitoração, infra-estrutura e <em>capacity planning</em>. Paralelamente, acontecia a apresentação de 
	<a href="http://blog.jayfields.com/" title="Jay Fields' Thoughts" rel="external">Jay Fields</a>,
	que falou sobre testes e, segundo me disseram, &#034;cutucou&#034; o <a href="http://rspec.info/" title="RSpec-1.1.8: Overview" rel="external">RSpec</a>, criado por 
	<a href="http://blog.davidchelimsky.net/" title="David Chelimsky  on software in process and practice" rel="external">David Chelimsky</a>.
</p>

<p>
	Após o almoço <a href="http://manoellemos.com/" title="Manoel Lemos" rel="external">Manoel Lemos</a>, 
	<a href="http://logbr.reflectivesurface.com/" title="Superfície Reflexiva" rel="external">Ronaldo Ferraz</a> e eu falamos sobre os desafios 
	de infra-estrutura enfrentados pelo BlogBlogs e metodologia de trabalho utilizada pela 
	<a href="http://webcointernet.com/" title="WebCo - brasileiros apaixonados pela internet" rel="external">Webco</a>, abordando um pouco de SCRUM, 
	Testes, soluções desenvolvidas por nós, dentre outros assuntos. Foi muito legal ver a sala cheia quando uma palestra de David Chelimsky acontecia na mesma hora.
</p>

<p>
	Assim que acabou nossa apresentação, fui correndo para a outra sala para assistir a segunda parte da apresentação de David Chelimsky.
	Ele falou sobre BDD e o Cucumber, que substituirá o atual Story Runner. Saí antes do final para poder assistir a apresentação de 
	Vinicíus Teles, que falou sobre empreendedorismo e como descobrir oportunidades em pequenos nichos de mercado,
	<a href="http://improveit.com.br/produtos/beonthenet" title="Be on the Net - Improve It" rel="external">citando seu exemplo</a>.
</p>

<p>
	As duas palestras seguintes foram substituídas por uma papo com uma galera bem legal que pretendia gravar um vídeocast.
	Só não rolou porque o 
	<a href="http://www.daviscabral.com.br/" title="Davis.Cabral  ideas.collect {|idea| idea.process! if idea.is_valid? }" rel="external">Davis</a> 
	deu um mega-FAIL e não gravou nada.
</p>

<p>
	Para encerrar a noite, o aguardado Obie Fernandez. Depois de seu 
	<a href="http://www.infoq.com/presentations/fernandez-sales-do-the-hustle" title="InfoQ: Do the Hustle" rel="external">Do the Hustle</a>, 
	criou-se uma expectativa muito grande, que não foi em vão. Começou parabenizando o Akita, e falou sobre a escolha do nome 
	<a href="http://hashrocket.com" rel="external">Hash Rocket</a>, com um conceito muito &#034;interessante&#034; por sinal. Falou sobre metodologias de 
	desenvolvimento, organização e paixão. Conseguiu segurar a maioria das pessoas até 20h40, quando sua apresentação terminou. 
	Se ele falasse por mais uma hora, acredito que ninguém iria ligar. Foi excelente. O que me deixou mais feliz foi que pude ter certeza que 
	nós da Webco estamos no caminho certo, já que muito do que ele falou está sendo aplicado aqui! Kudos for us!
</p>

<p>
	Foi um excelente evento. Novamente, gostaria de parabenizar ao Akita e a Locaweb, que mostraram como um evento pode ser bem organizado e
	problema imprevistos podem ser rapidamente resolvidos quando se quer. Outra coisa que foi muito legal foi o papo com a galera nos corredores. 
	Encontrei pessoas que só tinha conversado por IM ou Twitter e revi pessoas que há tempos não encontrava. Espero que ano que vem tenha um
	Rails Summit Latin America 2009. Se tiver, estarei lá com certeza!
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=2z23i3"><img src="http://feeds.feedburner.com/~a/simplesideias?i=2z23i3" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/423678606" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/rails-summit-latin-america/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/rails-summit-latin-america/</feedburner:origLink></item>
		<item>
		<title>Formatando textos com o plugin has_markup no ActiveRecord</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/420494308/</link>
		<comments>http://simplesideias.com.br/formatando-textos-com-o-plugin-has_markup-no-activerecord/#comments</comments>
		<pubDate>Tue, 14 Oct 2008 12:21:07 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[ActiveRecord]]></category>

		<category><![CDATA[has_markup]]></category>

		<category><![CDATA[has_plugins]]></category>

		<category><![CDATA[HTML]]></category>

		<category><![CDATA[Markdown]]></category>

		<category><![CDATA[Plugin]]></category>

		<category><![CDATA[Textile]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=258</guid>
		<description><![CDATA[
	Às vezes é preciso deixar que um usuário entre com textos formatados
	&#8212;seja HTML puro, Markdown ou Textile. O grande problema está na hora
	de filtrar o que está sendo enviado; não queremos que um markup inválido ou
	com tags que você não quer sejam salvas no banco de dados.



	Infelizmente, o Ruby on Rails não possui nenhuma forma [...]]]></description>
			<content:encoded><![CDATA[<p>
	Às vezes é preciso deixar que um usuário entre com textos formatados
	&mdash;seja HTML puro, Markdown ou Textile. O grande problema está na hora
	de filtrar o que está sendo enviado; não queremos que um markup inválido ou
	com tags que você não quer sejam salvas no banco de dados.
</p>

<p>
	Infelizmente, o Ruby on Rails não possui nenhuma forma nativa de fazer isso 
	(na verdade, acho meio burra a decisão de manter os métodos de sanitização apenas no escopo
	de views). 
</p>

<p>
	Pensando nesse problema, criei um plugin chamado <strong>has_markup</strong>,
	que permite especificar quais tags e atributos são permitidos, eliminando todo o resto.
	Ele também normaliza o HTML enviado, convertendo-o para XHTML caso ele esteja mal-formatado.
	Você pode definir se o texto será formatado em HTML puro, Markdown ou Textile. 
</p>

<p>
	Bem simples de usar e faz o trabalho muito bem!
</p>


<h3>Como instalar</h3>
<p>
	Primeiro, vamos instalar o plugin.
</p>

<pre class="text"><code>script/plugin install git://github.com/fnando/has_markup.git</code></pre>

<p>
	O <em>has_markup</em> possui algumas dependências se você quiser usar Tidy, Markdown ou Textile.
	Veja abaixo como você pode instalar estas dependências.
</p>

<h4>Markdown</h4>
<p>
	Parar ter suporte a Markdown, é necessário instalar a gem <a href="http://github.com/rtomayko/rdiscount/tree/master" rel="external">RDiscount</a>.
</p>

<pre class="text"><code>sudo gem install rdiscount</code></pre>

<h4>Textile</h4>
<p>
	Se você prefere Textile &mdash;eu prefiro!&mdash;, instale a gem <a href="http://redcloth.org/" rel="external">RedCloth</a>.
</p>

<pre class="text"><code>sudo gem install RedCloth</code></pre>

<h4>Tidy</h4>
<p>
	Se você quer ter certeza de que não irá quebrar o seu próprio HTML, torne-o válido com
	o <a href="http://tidy.sourceforge.net/" rel="external">Tidy</a>. Primeiro é preciso instalar a biblioteca. Acesse <a href=""></a> e 
	faça o download do código-fonte. Existem alguns binários disponíveis, então dê uma olhada
	para descobrir qual é o mais adequado para você. Para compilar, execute os comandos abaixo.
</p>

<pre class="text"><code>tar xvf tidy4aug00.tgz
cd tidy4aug00
make
sudo make install</code></pre>

<p>
	O Tidy deu alguns warnings após a compilação, mas ele foi instalado. No Mac OS X ele é instalado em 
	<code>/usr/lib/libtidy.dylib</code>.
</p>

<pre class="text"><code>cp -f tidy /usr/local/bin
cp -f man_page.txt /usr/local/man/man1/tidy.1
cd /usr/local/bin; \
	chmod 755 tidy; \
	chgrp bin tidy; \
	chown bin tidy;
chown: bin: Invalid argument
make: *** [install] Error 1
&nbsp;
&nbsp;</code></pre>

<p>
	Agora instale a gem com <code>sudo gem install tidy</code>.
</p>

<p>
	Este plugin tentará encontrar o Tidy em seu sistema, procurando alguns diretórios onde ele normalmente estaria.
	Se ele não puder ser encontrado, especifique o caminho para o diretório da biblioteca em 
	seu arquivo de ambiente na constante <code>TIDY_PATH</code>.
</p>

<pre class="rails"><code><span class="co1"># config/environments/development.rb</span>
TIDY_PATH = <span class="st0">'/custom/path/to/tidy'</span></code></pre>

<h3>Usando o has_markup</h3>

<p>
	O <em>has_markup</em> é um plugin para <a href="http://ar.rubyonrails.com" rel="external">ActiveRecord</a>,
	que disponibiliza algumas ferramentas que podem ser usadas em qualquer lugar. No seu modelo, basta
	adicionar algo como isto:
</p>

<pre class="rails"><code><span class="kw1">class</span> Post &lt; <span class="re2">ActiveRecord::Base</span>
  has_markup <span class="re3">:content</span>,
    <span class="re3">:format</span>       =&gt; <span class="re3">:markdown</span>,
    <span class="re3">:tidy</span>         =&gt; <span class="kw2">true</span>,
    <span class="re3">:tags</span>         =&gt; %w<span class="br0">&#40;</span><span class="kw3">p</span> a em strong ul li<span class="br0">&#41;</span>,
    <span class="re3">:attributes</span>   =&gt; %w<span class="br0">&#40;</span>href<span class="br0">&#41;</span>
<span class="kw1">end</span></code></pre>

<p>
	No exemplo acima, o atributo <code>content</code> será formatado com Markdown. 
	Apenas algumas poucas tags estão disponíveis e apenas o atributo <code>href</code> pode ser utilizado.
	O markup também irá passar pelo Tidy, garantindo que é um XHTML válido.
</p>

<p>
	<strong>NOTA:</strong> o <em>has_markup</em> mantém uma versão final do markup em um atributo <code>formatted_&lt;attribute&gt;</code>.
	Dessa forma, você não terá problemas de performance por ter que converter o texto toda vez que quiser exibí-lo.
	O modelo acima poderia ter uma estrutura como esta:
</p>

<pre class="rails"><code>create_table <span class="re3">:posts</span> <span class="kw1">do</span> |t|
  t.<span class="me1">string</span>  <span class="re3">:title</span>
  t.<span class="me1">text</span>    <span class="re3">:content</span>, <span class="re3">:formatted_content</span>
<span class="kw1">end</span></code></pre>

<p>
	Se você não quer limitar o conteúdo salvo, basta que você não especifique as tags e atributos aceitos.
</p>

<pre class="rails"><code><span class="kw1">class</span> Post &lt; <span class="re2">ActiveRecord::Base</span>
  has_markup <span class="re3">:content</span>,
    <span class="re3">:format</span>       =&gt; <span class="re3">:textile</span>,
    <span class="re3">:tidy</span>         =&gt; <span class="kw2">true</span>
<span class="kw1">end</span></code></pre>

<p>
	É possível usar o <em>has_markup</em> apenas para validar um HTML, mesmo sem estar formatado como Markdown ou Textile; 
	basta especificar o formato <code>:html</code>.
</p>

<pre class="rails"><code><span class="kw1">class</span> Post &lt; <span class="re2">ActiveRecord::Base</span>
  has_markup <span class="re3">:content</span>,
    <span class="re3">:format</span>       =&gt; <span class="re3">:html</span>,
    <span class="re3">:tidy</span>         =&gt; <span class="kw2">true</span>
<span class="kw1">end</span></code></pre>

<p>
	Para pegar o HTML equivalente a um texto Markdown ou Textile diretamente, 
	você pode instanciar um objeto da classe <code>Markup</code>
</p>

<pre class="rails"><code>markup = Markup.<span class="kw5">new</span><span class="br0">&#40;</span><span class="re3">:markdown</span>, <span class="st0">'some text'</span><span class="br0">&#41;</span>
markup = Markup.<span class="kw5">new</span><span class="br0">&#40;</span><span class="re3">:textile</span>,  <span class="st0">'some text'</span><span class="br0">&#41;</span>
<span class="kw3">puts</span> markup.<span class="me1">to_html</span></code></pre>

<p>
	Para sanitizar códigos HTML, utilize a classe <code>Sanitize</code>.
</p>

<pre class="rails"><code><span class="co1"># will sanitize and normalize HTML</span>
Sanitize.<span class="me1">html</span><span class="br0">&#40;</span><span class="st0">'&lt;script&gt;alert(document.cookie)&lt;/script&gt;'</span><span class="br0">&#41;</span>
&nbsp;
<span class="co1"># will sanitize and allow only the specified tags</span>
Sanitize.<span class="me1">html</span><span class="br0">&#40;</span><span class="st0">'&lt;script&gt;alert(document.cookie)&lt;/script&gt;'</span>,
	<span class="re3">:tags</span> =&gt; %w<span class="br0">&#40;</span><span class="kw3">p</span> a em strong img ul li ol<span class="br0">&#41;</span>
<span class="br0">&#41;</span>
&nbsp;
<span class="co1"># will sanitize and allow only the specified attributes</span>
Sanitize.<span class="me1">html</span><span class="br0">&#40;</span><span class="st0">'&lt;script&gt;alert(document.cookie)&lt;/script&gt;'</span>,
	<span class="re3">:attributes</span> =&gt; %w<span class="br0">&#40;</span>href title alt<span class="br0">&#41;</span>
<span class="br0">&#41;</span>
&nbsp;
<span class="co1"># will sanitize and normalize HTML using Tidy</span>
Sanitize.<span class="me1">html</span><span class="br0">&#40;</span><span class="st0">'&lt;script&gt;alert(document.cookie)&lt;/script&gt;'</span>,
	<span class="re3">:tidy</span> =&gt; <span class="kw2">true</span>
<span class="br0">&#41;</span></code></pre>

<p>
	Se quiser normalizar um HTML, utilize o método <code>tidy</code>.
</p>

<pre class="rails"><code>Sanitize.<span class="me1">tidy</span><span class="br0">&#40;</span><span class="st0">'some text'</span>, options<span class="br0">&#41;</span></code></pre>

<h3>Feedback</h3>

<p>
	É isso! Se você tem alguma sugestão, dúvida ou crítica, envie um comentário.
	O projeto está hospedado no <a href="http://github.com/fnando" rel="external">Github</a>, então
	sinta-se livre para fazer um fork a qualquer momento.
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=XpXlMj"><img src="http://feeds.feedburner.com/~a/simplesideias?i=XpXlMj" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/420494308" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/formatando-textos-com-o-plugin-has_markup-no-activerecord/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/formatando-textos-com-o-plugin-has_markup-no-activerecord/</feedburner:origLink></item>
		<item>
		<title>Exibindo calendários com o plugin has_calendar no Ruby on Rails</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/395189613/</link>
		<comments>http://simplesideias.com.br/exibindo-calendarios-com-o-plugin-has_calendar-no-ruby-on-rails/#comments</comments>
		<pubDate>Wed, 17 Sep 2008 13:21:27 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[Calendário]]></category>

		<category><![CDATA[Plugin]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=251</guid>
		<description><![CDATA[
	O novo Spesa está sendo desenvolvido em ritmo acelerado 
	&#8212; isso significa que ando trabalhando muito nas minhas horas vagas &#8212; e diversas funcionalidades que estou 
	implementando estão sendo extraídas na forma de plugins.



	O mais recente deles é o has_calendar,
	que permite exibir calendários com eventos de maneira muito simples.



	A minha idéia, já que não uso [...]]]></description>
			<content:encoded><![CDATA[<p>
	O novo <a href="http://spesa.com.br" rel="external">Spesa</a> está sendo desenvolvido em ritmo acelerado 
	&mdash; isso significa que ando trabalhando muito nas minhas horas vagas &mdash; e diversas funcionalidades que estou 
	implementando estão sendo extraídas na forma de <a href="http://github.com/fnando" rel="external">plugins</a>.
</p>

<p>
	O mais recente deles é o <a href="http://github.com/fnando/has_calendar" rel="external">has_calendar</a>,
	que permite exibir calendários com eventos de maneira muito simples.
</p>

<p>
	A minha idéia, já que não uso Windows nem para desenvolvimento, nem para (sic) produção, 
	foi utilizar o comando <code>cal</code>, disponível em sistemas *nix, evitando toda a
	complexidade de ter que se trabalhar com datas. Para deixar explicíto, este plugin não
	irá funcionar no Windows.
</p>

<h3>Usando o plugin</h3>

<p>
	Primeiro, você terá que instalar o plugin. 
	Para isso, execute o comando <code>script/plugin install git://github.com/fnando/has_calendar.git</code>.
</p>

<p>
	Se você quiser exibir um calendário sem eventos, pode simplesmente chamar o helper <code>calendar</code>.
</p>

<pre class="text"><code>&lt;%= calendar %&gt;</code></pre>

<p>
	Se quiser especificar um mês específico, pode passar um hash com algumas opções.
</p>

<pre class="text"><code>&lt;%= calendar :year =&gt; 2008, :month =&gt; 9 %&gt;</code></pre>

<p>
	O dia atual é diferenciado e não exibe o número; em vez disso o texto &#034;TODAY&#034; é colocado no lugar.
	Se quiser substituir esta mensagem, utilize a opção <code>:today</code>.
</p>

<pre class="text"><code>&lt;%= calendar :today =&gt; 'HOJE' %&gt;</code></pre>

<p>
	Para adicionar eventos, você deve passar um bloco, que receberá um objeto <code>Date</code> referente ao dia do calendário.
	Assim, você pode realizar consultas relacionadas a esta data e exibí-las da maneira que achar melhor.
</p>

<pre class="text"><code>&lt;% calendar do |date| %&gt;
  &lt;% for schedule in Schedule.by_date(date) %&gt;
    &lt;%= link_to schedule.title, schedule_path(schedule) %&gt;
  &lt;% end %&gt;
&lt;% end %&gt;</code></pre>

<p>
	Como você pode perceber, isso faria até 31 consultas ao banco de dados (uma para cada dia da semana) se você não otimizasse seu código 
	(embora eu tenha escrito o artigo assim para facilitar, minha idéia de uso ia ser totalmente diferente). Pensando nisso após ler o 
	<a href="http://simplesideias.com.br/exibindo-calendarios-com-o-plugin-has_calendar-no-ruby-on-rails/#comment-93043">comentário</a> do
	<a href="http://milk-it.net/" title="Milk-it Brasil Software House" rel="external">Carlos</a>, decidi que seria melhor implementar
	uma forma onde apenas o resultado de uma consulta fosse informado.
</p>

<p>
	No template, você pode definir a opção <code>:events</code>, passando o resultado de sua consulta. O bloco, que antes recebia a data, agora
	receberá também todos os registros específicos daquele dia.
</p>

<pre class="text"><code>&lt;% calendar :events =&gt; Schedule.all, :field => :scheduled_at do |date, events| %&gt;
  &lt;% for schedule in events %&gt;
    &lt;%= link_to schedule.title, schedule_path(schedule) %&gt;
  &lt;% end %&gt;
&lt;% end %&gt;</code></pre>

<h3>Melhorando a apresentação do calendário</h3>

<p>
	Para formatar o calendário, você pode usar este CSS como ponto de partida.
</p>

<pre class="css"><code><span class="re0">#calendar</span> <span class="br0">&#123;</span>
  <span class="kw1">border-collapse</span>: <span class="kw2">collapse</span>;
  <span class="kw1">width</span>: <span class="re3"><span class="nu0">100</span>%</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#calendar</span> td,
<span class="re0">#calendar</span> th <span class="br0">&#123;</span>
  <span class="kw1">color</span>: <span class="re0">#ccc</span>;
  <span class="kw1">font-family</span>: <span class="st0">&quot;Lucida Grande&quot;</span>,arial,helvetica,<span class="kw2">sans-serif</span>;
  <span class="kw1">font-size</span>: <span class="re3">10px</span>;
  <span class="kw1">padding</span>: <span class="re3">6px</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#calendar</span> th <span class="br0">&#123;</span>
  <span class="kw1">border</span>: <span class="re3">1px</span> <span class="kw2">solid</span> <span class="re0">#ccc</span>;
  <span class="kw1">background</span>: <span class="re0">#ccc</span>;
  <span class="kw1">color</span>: <span class="re0">#<span class="nu0">666</span></span>;
  <span class="kw1">text-align</span>: <span class="kw1">left</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#calendar</span> td <span class="br0">&#123;</span>
  <span class="kw1">background</span>: <span class="re0">#f0f0f0</span>;
  <span class="kw1">border</span>: <span class="re3">1px</span> <span class="kw2">solid</span> <span class="re0">#ddd</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#calendar</span> span <span class="br0">&#123;</span>
  <span class="kw1">display</span>: <span class="kw2">block</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#calendar</span> td<span class="re1">.events</span> <span class="br0">&#123;</span>
  <span class="kw1">background</span>: <span class="re0">#fff</span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#calendar</span> td<span class="re1">.today</span> <span class="br0">&#123;</span>
  <span class="kw1">background</span>: <span class="re0">#ffc</span>;
  <span class="kw1">color</span>: <span class="re0">#<span class="nu0">666</span></span>;
<span class="br0">&#125;</span>
&nbsp;
<span class="re0">#calendar</span> caption <span class="br0">&#123;</span>
  <span class="kw1">display</span>: <span class="kw2">none</span>;
<span class="br0">&#125;</span></code></pre>

<p>
	Ele irá se parecer com isto:
</p>

<p>
	<img src="http://m.simplesideias.com.br/has_calendar.png" alt="Imagem do has_calendar com estilo CSS" />
</p>

<p>
	Mais simples, impossível! ;)
</p>

<p>
	<strong>NOTA:</strong> O Mac OS X não permite iniciar a semana pela segunda-feira. Sendo assim, se você desenvolve neste 
	sistema operacional, a semana começará no domingo. Em sistemas Linux, onde a maioria das aplicações são executadas, a
	semana iniciará na segunda-feira.
</p>

<p>
	<strong>NOTA 2:</strong> Se você quiser utilizar este plugin no Windows, certifique-se de que exista um comando <code>cal</code>
	no seu PATH, retornando exatamente a saída do comando para *nix. Ele deve ser executado no formato <code>cal -m 12 2008</code>.
	Teoricamente funciona. :)
</p>

<p>
	<strong>UPDATE:</strong> Este artigo foi atualizado para mostrar a nova opção <code>:events</code>.
</p>

<p>
	<strong>UPDATE 2:</strong> O Carlos sugeriu adicionar a chamada ao método da data no próprio helper. Claro que fica melhor! 
	Use a opção <code>:field</code>.
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=0iuT8H"><img src="http://feeds.feedburner.com/~a/simplesideias?i=0iuT8H" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/395189613" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/exibindo-calendarios-com-o-plugin-has_calendar-no-ruby-on-rails/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/exibindo-calendarios-com-o-plugin-has_calendar-no-ruby-on-rails/</feedburner:origLink></item>
		<item>
		<title>Gerenciando plugins no Rails com Pez</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/382747365/</link>
		<comments>http://simplesideias.com.br/gerenciando-plugins-no-rails-com-pez/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 23:24:26 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[Git]]></category>

		<category><![CDATA[Pez]]></category>

		<category><![CDATA[Plugins]]></category>

		<category><![CDATA[Subversion]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=245</guid>
		<description><![CDATA[
	Ultimamente, tenho usado muito mais Git, mas
	ainda tenho projetos versionados com Subversion. E como todos os 
	meus plugins estão no 
	Github, sinto uma grande dificuldade em 
	mantê-los atualizados, já que utilizam 
	SCMs diferentes.



	Como já tinha lido muito sobre algumas ferramentas para esta finalidade, como 
	Braid,
	resolvi testá-los. Infelizmente, nenhuma delas funcionava da maneira como eu gostaria. [...]]]></description>
			<content:encoded><![CDATA[<p>
	Ultimamente, tenho usado muito mais <a href="http://git-scm.com" rel="external">Git</a>, mas
	ainda tenho projetos versionados com Subversion. E como todos os 
	<a href="http://github.com/fnando/" rel="external">meus plugins</a> estão no 
	<a href="http://github.com/" rel="external">Github</a>, sinto uma grande dificuldade em 
	mantê-los atualizados, já que utilizam 
	<a href="http://en.wikipedia.org/wiki/Source_Code_Management" rel="external">SCM</a>s diferentes.
</p>

<p>
	Como já tinha lido muito sobre algumas ferramentas para esta finalidade, como 
	<a href="http://evil.che.lu/projects/braid" rel="external">Braid</a>,
	resolvi testá-los. Infelizmente, nenhuma delas funcionava da maneira como eu gostaria. Então, 
	como bom geek que sou, decidi fazer minha própria implementação: conheçam o 
	<a href="http://github.com/fnando/pez" rel="external">Pez</a>.
</p>

<p>
	Pez é um gerenciador de plugins para Rails muito simples. A diferença principal em relação 
	às ferramentas semelhantes é que ele não tenta adicionar as alterações/atualizações destes 
	plugins no repositório do projeto. Em vez disso, ele cria um diretório central e faz apenas 
	links simbólicos para o diretório <em>vendor/plugins</em> do projeto. 
	Essa abordagem permite, por exemplo, que você mantenha um único diretório de plugins 
	para diferentes projetos, desde que eles utilizem as mesmas revisões/branches.
</p>

<p>
	Mas como não é só de notícias boas que se vive, aqui vem o lado negativo desta história: você
	não conseguirá usar o Pez se usa Windows, já que muitos comandos utilizados só estão 
	disponíveis em sistemas *nix.
</p>

<p>
	Se você se interessou, veja à seguir como instalá-lo e quais são os comandos disponíveis.
</p>

<h3>Instalando o Pez</h3>

<p>
	O Pez está hospedado no Github e pode ser instalado com o comando abaixo.
</p>

<pre class="text"><code>sudo gem install fnando-pez --source=http://gems.github.com</code></pre>

<p>
	Se quiser dar uma olhada no código ou gerar sua própria versão, siga os passos abaixo.
</p>

<pre class="text"><code>git clone git://github.com/fnando/pez.git
cd pez
rake gem:install</code></pre>

<h3>Usando o Pez na prática</h3>

<p>
	Depois que o Pez tiver sido instalado, você deve executar o comando <code>pez setup</code>
	à partir da raíz de seu projeto. Isso irá criar um arquivo <em>config/plugins.yml</em>,
	que terá todas as informações dos plugins adicionados.
</p>

<pre class="text"><code>--- 
plugins: 
  rateableplugin: 
    repo: svn://rubyforge.org/var/svn/rateableplugin/trunk
    type: svn
  has_cache: 
    repo: git://github.com/fnando/has_cache.git
    type: git
    revision: 8aafca390796d79ed200000f3f13243b471b96fc
  cucumber: 
    repo: git://github.com/aslakhellesoy/cucumber.git
    type: git
    revision: 32d4f03d19bf33172bb7b48fed48e906a56598a7
    branch: html-visitor
  content_cache: 
    repo: http://svn.codahale.com/content_cache/
    type: svn
    revision: 20
development: /Users/fnando/Sites/sample/tmp/plugins
production: /Users/fnando/Sites/sample/tmp/plugins
&nbsp;</code></pre>

<p>
	Por padrão, os plugins são mantidos no diretório <em>tmp/plugins</em>. Você pode alterar essa
	configuração a qualquer momento, alterando o caminho relativo ao ambiente de seu projeto.
</p>

<p>
	O Pez possui uma série de comandos. Para ver a lista completa, execute o comando 
	<code>pez help</code>. Você pode visualizar a ajuda para um comando específico com o comando 
	<code>pez help [command]</code>.
</p>

<p>
	Como você pode perceber, não tem muito segredo! Se você tiver alguma sugestão, envie um 
	comentário. Se quiser contribuir, o projeto está no Github: 
	<a href="http://github.com/fnando/pez" rel="external">http://github.com/fnando/pez</a>.
</p>

<p>
	<strong>Trivia:</strong> O nome foi tirado de um album do <a href="http://www.lessthanjake.com/" rel="external">Less Than Jake</a> chamado Pezcore, que 
	eu estava ouvindo na hora que eu o programava. Ainda bem que não tenho gostos musicais 
	bizarros! :)
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=KZDBzI"><img src="http://feeds.feedburner.com/~a/simplesideias?i=KZDBzI" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/382747365" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/gerenciando-plugins-no-rails-com-pez/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/gerenciando-plugins-no-rails-com-pez/</feedburner:origLink></item>
		<item>
		<title>has_cache: cache no Rails de maneira simples</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/373092285/</link>
		<comments>http://simplesideias.com.br/has_cache-cache-no-rails-de-maneira-simples/#comments</comments>
		<pubDate>Sun, 24 Aug 2008 01:09:34 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[Cache]]></category>

		<category><![CDATA[memcached]]></category>

		<category><![CDATA[Performance]]></category>

		<category><![CDATA[Plugin]]></category>

		<category><![CDATA[Plugins]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=226</guid>
		<description><![CDATA[
	Há algum tempo atrás mostrei como utilizar as 
	opções de cache disponíveis no Ruby on Rails 2.1. 
	
	Embora esta tarefa tenha se tornado mais simples, ainda exige um processo um tanto quanto manual. 



	Pensando nisso, comecei a estudar formas mais automáticas de se fazer isso. Eu já simpatizava com a idéia implementada pelo Geoffrey Grosenbach, [...]]]></description>
			<content:encoded><![CDATA[<p>
	Há algum tempo atrás mostrei como utilizar as 
	<a href="http://simplesideias.com.br/conhecendo-as-opcoes-de-cache-do-rails-21/" title="Simples Idéias. Por Nando Vieira.  &raquo; Arquivo   &raquo; Conhecendo as opções de cache do Rails 2.1">opções de cache</a> disponíveis no Ruby on Rails 2.1. 
	
	Embora esta tarefa tenha se tornado mais simples, ainda exige um processo um tanto quanto manual. 
</p>

<p>
	Pensando nisso, comecei a estudar formas mais automáticas de se fazer isso. Eu já simpatizava com a idéia implementada pelo <a href="http://nubyonrails.com/" title="Nuby on Rails | Ruby on Rails for Newbies" rel="external">Geoffrey Grosenbach</a>, onde ele de mostrou uma <a href="http://nubyonrails.com/articles/about-this-blog-memcached" rel="external" title="About This Blog: Memcached | Ruby on Rails for Newbies">forma muito inteligente de lidar com cache</a> ou, melhor dizendo, com sua expiração.
</p>

<p>
	A idéia consiste basicamente em utilizar uma data de atualização do objeto para manter o controle de cache. Desta forma, sempre que a data for atualizada, o cache irá expirar automaticamente. Esta abordagem é especialmente útil quando utilizada com o Memcache, já que ele irá utilizar uma quantidade pré-definida de memória, descartando os itens mais antigos quando ela se esgotar.
</p>

<p>
	A solução que encontrei para este problema foi empacotada na forma de um plugin: <a href="http://github.com/fnando/has_cache" rel="external" title="fnando's has_cache at master &mdash; GitHub">has_cache</a>.
</p>

<h3>Utilizando o plugin has_cache</h3>
<p>
	Para usar este plugin, basta você instalá-lo através do comando abaixo:
</p>

<pre class="text"><code>script/plugin install git://github.com/fnando/has_cache.git</code></pre>

<p>
	Vale lembrar que este plugin exige as versões 2.1 ou superior do Ruby on Rails.
</p>

<p>
	O plugin possui funcionalidades específicas para models, actions e views, como você verá a seguir.
</p>

<h4>Modelos</h4>

<p>
	Depois de instalado, basta adicionar a seguinte chamada ao seu modelo:
</p>

<pre class="rails"><code><span class="kw1">class</span> Game &lt; <span class="re2">ActiveRecord::Base</span>
  <span class="kw5">has_many</span> <span class="re3">:comments</span>
  <span class="kw5">has_many</span> <span class="re3">:publishers</span>
  <span class="kw5">belongs_to</span> <span class="re3">:category</span>
&nbsp;
  has_cache
&nbsp;
  <span class="kw1">def</span> recent_comments
    comments.<span class="me1">recent</span> <span class="re3">:limit</span> =&gt; <span class="nu0">5</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>
	Apenas por adicionar a chamada ao método <code>has_cache</code>, todas as associações <code>has_many</code> e <code>belongs_to</code> irão ter uma versão com cache. Por exemplo, em vez de utilizar <code>@game.comments</code>, você pode utilizar <code>@game.cached_comments</code>. Simples assim!
</p>

<p>
	Você também pode adicionar métodos que não são relacionamentos; basta utilizar a opção <code>:include</code>.
</p>

<pre class="rails"><code>has_cache <span class="re3">:include</span> =&gt; <span class="re3">:recent_comments</span></code></pre>

<p>
	O exemplo acima irá adicionar o <em>método de instância</em> <code>recent_comments</code>. Se precisar adicionar <em>métodos de classe</em>, pode adicionar uma chamada como esta:
</p>

<pre class="rails"><code>has_cache <span class="re3">:include</span> =&gt; <span class="br0">&#123;</span>
  <span class="re3">:class_methods</span> =&gt; %w<span class="br0">&#40;</span>all find<span class="br0">&#41;</span>, 
  <span class="re3">:instance_methods</span> =&gt; <span class="re3">:recent_comments</span>
<span class="br0">&#125;</span></code></pre>

<p>
	Os métodos de classe possuem um argumento obrigatório, que é a chave que irá identificar aquele cache.
</p>

<pre class="text"><code>Game.cached_all :sorted_by_title, :order =&gt; 'title asc'</code></pre>

<p>
	Se você instalar o plugin <a href="http://github.com/fnando/has_paginate/" rel="external" title="fnando's has_paginate at master &mdash; GitHub">has_paginate</a>, poderá fazer consultas paginadas com cache.
</p>

<pre class="rails"><code>Game.<span class="me1">cached_paginate</span> %w<span class="br0">&#40;</span>all <span class="re1">@page</span><span class="br0">&#41;</span>, <span class="re3">:order</span> =&gt; <span class="st0">'title asc'</span>, <span class="re3">:page</span> =&gt; <span class="re1">@page</span>
<span class="re1">@game</span>.<span class="me1">cached_comments</span><span class="br0">&#40;</span><span class="re3">:page</span> =&gt; <span class="re1">@page</span><span class="br0">&#41;</span></code></pre>

<p>
	Se quiser evitar a paginação, basta passar a opção <code>:paginate</code> com o valor <code>false</code>.
</p>

<pre class="rails"><code><span class="re1">@game</span>.<span class="me1">cached_comments</span><span class="br0">&#40;</span><span class="re3">:paginate</span> =&gt; <span class="kw2">false</span><span class="br0">&#41;</span></code></pre>

<p>
	<strong>ATENÇÃO:</strong> Se o plugin has_paginate estiver instalado, todas as associações <code>has_many</code> serão paginadas por padrão.
</p>

<p>
	Mais à frente você verá como o cache é expirado, e como definir novas chaves que serão expiradas.
</p>

<h4>Controllers</h4>
<p>
	No controller, você pode utilizar o método <code>cached_render</code>:
</p>

<pre class="rails"><code><span class="kw1">class</span> GamesController &lt; ApplicationController
  <span class="kw1">def</span> index
    <span class="re1">@page</span> = <span class="br0">&#91;</span>params<span class="br0">&#91;</span><span class="re3">:page</span><span class="br0">&#93;</span>.<span class="kw5">to_i</span>, <span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">max</span>
&nbsp;
    cached_render <span class="re3">:cache_name</span> =&gt; %w<span class="br0">&#40;</span>games index#{@page}) do
      <span class="re1">@games</span> = Game.<span class="me1">cached_paginate</span> %w<span class="br0">&#40;</span>all #{@page}), @page
    <span class="kw1">end</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>
	Você pode especificar o tempo de vida do cache com a opção <code>:expires_in</code>.
</p>

<pre class="rails"><code>cached_render <span class="re3">:expires_in</span> =&gt; <span class="nu0">15</span>.<span class="me1">minutes</span> <span class="kw1">do</span>
  <span class="co1"># do something</span>
<span class="kw1">end</span></code></pre>

<p>
	Sempre que puder, utilize esta abordagem. Porém, se algum detalhe da tela é diferente para os usuários &mdash; um usuário logado tem um box com alguma identificação &mdash;, você não conseguirá fazer cache de toda a <em>action</em>. Mas poderá ter uma boa performance fazendo cache de pedaços da tela.
</p>

<h4>Views</h4>

<p>
	Você pode fazer cache de fragmentos de um template. O plugin has_cache adiciona um método chamado <code>cached_block</code>.
</p>

<pre class="text"><code>&lt;h1&gt;Games&lt;/h1&gt;
&nbsp;
&lt;% cached_block [:game_list, @page] do %&gt;
  &lt;ul&gt;
    &lt;% each_paginate @games do |game, i| %&gt;
      &lt;li&gt;
        &lt;%= game.title %&gt;
      &lt;/li&gt;
    &lt;% end %&gt;
  &lt;/ul&gt;
&nbsp;
  &lt;%= paginate @games, url_for(:action =&gt; 'index') %&gt;
&lt;% end %&gt;</code></pre>

<p>
	Você também pode definir o tempo de vida do cache com a opção <code>:expires_in</code>.
</p>

<pre class="text"><code>&lt;% cached_block [:game_list, @page], :expires_in =&gt; 1.hour do %&gt;
  &lt;!-- do something --&gt;
&lt;% end %&gt;</code></pre>

<h3>Como funciona a expiração do cache</h3>

<p>
	Todo relacionamento <code>has_many</code> precisa de um campo com o nome do relacionamento, que servirá como o controle de expiração do cache. No nosso exemplo, nosso modelo deveria ser criado da seguinte forma:
</p>

<pre class="rails"><code><span class="kw1">class</span> CreateGames &lt; <span class="re2">ActiveRecord::Migration</span>
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">up</span>
    create_table <span class="re3">:games</span> <span class="kw1">do</span> |t|
      t.<span class="me1">references</span> <span class="re3">:category</span>
      t.<span class="me1">datetime</span> <span class="re3">:comments_updated_at</span>, <span class="re3">:publishers_updated_at</span>
      t.<span class="me1">string</span> <span class="re3">:title</span>
&nbsp;
      t.<span class="me1">timestamps</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">down</span>
    drop_table <span class="re3">:games</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>
	Toda vez que um comentário for criado, o plugin irá atualizar automaticamente o campo <code>comments_updated_at</code>, que é utilizado na composição da chave que irá identificar o cache. O mesmo irá acontecer quando um novo <em>publisher</em> for adicionado.
</p>

<p>
	As seguintes estruturas de chave são expiradas quando um objeto é salvo ou destruído:
</p>

<dl class="code">
	<dt>próprio objeto</dt>
	<dd><code>:table/:id</code></dd>
	<dd><code>:table/:id-:updated_at</code></dd>
	
	<dt>associações <code>has_many</code></dt>
	<dd><code>:table/:id/:updated_at/:association/:association_updated_at</code></dd>
	
	<dt>associações <code>belongs_to</code></dt>
	<dd><code>:table/:id</code></dd>
	
	<dt>métodos de instância</dt>
	<dd><code>:table/:id/:updated_at/:method_name</code></dd>
	
	<dt>métodos de classe</dt>
	<dd>Não são expirados automaticamente.</dd>
</dl>

<p>
	Como os métodos de classe recebem uma chave na hora que são chamados, não podem ser expirados automaticamente. Neste caso, você pode deixar o método expirar por tempo ou forçar sua expiração.
</p>

<pre class="rails"><code>has_cache <span class="re3">:before_expire</span> =&gt; <span class="kw3">proc</span> <span class="br0">&#123;</span>|game|
  Game.<span class="me1">has_cache_options</span><span class="br0">&#91;</span><span class="re3">:to_expire</span><span class="br0">&#93;</span> &lt;&lt; <span class="st0">&quot;games/sorted_by_title&quot;</span>
<span class="br0">&#125;</span></code></pre>

<h3>E para finalizar&#8230;</h3>

<p>
	Se você tiver alguma sugestão, faça um fork do <a href="http://github.com/fnando/has_cache/" rel="external" title="fnando's has_cache at master &mdash; GitHub">has_cache</a> e envie um patch. Dúvidas? Mande um comentário.
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=twoYAR"><img src="http://feeds.feedburner.com/~a/simplesideias?i=twoYAR" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/373092285" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/has_cache-cache-no-rails-de-maneira-simples/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/has_cache-cache-no-rails-de-maneira-simples/</feedburner:origLink></item>
		<item>
		<title>Textmate cheat sheet</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/351965978/</link>
		<comments>http://simplesideias.com.br/textmate-cheat-sheet/#comments</comments>
		<pubDate>Thu, 31 Jul 2008 21:05:02 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Mac OS X]]></category>

		<category><![CDATA[Cheat Sheet]]></category>

		<category><![CDATA[Textmate]]></category>

		<category><![CDATA[Wallpaper]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=223</guid>
		<description><![CDATA[
	O Textmate possui uma série de atalhos que se você não souber como usá-los, será como utilizar um Notepad.
	Pensando nisso, fiz um wallpaper com diversos atalhos que são muito úteis e que você precisa conhecer.



	
		
	



	Você pode fazer o download do wallpaper aqui. 
	Note que ele foi feito especialmente para 
	Macbooks, 
	com resolução de 1280&#215;800.
]]></description>
			<content:encoded><![CDATA[<p>
	O <a href="http://macromates.com" rel="external">Textmate</a> possui uma série de atalhos que se você não souber como usá-los, será como utilizar um Notepad.
	Pensando nisso, fiz um wallpaper com diversos atalhos que são muito úteis e que você precisa conhecer.
</p>

<p>
	<a href="http://m.simplesideias.com.br/fnando-desktop.png">
		<img src="http://m.simplesideias.com.br/fnando-desktop-thumb.png" alt="Meu desktop com o wallpaper de atalhos do Textmate" />
	</a>
</p>

<p>
	Você pode fazer o <a href="http://f.simplesideias.com.br/matesheet.png">download do wallpaper aqui</a>. 
	Note que ele foi feito especialmente para 
	<a href="http://boo-box.com/link/bid:364/lang:pt-BR/tags:macbook/format:box" class="bbli">Macbooks<img src="http://boo-box.com/bbli" alt="[bb]" class="bbic" /></a>, 
	com resolução de 1280&#215;800.
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=GI3wAM"><img src="http://feeds.feedburner.com/~a/simplesideias?i=GI3wAM" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/351965978" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/textmate-cheat-sheet/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/textmate-cheat-sheet/</feedburner:origLink></item>
		<item>
		<title>Utilizando o padrão Singleton no Ruby</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/343140592/</link>
		<comments>http://simplesideias.com.br/utilizando-o-padrao-singleton-no-ruby/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 03:09:29 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Classes]]></category>

		<category><![CDATA[Design Pattern]]></category>

		<category><![CDATA[Orientação à Objetos]]></category>

		<category><![CDATA[Singleton]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=219</guid>
		<description><![CDATA[
	Singleton 
	é um design pattern usado para restringir a instanciação de objetos, fornecendo um ponto global de acesso a uma única instância de uma classe.



	No Ruby, você pode utilizar este padrão da maneira mais simples possível. Basta carregar a biblioteca Singleton.


require &#34;singleton&#34;
&#160;
class Database
  include Singleton
&#160;
  def connect
    @connection = Adapter.connect
 [...]]]></description>
			<content:encoded><![CDATA[<p>
	<a href="http://en.wikipedia.org/wiki/Singleton_pattern" title="Singleton pattern - Wikipedia, the free encyclopedia" rel="external">Singleton</a> 
	é um <em>design pattern</em> usado para restringir a instanciação de objetos, fornecendo um ponto global de acesso a uma única instância de uma classe.
</p>

<p>
	No Ruby, você pode utilizar este padrão da maneira mais simples possível. Basta carregar a biblioteca <a href="http://www.ruby-doc.org/stdlib/libdoc/singleton/rdoc/index.html" title="singleton: Ruby Standard Library Documentation" rel="external">Singleton</a>.
</p>

<pre class="rails"><code><span class="kw3">require</span> <span class="st0">&quot;singleton&quot;</span>
&nbsp;
<span class="kw1">class</span> Database
  <span class="kw1">include</span> <span class="kw4">Singleton</span>
&nbsp;
  <span class="kw1">def</span> connect
    <span class="re1">@connection</span> = Adapter.<span class="me1">connect</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>
	Ao adicionar o módulo <code>Singleton</code>, você torna o método <code>new</code> privado. 
	Se você tentar instanciar esta classe, verá um erro como este:
</p>

<pre class="text"><code>NoMethodError: private method `new' called for Test:Class
  from (irb):3
  from :0</code></pre>

<p>
	Para ter acesso à instância da classe <code>Test</code>, você deve utilizar o método <code>instance</code>.
</p>

<pre class="rails"><code>Database.<span class="me1">instance</span>.<span class="me1">connect</span></code></pre>

<p>
	Muito elegante, assim como quase tudo no Ruby!
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=Rgz5Qt"><img src="http://feeds.feedburner.com/~a/simplesideias?i=Rgz5Qt" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/343140592" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/utilizando-o-padrao-singleton-no-ruby/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/utilizando-o-padrao-singleton-no-ruby/</feedburner:origLink></item>
		<item>
		<title>Utilizando o named_scope no ActiveRecord do Ruby on Rails 2.1</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/335563568/</link>
		<comments>http://simplesideias.com.br/utilizando-o-named_scope-no-activerecord-do-ruby-on-rails-21/#comments</comments>
		<pubDate>Tue, 15 Jul 2008 00:11:22 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby on Rails]]></category>

		<category><![CDATA[ActiveRecord]]></category>

		<category><![CDATA[named_scope]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=217</guid>
		<description><![CDATA[
	O Ruby on Rails 2.1 trouxe uma série de novidades em quase todos os módulos do framework. 
	Uma das novidades que mais gostei foi o named_scope, que permite criar buscas personalizadas, sem perder a elegância.
	Veja como usar todo o poder desta funcionalidade neste artigo.


Exemplos de uso


	Imagine que você tenha dois modelos: Band e Genre.


class CreateBands [...]]]></description>
			<content:encoded><![CDATA[<p>
	O Ruby on Rails 2.1 trouxe uma série de novidades em quase todos os módulos do framework. 
	Uma das novidades que mais gostei foi o <a href="http://ar.rubyonrails.com/classes/ActiveRecord/NamedScope/ClassMethods.html#M000278" rel="external">named_scope</a>, que permite criar buscas personalizadas, sem perder a elegância.
	Veja como usar todo o poder desta funcionalidade neste artigo.
</p>

<h3>Exemplos de uso</h3>

<p>
	Imagine que você tenha dois modelos: <code>Band</code> e <code>Genre</code>.
</p>

<pre class="rails"><code><span class="kw1">class</span> CreateBands &lt; <span class="re2">ActiveRecord::Migration</span>
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">up</span>
    create_table <span class="re3">:bands</span> <span class="kw1">do</span> |t|
      t.<span class="me1">string</span> <span class="re3">:name</span>
      t.<span class="me1">references</span> <span class="re3">:genre</span>
&nbsp;
      t.<span class="me1">timestamps</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">down</span>
    drop_table <span class="re3">:bands</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;</code></pre>

<pre class="rails"><code><span class="kw1">class</span> CreateGenres &lt; <span class="re2">ActiveRecord::Migration</span>
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">up</span>
    create_table <span class="re3">:genres</span> <span class="kw1">do</span> |t|
      t.<span class="me1">string</span> <span class="re3">:name</span>
      t.<span class="me1">timestamps</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">down</span>
    drop_table <span class="re3">:genres</span>
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;</code></pre>

<p>
	Antes do Ruby on Rails 2.1, se você quisesse criar consultas personalizadas poderia criar métodos ou estender as associações.
	Por exemplo, poderíamos implementar uma busca pelos artistas recentes ou de um gênero.
</p>

<pre class="rails"><code><span class="kw1">class</span> Band &lt; <span class="re2">ActiveRecord::Base</span>
  <span class="kw5">belongs_to</span> <span class="re3">:genre</span>
&nbsp;
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">recent</span>
    all <span class="re3">:order</span> =&gt; <span class="st0">&quot;created_at desc&quot;</span>
  <span class="kw1">end</span>
&nbsp;
  <span class="kw1">def</span> <span class="kw2">self</span>.<span class="me1">by_genre</span><span class="br0">&#40;</span>genre<span class="br0">&#41;</span>
    all <span class="re3">:conditions</span> =&gt; <span class="br0">&#123;</span>:genre_id =&gt; genre<span class="br0">&#125;</span>
  <span class="kw1">end</span>
<span class="kw1">end</span></code></pre>

<p>
	Mas como você faria se quisesse todos os artistas recentes de um gênero? 
	E se você quisesse adicionar mais uma condição, como a primeira letra do nome do artista?
	É quando a coisa se complica!
	Se você usar o <code>named_scope</code>, pode escrever o exemplo anterior desta maneira:
</p>

<pre class="rails"><code><span class="kw1">class</span> Band &lt; <span class="re2">ActiveRecord::Base</span>
  <span class="kw5">belongs_to</span> <span class="re3">:genre</span>
&nbsp;
  named_scope <span class="re3">:recent</span>, <span class="re3">:order</span> =&gt; <span class="st0">&quot;created_at desc&quot;</span>
  named_scope <span class="re3">:by_genre</span>, <span class="kw3">lambda</span> <span class="br0">&#123;</span>|genre| <span class="br0">&#123;</span>:conditions =&gt; <span class="br0">&#91;</span><span class="st0">&quot;genre_id = ?&quot;</span>, genre<span class="br0">&#93;</span> <span class="br0">&#125;</span><span class="br0">&#125;</span>
<span class="kw1">end</span></code></pre>

<p>
	Ambas abordagens funcionam da mesma maneira quando acessadas sozinhas, como <code>Band.recent</code> ou <code>Band.by_genre(params[:genre_id])</code>.
	A difença principal do <code>named_scope</code> é que você pode fazer chamadas encadeadas, propagando as opções de consulta. Note que não é preciso seguir nenhuma ordem específica nas chamadas.
</p>

<pre class="rails"><code>Band.<span class="me1">recent</span>.<span class="me1">by_genre</span><span class="br0">&#40;</span>params<span class="br0">&#91;</span><span class="re3">:genre_id</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
Band.<span class="me1">by_genre</span><span class="br0">&#40;</span>params<span class="br0">&#91;</span><span class="re3">:genre_id</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">recent</span></code></pre>

<p>
	Todas as buscas adicionadas pelo <code>named_scope</code> se comportam como objetos do ActiveRecord. Você pode executar contagens, fazer outras buscas ou agir ativamente nos resultados retornados.
</p>

<pre class="rails"><code>Band.<span class="me1">by_genre</span>.<span class="kw5">first</span><span class="br0">&#40;</span><span class="re3">:conditions</span> =&gt; <span class="br0">&#91;</span><span class="st0">&quot;name = ?&quot;</span>, params<span class="br0">&#91;</span><span class="re3">:name</span><span class="br0">&#93;</span><span class="br0">&#93;</span><span class="br0">&#41;</span>
Band.<span class="me1">recent</span>.<span class="me1">reload</span>
Band.<span class="me1">recent</span>.<span class="kw5">count</span>
Band.<span class="me1">by_genre</span><span class="br0">&#40;</span>params<span class="br0">&#91;</span><span class="re3">:genre_id</span><span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">fans</span>.<span class="me1">average</span><span class="br0">&#40;</span><span class="re3">:fans_count</span><span class="br0">&#41;</span></code></pre>

<p>
	Se você ainda não usa o <code>named_scope</code>, comece a usá-la agora mesmo!
	Ele é, sem dúvida, uma das melhores funcionalidades do ActiveRecord. 
	Não sei como pude viver sem isto até agora!
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=bmnozU"><img src="http://feeds.feedburner.com/~a/simplesideias?i=bmnozU" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/335563568" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/utilizando-o-named_scope-no-activerecord-do-ruby-on-rails-21/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/utilizando-o-named_scope-no-activerecord-do-ruby-on-rails-21/</feedburner:origLink></item>
		<item>
		<title>Executando métodos sem se preocupar com exceções no Ruby</title>
		<link>http://feeds.feedburner.com/~r/simplesideias/~3/335466456/</link>
		<comments>http://simplesideias.com.br/executando-metodos-sem-se-preocupar-com-excecoes-no-ruby/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 21:55:53 +0000</pubDate>
		<dc:creator>Nando Vieira</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Dica]]></category>

		<category><![CDATA[Exception]]></category>

		<guid isPermaLink="false">http://simplesideias.com.br/?p=218</guid>
		<description><![CDATA[
	Cansado de ter que verificar se um objeto existe antes de chamar algum método ou acessar um atributo?


if @object &#38;&#38; @object.some &#38;&#38; @object.some.fancy &#38;&#38; @object.some.fancy.call
  # do something
else
  puts &#34;meh. i don't like this syntax!&#34;
end


	Concordo que isto não é muito comum, mas você já deve ter feito algo como isto:


if @object &#38;&#38; @object.respond_to?&#40;:some_method&#41; [...]]]></description>
			<content:encoded><![CDATA[<p>
	Cansado de ter que verificar se um objeto existe antes de chamar algum método ou acessar um atributo?
</p>

<pre class="rails"><code><span class="kw1">if</span> <span class="re1">@object</span> &amp;&amp; <span class="re1">@object</span>.<span class="me1">some</span> &amp;&amp; <span class="re1">@object</span>.<span class="me1">some</span>.<span class="me1">fancy</span> &amp;&amp; <span class="re1">@object</span>.<span class="me1">some</span>.<span class="me1">fancy</span>.<span class="kw5">call</span>
  <span class="co1"># do something</span>
<span class="kw1">else</span>
  <span class="kw3">puts</span> <span class="st0">&quot;meh. i don't like this syntax!&quot;</span>
<span class="kw1">end</span></code></pre>

<p>
	Concordo que isto não é muito comum, mas você já deve ter feito algo como isto:
</p>

<pre class="rails"><code><span class="kw1">if</span> <span class="re1">@object</span> &amp;&amp; <span class="re1">@object</span>.<span class="kw5">respond_to</span>?<span class="br0">&#40;</span><span class="re3">:some_method</span><span class="br0">&#41;</span> &amp;&amp; <span class="re1">@object</span>.<span class="me1">some_method</span>
  <span class="co1"># do something</span>
<span class="kw1">end</span></code></pre>

<p>
	Evite este tipo de aborrecimento trazido por estas verificações, adicionando um método como este:
</p>

<pre class="rails"><code><span class="kw1">def</span> try<span class="br0">&#40;</span>&amp;block<span class="br0">&#41;</span>
  <span class="kw3">raise</span> <span class="st0">'No block given'</span> <span class="kw1">unless</span> block_given?
  <span class="kw1">yield</span> <span class="kw1">rescue</span> <span class="kw2">nil</span>
<span class="kw1">end</span>
&nbsp;
<span class="kw1">if</span> try <span class="br0">&#123;</span> <span class="re1">@objet</span>.<span class="me1">some</span>.<span class="me1">fancy</span>.<span class="kw5">call</span> <span class="br0">&#125;</span>
  <span class="co1"># do something</span>
<span class="kw1">else</span>
  <span class="kw3">puts</span> <span class="st0">'hey! this call returned nil, false or threw an exception'</span>
<span class="kw1">end</span></code></pre>

<p>
	Muito mais com a cara de Ruby, não acha?
</p>
<p><a href="http://feeds.feedburner.com/~a/simplesideias?a=eXBD1k"><img src="http://feeds.feedburner.com/~a/simplesideias?i=eXBD1k" border="0"></img></a></p><img src="http://feeds.feedburner.com/~r/simplesideias/~4/335466456" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://simplesideias.com.br/executando-metodos-sem-se-preocupar-com-excecoes-no-ruby/feed/</wfw:commentRss>
		<feedburner:origLink>http://simplesideias.com.br/executando-metodos-sem-se-preocupar-com-excecoes-no-ruby/</feedburner:origLink></item>
	</channel>
</rss>
