<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/_xslt/rss20_xhtml10_strict.xsl" type="text/xsl" media="screen"?>
<rss version="2.0">
  <channel>
    <title>Eine Zufuhransammlung</title>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://www.xfruits.com/lsdr/planet/" type="text/xml"/>
    <link>http://xfruits.com/lsdr/</link>
    <description/>
    <language>en-us</language>
    <copyright/>
    <generator>xFruits - http://www.xfruits.com</generator>
    <pubDate>Fri, 03 Jul 2009 12:34:58 GMT</pubDate>
    <lastBuildDate>Tue, 30 Nov 1999 00:00:00 GMT</lastBuildDate>
    <category>rss feed planet collection</category>
    <item>
      <title>XHML 2 Charter Set To Expire</title>
      <description/>
      <pubDate>Fri, 03 Jul 2009 09:40:39 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124202&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Philippe Le Hegaret and Ian Jacobs: W3C management has decided to allow the Working Group’s charter to expire at the end of 2009 and not to renew it ... we expect the next generation XML serialization of HTML to be defined in the HTML 5 specification.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124202" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3038</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Seleções de blocos com o Vim</title>
      <description><![CDATA[<object width="425" height="344">
<param name="movie" value="http://www.youtube.com/v/B22N3-pFRSw"></param>
<param name="wmode" value="transparent"></param>
<embed src="http://www.youtube.com/v/33oelVTGnAU" type="application/x-shockwave-flash" wmode="transparent" width="425" height="344"></embed>
</object>

<p>
Ontem o meu amigo <a href="http://samirmamude.com">Samir Mamude</a> me chamou a atenção para <a href="http://cidadaocarioca.blogspot.com/2009/06/visual-studio-2010-novidades-na-edicao.html">esse post aqui</a>, onde o autor mostrou alguns dos recursos novos do <a href="http://www.microsoft.com/visualstudio/en-us/products/2010/default.mspx">Microsoft Visual Studio 2010</a>, que agora possibilita recursos para edição em blocos.
</p>

<p>
Como ele bem comentou lá no post original, nós já temos esses recursos já faz um bom tempo, no bom e velho (jurássico é sacanagem) <a href="http://www.vim.org">Vim</a>, e como o autor do post pediu um vídeo para compararmos (ou provarmos que existia mesmo, sei lá), eu fiz <a href="http://www.youtube.com/watch?v=33oelVTGnAU">esse vídeo aí em cima</a> mostrando como funcionam os recursos similares do Vim para esse tipo de coisa. Vale lembrar, como disse no post original:
</p>

<ol>
<li>Eram 23:36, eu estava com sono e tive que fazer "colinha" do código ali e comi alguma bronha pois ...</li>
<li>... retirei TODOS os plugins e zerei meu .vimrc, deixando ele PELADO para fazer o vídeo. Algumas coisas como o autocomplete de chaves e parênteses sem funcionar deixam a gente perdido. Eram algumas poucas linhas para habilitar isso no arquivo de configuração, antes que falem alguma coisa.</li>
<li>Eu estava rodando ele direto num terminal, para mostrar que mesmo em um terminalzão texto isso tudo funciona. Quebra um baita galho usando com SSH. No modo gráfico fica mais bonito, mas eu quis mostrar na lasqueira mesmo.</li>
<li>Sem chance de ter som no vídeo, o Corinthians estava jogando e o mundo estava se acabando em fogos aqui. :-)</li>
<li>Não, eu não programo em C#, só quis fazer o exemplo ficar igual. ;-)</li>
</ol>

<p>
Eu inseri algumas anotações durante o vídeo, mas dando uma resumida aqui:
</p>

<ol>
<li>O segredo da coisa está na combinação de teclas <tt>CTRL+V</tt>. Acionando as danadas podemos fazer seleções em blocos.</li>
<li>Depois de selecionar os <tt>readonly</tt> usando <tt>w</tt> para ir até no final da palavra e as setas (ou melhor, como anotei lá, usar <tt>4j</tt> para descer direto), eu apaguei o bloco com <tt>x</tt>.</li>
<li>Para fazer as inserções dos <tt>m_</tt>, eu selecionei o bloco e apertei <tt>I</tt> (insert), digitando o texto que queria inserir no restante do bloco (no caso, <tt>m_</tt>) e logo após apertei <tt>ESC</tt>, o que repetiu tudo o que eu fiz para o restante do bloco.</li>
<li>Para trocar todos os <tt>public</tt> para <tt>readonly</tt>, eu selecionei o block e apertei <tt>c</tt> (change), digitando o texto que queria seguido por <tt>ESC</tt>.</li>
<li>Para os comentários, selecionei o bloco no final da linha, apertei <tt>$A</tt> (importante notar o <tt>$</tt> que indica o final da linha, e <tt>A</tt> de append), digitei o texto que queria (<tt>// Comment</tt>) e apertei <tt>ESC</tt>.</li>
<li>Para inserir o código novo, digitei a primeira e a segunda linha, sendo que a segunda eu desconfio que saiu fora da indentação pois eu havia deixado a configuração zerada para o teste. Logo após repliquei a segunda linha com <tt>y</tt> (yank, para copiar) e <tt>4p</tt>, o que colou ela 4 vezes. Em seguida marquei o bloco logo acima e copiei e colei com <tt>y</tt> e <tt>p</tt> no lugar determinado, retirando que não era necessário com <tt>dw</tt> (apagar palavra), movendo com <tt>w</tt> (palavra pra frente) e <tt>b</tt> (palavra pra trás).</li>
</ol>

<p>
Pronto! O resultado foi similar, lembrando que foi feito em um terminal texto, sem necessidade de modo gráfico, o que várias vezes é uma mão-na-roda e quebra um galhão (ainda mais acessando via SSH) e que temos esse recurso faz um bom tempo já. No modo gráfico fica até mais bonito, e com alguns <a href="http://www.vim.org/scripts/index.php">plugins</a> habilitados a edição fica rápida e matadora!
</p>

<p>
As combinações de teclas podem assustar em um primeiro momento, mas é como até foi mencionado, se você se acostuma com o editor, é uma coisa meio de reflexo e muito rápida. O Vim assusta em um primeiro contato, mas depois que gosta não fica sem. Vejam a <a href="http://aurelio.wordpress.com/2009/06/30/10anos-vim/">saga do Aurélio com o Vim</a> para ver o tamanho do abacaxi quando se começa a usar o negócio. :-)
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388994438" />
]]></description>
      <pubDate>Fri, 03 Jul 2009 02:48:27 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388994438&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F563</link>
      <guid>http://eustaquiorangel.com/posts/563</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Rails é o novo ASP, redux</title>
      <description><![CDATA[E depois tem gente que acha que eu estou brincando quando digo que Rails é o novo ASP. Agora temos um Rails Rescue Handbook, especialmente voltado para projetos Rails que estão no buraco. Eu acho maravilhoso!<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847728" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/07/02/rails-e-o-novo-asp-redux/#comments</comments>
      <pubDate>Thu, 02 Jul 2009 19:53:13 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847728&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F07%2F02%2Frails-e-o-novo-asp-redux%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>E depois tem gente que acha que eu estou brincando quando digo que Rails é o novo ASP. Agora temos um <a href="http://www.infoq.com/news/2009/07/rails-rescue-handbook">Rails Rescue Handbook</a>, especialmente voltado para projetos Rails que estão no buraco. Eu acho maravilhoso! <img src='http://logbr.reflectivesurface.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>]]></content:encoded>
      <category>Geral</category>
      <guid>http://logbr.reflectivesurface.com/2009/07/02/rails-e-o-novo-asp-redux/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Media Dependent Styling</title>
      <description><![CDATA[I finally decided to upgrade my cell phone to one that supports the web and email.  I settled on an LG enV3 in slate blue.  One of the pages I frequently check is my comments page, and as I had taken care to ensure that the markup degraded gracefully, the page displays adequately on my mobile device — with one obvious annoyance that surprised me.
To read the comments, I have to horizontally scroll.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124203" />
]]></description>
      <pubDate>Thu, 02 Jul 2009 10:50:45 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124203&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[I finally decided to upgrade my cell phone to one that supports the web and email.  I settled on an LG enV3 in slate blue.  One of the pages I frequently check is my comments page, and as I had taken care to ensure that the markup degraded gracefully, the page displays adequately on my mobile device — with one obvious annoyance that surprised me.
To read the comments, I have to horizontally scroll.  Usability significantly improves if I add the following to my CSS:
body {width:320px}
Now, clearly I don’t want all user agents to format the page with a 320px width.  My preferred approach would be to solve this in the CSS.  The first thing I tried was media="handheld", but sadly the results showed that this was ignored.
I tried Media Queries, but they too were ignored.  This opens up the possibility of styling by default a limited width and only utilizing the full width on browsers that support Media Queries.  Firefox 3.5 being one such browser.  Firefox 3.0.11 doesn’t have such support.  My conclusion is that this isn’t widely enough supported for me to depend on it.
I may end up having to do conneg.  Available headers include:
HTTP_X_WAP_PROFILE: "http://uaprof.vtext.com/lg/vx9200/vx9200.xml"
HTTP_ACCEPT_CHARSET: utf-8, utf-16, us-ascii, iso-8859-1
HTTP_USER_AGENT: Mozilla/5.0 (compatible; Teleca Q7; Brew 3.1.5; U; en) 320X240 LGE VX9200
HTTP_VIA: 1.1 Comverse 4.5
HTTP_ACCEPT: text/html, application/xhtml+xml, multipart/mixed, multipart/related, */*
HTTP_ACCEPT_LANGUAGE: en; q=1.0, en, *; q=0.5
HTTP_ACCEPT_ENCODING': gzip, deflate]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3037</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Rails Book Update and Outlook</title>
      <description><![CDATA[Agile Web Development with Rails, 3rd Edition is about to have its third printing.  Translations are under way for Chinese, Japanese, Korean, and Spanish.  One thing I wasn’t aware of before participating in the development of this book is that printers have an opportunity to address errata in each printing.  Other changes are fodder for a new edition (or possibly even a new title).  What would I like to see in a follow-on to this book?<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124204" />
]]></description>
      <pubDate>Wed, 01 Jul 2009 15:52:27 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124204&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Agile Web Development with Rails, 3rd Edition is about to have its third printing.  Translations are under way for Chinese, Japanese, Korean, and Spanish.
One thing I wasn’t aware of before participating in the development of this book is that printers have an opportunity to address errata in each printing.  I don’t know how widespread this practice is, but this is definitely something that Pragmatic Programmers takes advantage of.  The ground rules on what changes are allowed are a bit flexible, but in general work out to be something along the lines of “no new features” (i.e., bug fixes only) and “don’t affect pagination”.  Process wise, I make changes to the source, provide a diff to a layout editor who verifies the layout and makes tweaks as necessary (e.g., adjusting inter-line spacing if necessary to ensure that changes are localized), and the results are sent off to the printer.
Other changes are fodder for a new edition (or possibly even a new title).  Examples of this include the changes required to use this book with Rails 2.3.2.
What would I like to see in a follow-on to this book?

First, basic hygiene.  All the examples should be changed so that they work without any deprecation warnings against the first 3.0 public release of Rails.  Given that Yehuda Katz is now actively monitoring these tests, this should not be an issue.  This brings up a naming issue, as a fourth edition of this book being the one that targets the third release of Rails is a point of confusion.  Those that remember the early days of the NEcho wiki know that I suck at naming, so I’m happy to leave this problem to others.
Second, widen the base.  The first edition of this book had a near cult following from a number of Rails enthusiasts, so the introduction to Ruby tucked into the back was sufficient, and perhaps even overkill.  Based on the errata I have seen, it now is a necessity, and should both be moved into the front of the book and updated to specifically target refugees from other languages. But I mean more than that.  It is clear that a number of readers have never found the command line (translation for Mac users: Terminal.app).  A few pages on that topic, as well as another couple on SQL would go a long way.
Third, pruning.  This book contains in depth coverage of topics aren’t fundamental or are no longer exemplary (e.g. database constraints, data migrations, active record based sessions, non-REST routing, non AR objects in sessions, non AR objects in forms, forms without underlying models, ...).  At a minimum, these topics should be deemphasized by being moved later in the book.  In some cases, they should be moved outside the book entirely (fodder for future “recipe” books perhaps).  Additionally, over time, the state of Rails documentation has improved, so this book can afford to reference the documentation more.
Fourth, refactoring.  This book starts with scaffolding, and then takes a walk through a number of Rails features.  As Rails is getting more modular, a more phased introduction is possible.  one could imagine a book that starts out with a “we don’t need no steenken framework” approach to life, and starts out with a single file (Sinatra style) application, and then one by one adds in a Rails feature, explores what benefits (and tradeoffs) that feature provides.  Initially, the approach could stay entirely with Rails defaults, and then once that is complete, subsystems can be swapped out or augmented.  Concretely, this could mean starting with an XML file on another machine with products that needs to be parsed and stored in a database.  This could start with no Rails (coding direct to SQLite3), substituting in ActiveRecord.  Introducing Rack, then Metal, then ActionController::Http, ... eventually dovetailing with the current Depot application.  When Depot gets to the point where it generates XML, it won’t seem so random.  And when we get to ActiveResource, it will complete the loop as it will essentially be parsing the XML with zero code.
Fifth, radical refactoring.  This is the part that is most speculative, and may not be successful.  I’ve talked about eliminating or moving forward the appendixes.  I’ve talked about pruning the “Rails In Depth” chapters.  If the remainder of these chapters could be made small enough, they could be integrated with the chapters in Depot where these concepts are introduced.  Additionally, the very first Rack based-application could be automated using whenever, tested using Rack-Test, deployed using Capistrano, establishing best practices early on.  I’ll be honest: while this is highly desirable, it is also a considerable challenge.  If the end result is that this overwhelms the coverage of Rails it ends up being a disservice and a distraction.  I definitely don’t want to get to the point where you have to get 2/3rds of the way through the book before you learn about scaffolding.


Hopefully, this work can get underway by the end of the month and be complete as near as possible to the first public release of Rails.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3036</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Programming Talk</title>
      <description><![CDATA[Sabe a diferença semântica entre class &#60;&#60; self e métodos de classe no Ruby? Já programou meta-decorators em Python? Quer implementar OMeta em sua linguagem favorita? Já programou em Nu ou Newspeak? Já está na curva descendente de uso de meta-programação em sua linguagem diária?

Se respondeu sim a alguma dessas questões ou simplesmente gosta de [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847729" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/29/programming-talk/#comments</comments>
      <pubDate>Mon, 29 Jun 2009 22:12:02 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847729&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F29%2Fprogramming-talk%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Sabe a diferença semântica entre <code>class &lt;&lt; self</code> e métodos de classe no Ruby? Já programou <span class="foreign-word" lang="en">meta-decorators</span> em Python? Quer implementar <a href="http://tinlizzie.org/ometa/">OMeta</a> em sua linguagem favorita? Já programou em <a href="http://programming.nu/">Nu</a> ou <a href="http://newspeaklanguage.org/">Newspeak</a>? Já está na curva descendente de uso de meta-programação em sua linguagem diária?</p>

<p>Se respondeu sim a alguma dessas questões ou simplesmente gosta de discutir linguagens de programação de maneira mais profunda, junte-se a nós no grupo <a href="http://groups.google.com/group/programming-talk">programming-talk</a>.</p>

<p>Aceitamos <span class="foreign-word" lang="en">newbies</span> de qualquer natureza&#8211;já que todos somos iniciantes em alguma coisa&#8211;mas não para fazer perguntas idiotas sobre como usar a <span class="foreign-word" lang="en">feature</span> XYZ em seu trabalho diário. Por causa disso, o grupo é <span class="foreign-word" lang="en">invite-only</span>.</p>

<p>Se tem interesse, acesse o grupo e peça um convite. Justifique sua entrada, a propósito (ou a entrada será automaticamente negada). <img src='http://logbr.reflectivesurface.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>]]></content:encoded>
      <category>Desenvolvimento</category>
      <guid>http://logbr.reflectivesurface.com/2009/06/29/programming-talk/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>ECMAScript 5 Test Suites</title>
      <description/>
      <pubDate>Mon, 29 Jun 2009 21:29:17 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124205&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Christian Plesner Hansen: Today we’re releasing the Sputnik JavaScript test suite. Sputnik is a comprehensive set of more than 5000 tests that touch all aspects of the JavaScript language as defined in the ECMA-262 standard.
Allen Wirfs-Brock: Anyone who has the interest and skills for developing individual ECMAScript conformance tests are invited to participate in the project. If you’re interested check out the Codeplex site and get involved.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124205" />
]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3035</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Dois começos</title>
      <description><![CDATA[I

Em retrospecto, eu posso dizer sem qualquer sombra de dúvida que a culpa cai toda sobre os ombros deste que lhes escreve. Vocês sabem muito bem o que costumam dizer os sábios sobre a mal-fadada curiosidade e gatos proverbiais. Mesmo assim, não consigo excluir da minha mente a idéia&#8211;cínica, e alguns diriam até ingrata&#8211;de que [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847730" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/28/dois-comecos/#comments</comments>
      <pubDate>Sun, 28 Jun 2009 13:00:48 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847730&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F28%2Fdois-comecos%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<h3>I</h3>

<p>Em retrospecto, eu posso dizer sem qualquer sombra de dúvida que a culpa cai toda sobre os ombros deste que lhes escreve. Vocês sabem muito bem o que costumam dizer os sábios sobre a mal-fadada curiosidade e gatos proverbiais. Mesmo assim, não consigo excluir da minha mente a idéia&#8211;cínica, e alguns diriam até ingrata&#8211;de que ela sabia exatamente o que estava por acontecer e me deixou no igualmente proverbial escuro. Exceto por minha morte, é claro. Essa&#8211;eu não só tenho certeza como evidências concretas&#8211;foi única e exclusivamente culpa minha.</p>

<p>Mas, eu me adianto. É comum, quando eu escrevo, digo de passagem. Se quero contar a estória direito&#8211;e imagino que sim, já que estou me dando esse trabalho&#8211;preciso retornar há alguns meses atrás quando a confusão começou. E por confusão, estou caracterizando o tipo de caos e tumulto que eventualmente levam ao fim de uma civilização, algo que, no meu caso, é quase que inteiramente a realidade.</p>

<p>Eu estava em Wintrya naquela época, uma cidade suja, mal-cheirosa, habitada por multidões de seres incultos e ignorantes, dominada por uma casta corrupta e extremamente suscetível a suborno e, para completar, tão ao sul do Círculo das Terras quando eu poderia estar. Em suma, o local perfeito para o que eu tinha em mente: recomeçar minha carreira. O único problema então era que eu estava, sem sucesso algum, devo dizer, chegando perto desse objetivo. Na verdade, eu poderia dizer que estava começando a ver algum futuro pela frente mas estaria mentido.</p>

<p>Pensando bem, talvez eu precisa começar um pouco antes ainda. Histórias começam no preciso instante em que os eventos se aceleram rumo ao inevitável, no certo instante em que o protagonista&#8211;e eu hesito em me denominar assim&#8211;comete o erro impensado de acreditar que é mais especial do que o resto do seu mundo.</p>

<p>No meu caso, acordei em uma manhã tipicamente enevoada e comum em minha bela cidade ao norte do Círculo das Terras e decidi, assim mesmo, que estava na hora de mudar de carreira. Quinze anos como assassino profissional era algo do qual eu podia me orgulhar mas chega um ponto em que tudo começa a ficar rotineiro de mais, sem graça, sem interesse. Minha carreira estava estabelecida, sim. Eu tinha respeito, era anônima e possuía dinheiro suficiente para durar um bom tempo. Mas, no final das contas, há um número limitado de estratégias que dão certo e mesmo para o mais profissional dos assassinos chega um momento que o tanto de sangue e tripas já vista supera a vontade representada por cintilantes moedas de ouro. Em suma, a coisa toda perdera o interesse para mim.</p>

<h3>II</h3>

<p>Em retrospecto, eu diria que a culpa foi toda minha. Você sabe o que dizem sobre curiosidade e o gatos. Por outro lado, não consigo me furtar à sensação de que ela sabia o que estava por vir e me deixou no escuro. Exceto pela minha morte, é claro. Essa, eu tenho certeza, foi inteiramente um problema meu.</p>

<p>Mas, eu me adianto. Se eu quero contar a história direito, preciso retornar para alguns meses atrás, quando a confusão&#8211;e por confusão eu quero dizer, aquelas capazes de destruir uma civilização inteira&#8211;começou.</p>

<p>Eu estava em Wintrya naquela época, tão ao sul do Círculo das Terras quanto eu poderia estar, refazendo minha vida. Sem muito sucesso, mas começando a ver algum futuro pela frente. Mas talvez eu precise começar um pouco antes ainda.</p>

<p>Uma manhã eu acordei e decidi que estava na hora de mudar de carreira. Quinze anos como um assassino profissional era algo do qual eu tinha um certo orgulho mas chega um ponto em que os serviços começam a se tornar rotineiros e a coisa toda não tem tanta graça mais. Minha carreira estava bem estabelecida: eu era respeitado, anônimo e com dinheiro suficiente para durar um tempo considerável. Mas, nada era tão interessante mais.</p>]]></content:encoded>
      <category>Experimentos</category>
      <guid>http://logbr.reflectivesurface.com/?p=1287</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Test Notifications</title>
      <description><![CDATA[Yehuda Katz: Last week, Carl and I started digging into the Rails initializer, and the tests in the initializer (railties) are more mock-based and less reliable than the tests in ActionPack (which we’ve been working with so far). They’re pretty reasonable unit tests for individual components, but getting all of the tests to pass did not result in an (even close) bootable Rails app.
To help with spreading the word, I’ve created a registration page where those with an interest in doing so can sign up for IM notification on test results.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124206" />
]]></description>
      <pubDate>Sun, 28 Jun 2009 11:46:10 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124206&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Yehuda Katz: Last week, Carl and I started digging into the Rails initializer, and the tests in the initializer (railties) are more mock-based and less reliable than the tests in ActionPack (which we’ve been working with so far). They’re pretty reasonable unit tests for individual components, but getting all of the tests to pass did not result in an (even close) bootable Rails app.
As work continues on initialization, problems continue to pop up from time to time.  As I write this, there are a number of failures, all of the same basic form: the tests that Rails will generate for a project won’t run.
To help with spreading the word, I’ve created a registration page where those with an interest in doing so can sign up for IM notification on test results.
I’ve worked with OpenID before, but this was the first time I tried the Rails plugin.  It truly does make this much simpler, but one still needs to be aware of the fact that methods that call open_id_authentication will be called twice: once with the original params, and once after all the openid redirects have been processed.  If there is interesting information in the params it needs to be saved someplace, like in the session or a cookie.
I developed the page on my own machine.  One problem that I haven’t fully debugged that I found after I deployed it on DreamHost is that retrieving the value of cookies results in a quoted string, specifically double quotes are added around the value.  Weird.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3034</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Balanço cultural de maio</title>
      <description><![CDATA[Junho quase terminando e só agora deu tempo de fazer o balanço cultural de maio. O mês foi ainda mais corrido do que maio, mas deu tempo de ler um pouco mais às custas de algumas noites mal dormidas. O resultado do mês foi o seguinte:


5 livros
2 filmes


Começando o mês, li Leading Geeks, do Paul [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847731" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/26/balanco-cultural-de-maio-2/#comments</comments>
      <pubDate>Fri, 26 Jun 2009 13:26:45 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847731&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F26%2Fbalanco-cultural-de-maio-2%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Junho quase terminando e só agora deu tempo de fazer o balanço cultural de maio. O mês foi ainda mais corrido do que maio, mas deu tempo de ler um pouco mais às custas de algumas noites mal dormidas. O resultado do mês foi o seguinte:</p>

<ul>
<li>5 livros</li>
<li>2 filmes</li>
</ul>

<p>Começando o mês, li <a href="http://www.amazon.com/Leading-Geeks-Manage-Deliver-Technology/dp/0787961485">Leading Geeks</a>, do Paul Glen. Para quem está começando a carreira gerencial, o livro é absolutamente imprescindível. Paul Glen é um <span class="foreign-word" lang="en">geek</span> escrevendo para <span class="foreign-word" lang="en">geeks</span>. Seu livro não é interessante somente para gerentes mas também para aqueles que tem gerentes na área pelo fato de focar não só nos detalhes do dia-a-dia gerencial mas também em procurar entender como funciona a mente <span class="foreign-word" lang="en">geek</span>. Dividido em dois temas, o contexto da liderança e o conteúdo da liderança, <em>Leading Geeks</em> fornece um bom <span class="foreign-word" lang="en">framework</span> para equipes que precisam trabalhar melhor em áreas de conhecimento e tecnologia.</p>

<p>Os dois próximos livros foram The Knight e The Wizard, os componentes da duologia <a href="http://en.wikipedia.org/wiki/The_Wizard_Knight">The Wizard Knight</a> de Gene Wolfe. Não preciso me estender aqui porque já fiz <a href="http://logbr.reflectivesurface.com/2009/06/01/the-wizard-knight/">uma resenha bem detalhada</a> do livro anteriormente. Basta dizer que recomendo muito, especialmente para quem gosta de literatura fantástica de natureza mais inusitada.</p>

<p>Seguindo o mês, li <a href="http://www.amazon.com/Buried-Pyramid-Jane-Lindskold/dp/0765302608">The Buried Pyramid</a>, por Jane Lindskold. Esse é o primeiro livro da autora que eu leio e confesso que não gostei muito. O livro começa interessante, com uma estória envolvendo um faráo desaparecido nas areias do tempo e um soldado tornado arqueólogo que quer ser o primeiro a descobrir onde jaz o túmulo do mesmo. Em paralelo, um grupo misterioso pretende impedir a descoberta. Poderia ter sido um livro interessante mas descamba para uma enorme seqüência sem sentido no terço final culminando em um final <span class="foreign-word" lang="la">deus ex machina</span> que, embora responda as questões levantadas tira qualquer possibilidade de sentido do livro. Infelizmente, passo os próximos livros da autora a menos que alguém tenha uma recomendação muito boa.</p>

<p>Terminei o mês lendo <a href="http://www.starrigger.net/Downloads.htm#Eternity">Eternity&#8217;s End</a>, por Jeffrey A. Carver. O livro, uma <span class="foreign-word" lang="en">space opera</span>, conta a estória de um <span class="foreign-word" lang="en">rigger</span> chamado Renwald Legroeder que se vê envolvido em uma conspiração para esconder o mistério que cerca uma nave espacial fantasmagórica perdida durante uma viagem espacial. Os <span class="foreign-word" lang="en">riggers</span> são pessoas com a habilidade de conduzir naves espaciais em segurança através de uma dimensão espaço-temporal chamada de <span class="foreign-word" lang="en">Flux</span> que permite viagens em velocidades acima da luz. Legroeder, que foi aprisionado por piratas durante uma viagem, tem que se aliar a uma advogada e uma raça alienígena quando é preso por ter supostamente ajudado a captura de sua nave. Em uma corrida para provar sua inocência e descobrir o mistério do <a href="http://en.wikipedia.org/wiki/The_Flying_Dutchman">Holandês Voador</a> espacial, Legroeder precisa ir além de seus conhecimentos e formação para achar a verdade. O livro é interessante e embora não tenha tanta força literária, consegue sustentar bem a leitura até um final convincente.</p>

<p>Nos filmes, comecei o mês com <a href="http://www.imdb.com/title/tt0758774/">Body of Lies</a>, um <span class="foreign-word" lang="en">thriller</span> de espionagem com Leonardo DiCaprio e Russell Crowe, envolvendo conspirações e a caçada a um terrorista na Síria. Chega a ser interessante em alguns pontos, mas falha pelo final meia-boca.</p>

<p>Logo também no início do mês, fui ver a nova versão de <a href="http://www.imdb.com/title/tt0796366/">Star Trek</a>. Com fã absoluto de todas as manifestações da série, não preciso dizer que o filme marcou o fim de sete anos ansiosa de espera por algum material novo na franquia. Obviamente, como se tratava de um <span class="foreign-word" lang="en">reboot</span> da série, fiquei bem preocupado com a possibilidade de que o resultado final fosse completamente avesso ao que Star Trek representa.</p>

<p>Felizmente, embora o filme tenha suas falhas, para mim representou um boa retorno de <em>Star Trek</em> às telas&#8211;e pelo sucesso, possivelmente à televisão também. O filme já sofreu análises extensivas por partes dos milhões de fãs e não vou me estender nos detalhes do cânon. O filme é de ação, sim, algo que a série precisava, e, sim, peca em não forçar tanto os temas que tornaram a série icônica. Mas é um bom começo para uma exploração futura e revista desses temas. Não acho que essa bola vá cair com a competência que todos produtores sempre tiveram. Não é a <em>Star Trek</em> que nos acostumamos a ver em alguns aspectos e é em outros aspectos igualmente válidos. Vi três vezes o filme e vou comprar quando sair. Mas, fazer o quê, sou fã. <img src='http://logbr.reflectivesurface.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>No próximo mês, mais livros e filmes.</p>]]></content:encoded>
      <category>Filmes e Séries</category>
      <guid>http://logbr.reflectivesurface.com/2009/06/26/balanco-cultural-de-maio-2/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Eu tenho um sonho…</title>
      <description><![CDATA[Hoje foi um daqueles dias ótimos no trabalho. Apesar da chuva, o movimento não diminuiu e consegui vender nada mais, nada menos do que duzentos pratos de milho verde.

Eu gosto de dias de chuva, confesso. Por mais que seja inconveniente para o cliente&#8211;e sempre há a chance que eles desapareçam se as ruas ficarem alagadas [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847732" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/25/eu-tenho-um-sonho/#comments</comments>
      <pubDate>Thu, 25 Jun 2009 20:43:47 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847732&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F25%2Feu-tenho-um-sonho%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Hoje foi um daqueles dias ótimos no trabalho. Apesar da chuva, o movimento não diminuiu e consegui vender nada mais, nada menos do que duzentos pratos de milho verde.</p>

<p>Eu gosto de dias de chuva, confesso. Por mais que seja inconveniente para o cliente&#8211;e sempre há a chance que eles desapareçam se as ruas ficarem alagadas e intransitáveis&#8211;eu sempre tive uma queda para a paisagem cinzenta e opaca dos dias frios e nublados dessa cidade.</p>

<p>E hoje, um dia que combinou chuva e boas vendas, merece uma comemoração extra.</p>

<p>Eu já estou nesse ponto há 20 anos. Não considero minha vida sofrida. Fico vendo aqueles executivos passarem apressados para cima e para baixo, homens e mulheres com aquele porte que indica poder, alheios ao mundo ao seu redor. Volta e meia, um deles sai mais tarde do trabalho, para aqui e comenta um pouco sopre o trabalho no escritório, sobre a pressão dos chefes, sobre as intrigas e políticas. Não quero isso para mim, é o que eu sempre penso.</p>

<p>Fiz faculdade também. Acabei nesse lugar por força do destino mas não acho que tenha sido lesado pelos deuses ou algo assim. Consegui criar e sustentar uma família, meus filhos estão todos crescidos e bem. E eu, bem, eu continuo aqui. Nos momentos de pouco movimento, leio meus livros, me inteiro do mundo, converso com os clientes, fico sabendo de tudo: dores e amores, conquistas e perdas, beleza e feiúra expostas na cidade.</p>

<p>É impressionante como as coisas são. Um dias desses, um violonista famoso decidiu tocar aqui por perto. Um experimento. Seis peças de Bach por quarenta e cinco minutos. Perdi a conta de quantas pessoas passaram sem prestar atenção. Eu, embevecido, via o mundo andar ao redor, alheio ao som majestoso saindo daquelas cordas, e abanava minha cabeça. De que adianta essa vida toda corrida se você não tem tempo para parar por alguns minutos e contemplar o maior de todos os mestres?</p>

<p>Isso me lembra dos dias em que eu tenho alguns pesadelos estranhos. Há dias&#8211;raros, graças a Deus&#8211;em que eu acho que sou um programador em uma dessas firmas grandes, fábricas de <span class="foreign-word" lang="en">software</span> como meu filho costuma dizer quando conta do seu trabalho, e fico o dia todo em uma baia apertada, no meio do barulho, tentando fazer um trabalho que nunca acaba. Acordo suando frio.</p>

<p>Ainda bem que estou aqui, vendo a chuva cair, e me preparando para mais uma boa noite de sono. Amanhã tem mais. Se o sol sair, o dia pode ser melhor ainda para as vendas. Já tenho o livro preparado para os momentos preguiçosos. Só sinto falta mesmo da patroa. O resto está muito bem.</p>

<hr />

<p>Agradecimentos ao <a href="http://eustaquiorangel.com/">TaQ</a> e <a href="http://tecnocracia.com.br/">Manoel Netto</a> pela inspiração.</p>]]></content:encoded>
      <category>Vida</category>
      <guid>http://logbr.reflectivesurface.com/2009/06/25/eu-tenho-um-sonho/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Validator.Nu on GCJ Update</title>
      <description><![CDATA[ruby test/fonts.rb test/google.html
size => -1
size => -1
size => -2
size => -2
I jotted down a few notes.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124207" />
]]></description>
      <pubDate>Tue, 23 Jun 2009 19:48:44 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124207&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[ruby test/fonts.rb test/google.html
size => -1
size => -1
size => -2
size => -2
Notes:

Another gcj bug slowed me down for a bit.
HtmlDocumentBuilder has a private method to lazily initialize a driver, but that method was never called.  I added a call — I hope Henri agrees.
I now pass the raw bytes from Ruby to Java (as a ByteArrayInputStream).  Future iterations can replace this read and memcpy with a BufferedReader so that it won’t be necessary to have two entire copies of the file being parsed in memory.
Java objects are wrapped with Ruby objects, the Ruby objects are linked so that attributes point to elements which point to the owning document.  The Java document object will be released when the Ruby document object no longer has references.
Individual methods are very straightforward to implement: CNI makes native access to Java objects fairly transparent, and Ruby’s native API is also each to pick up and use.  Take a look at jaxp_element_attributes if you would like to see a good example:

Unwrap the Ruby Element to find the Java Element
Create a new Ruby Hash
Get the attributes from the Java Element, and iterate over them:

Retrieve Java Attribute object from the Java NamedNodeMap
Wrap the Java Attribute object in a Ruby Attribute object
Set @element in the Ruby Attribute object to point to the Ruby element
Add the Ruby Attribute object to the hash with the attribute name as the key

Return the Ruby hash

It doesn’t look like FFI will be as easy as CNI is inherently C++.  Of course, JRuby can directly call into Java — but there still will be a need for a more Rubyish API.
JAXP’s implementation of XPath is fully namespace aware making it a bit cumbersome to use.  If CSS selectors are to be implemented by mapping the selectors to XPath expressions, this is something that will need to be accomodated.
Conversion of strings (Java uses UTF-16, Ruby UTF-8) is only done when necessary.
At the moment, I’ve only implemented data access and traversal methods, but there is no reason that these methods can’t construct new Java objects and modify the DOM.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3033</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Revisiting RedHat</title>
      <description><![CDATA[I switched to Debian in 2003 given the uncertainty at the time for RedHat.  Eighteen months later, I switched to Ubuntu as I found the unpredictable release cycle of Debian to be an issue.
I had occasion to try Fedora again yesterday when debugging a GCP/JAXP issue.  I was curious to see what had changed since I had last looked into a RPM based distribution over five years ago, and the answer in retrospect was totally obvious.  The difference between two 2009 vintage Linux distributions is much smaller than the difference between a 2009 vintage distribution and a 2003 vintage distribution, even of those distributions came from the same place.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124208" />
]]></description>
      <pubDate>Mon, 22 Jun 2009 15:49:49 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124208&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[I switched to Debian in 2003 given the uncertainty at the time for RedHat.  Eighteen months later, I switched to Ubuntu as I found the unpredictable release cycle of Debian to be an issue.
Clearly Fedora weathered the storm and has not only survived but thrived.
I had occasion to try Fedora again yesterday when debugging a GCP/JAXP issue.  The problem turned out to be the version of libjaxp1.3-java included in the distribution was incompatible with the version of GCJ included in that same distribution.  That’s the second distribution packaging bug I encountered relating to GCJ on Ubuntu.
Apparently, RedHat based distributions put more attention on Java than Debian based distributions do.
Anyway, I was curious to see what had changed since I had last looked into a RPM based distribution over five years ago, and the answer in retrospect was totally obvious.  The difference between two 2009 vintage Linux distributions is much smaller than the difference between a 2009 vintage distribution and a 2003 vintage distribution, even of those distributions came from the same place.
Oh, there are differences.  On Ubuntu, the Terminal application is an Accessory, on Fedora it is a System Tool.  Yum totally closed the gap with apt-get, but package names are different, for example ruby1.8-dev on Ubuntu maps to ruby-devel on Fedora.  Shutting down wasn’t obvious on Fedora, at least not until I logged off.  Sudo is preconfigured on Ubuntu, not so on Fedora.  Yum default to “No”, aptitude to “Yes” on “Is this OK?” types of questions.
But those differences are cosmetic.  The true differences are in the version of the packages.  Fedora 11 gives you Rails 2.3.2 and Ruby 1.8.6 whereas Ubuntu 9.04 provides Rails 2.1.0 and Ruby 1.8.7.  Ubuntu provides Firefox 3.0, Fedora provides Firefox 3.5beta4.
Given that I’m likely to continue playing with GCJ for a few more weeks at least, I might even consider switching.  The only two showstoppers I’ve seen are both temporary.  VirtualBox doesn’t seem to know how to install Guest additions on Fedora 11, and Firebug won’t install on Firefox 3.5beta4.  I’d also miss the new notification system that debuted in Jaunty.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3032</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>IBM enters cloud computing</title>
      <description/>
      <pubDate>Tue, 16 Jun 2009 14:07:12 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=380579333&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Color me shocked, but IBM has just rolled out
a cloud computing offering. For the short year
that I worked at IBM I argued many times for IBM to enter
SaaS, but to no avail, so it's great to see them finally 
entering the field. Now this is IBM
and those bureaucratic genes run deep, so don't expect to 
just whip out
    a credit card and start playing:




 Fill out a test drive enrollment form
 You will be contacted by an IBM CoD specialist to discuss the offer and agree to terms including a small activation fee of $99 and desired start date
 You will be issued instructions, a VPN ID and password to access an isolated cluster in the IBM CoD center for the agreed upon timeframe
 You can try the service up to 3 days



I can only imagine the process if you want to actually sign up 
and do something. Regardless, I take it as a positive sign 
that IBM has finally arrived.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=380579333" />
]]></content:encoded>
      <guid>http://bitworking.org/news/432/ibm-enters-cloud</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Invoking HtmlParser from C++</title>
      <description><![CDATA[On Friday, I said Next task is to repackage the htmlparser as a library, and to reimplement the HTML2XML tool itself in C++.  This is now done.  In the process, I also converted a SystemErrErrorHandler class into C++ so that I could be sure that I was able to do both Java=>C++ and C++=>Java calls.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124210" />
]]></description>
      <pubDate>Mon, 15 Jun 2009 19:03:47 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124210&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[On Friday, I said Next task is to repackage the htmlparser as a library, and to reimplement the HTML2XML tool itself in C++.  This is now done.  In the process, I also converted a SystemErrErrorHandler class into C++ so that I could be sure that I was able to do both Java=>C++ and C++=>Java calls.
A few things learned along the way:

Installing libjaxp1.3-java-gcj doesn’t give you headers, but you can generate these yourself using gcjh.
At least on Ubuntu, there is a bug that prevents gcjh from working.  The workaround is to add /usr/share/java/libgcj.jar to the classpath.
In gcj, everything inherits directly from java.lang.Object.  This means that you can’t even pass an instance to a subclass to a method that is expecting an instance of a superclass without an explicit cast.
If you wish to implement a class in C++ that can be used from Java, there is a lot of work to be done.  Much of this can be avoided if you define the class in Java, marking the methods you wish to implement in C++ as native, compiling the Java, and generating a header.
Constructors can’t be native methods.  The workaround is to have the constructor call a private method.
If you with to try the executable, remember to set LD_LIBRARY_PATH.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3030</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Rest In Place</title>
      <description><![CDATA[Edit in place is a handy feature where clicking on an area of a web page replaces that portion of the page with a form which will enable the user to update that information.  At one time, this was a part of Rails, but in 2007 it moved out to a plugin, and improved upon.  The one that looked like it most closely matched my needs was REST in Place.  It comes in three flavors, I picked JQuery.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124211" />
]]></description>
      <pubDate>Sun, 14 Jun 2009 10:54:28 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124211&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Edit in place is a handy feature where clicking on an area of a web page replaces that portion of the page with a form which will enable the user to update that information.  At one time, this was a part of Rails, but in 2007 it moved out to a plugin, and improved upon.  The one that looked like it most closely matched my needs was REST in Place.  It comes in three flavors, I picked JQuery.
URLencoding
The first issue I had was that I would not be able to authenticate, despite carefully following the instructions for setting a rails_authenticity_token.  Looking at it from the server logs, it appeared that the token received had a space in it.  Looking at it from the client, I found a plus in the same place.  Looks like request wasn’t properly x-www-form-urlencoded. Looking at the source (line 18) verifies this to be the case.  A call to encodeURIComponent would solve this.  So would a call to CGI.escape in the assignment to rails_authenticity_token.  The former seems like the “right” way, but instead of modifying the gem, I decided to take the latter approach for now.
It is not clear to me why this problem wouldn’t affect others enough to have been noticed and fixed.
JSON
Once this was fixed, I could edit information in place.  The trouble is that the formatting was lost after the edit.  The information I was editing at the time was a dollar amount, something that I format with number_to_currency.  It seems that under the covers, after an update is made, the information is re-fetched using JSON and that’s the information that is displayed.  That information is “raw” and essentially straight from the database.  My first attempt to address this was to create new attributes which were not backed by the database; but by default such attributes are not included in the JSON so instead of simply losing the formatting, now I lost the result entirely.  This could be addressed, but I decided to go back to the original attributes, and centralize the formatting.
class ActiveRecord::Base
  def self.dollarize *attrs
    attrs.each do |name|
      define_method name do
        clone = SimpleDelegator.new(self[name])
        clone.extend(ApplicationHelper)
        def clone.to_s
          number_to_currency self, :unit=>''
        end
        def clone.to_json(opts)
          to_s.inspect
        end
        clone
      end

      define_method "#{name}=" do |value|
        self[name.to_sym]=value.gsub(/[^0-9.]/, '').to_f
      end
    end
  end
end
This allows fields to be declared as dollarized, after which point all formatting is taken care of automatically, and all other basic numeric functionality is delegated back to the original Float.
Kinda odd to have ApplicationHelper included within a model, but the amount of lines of code went down, processing became more consistent, so this was totally a net plus.
Caching
Now that the basic functionality worked, I noticed something odd.  If after doing an in-page-edit I clicked on a link and subsequently clicked on the back button, I was presented with JSON instead of the HTML page I was expecting.
I’m not totally sure what is going on here, as the server was properly sending private, max-age=0, must-revalidate as the cache control header.  The only thing I can figure is some oddity with Firefox 3.0.11 with XMLHttpRequeset and https sessions.  I’m not a big fan of conneg for this reason.  When it works, it is very useful.  When it doesn’t, it is often difficult to diagnose and debug.
But I have a known workaround.  By appending a question mark to the URI used for XHR, the client sees it as a different resource and the server processes it the same.
Helper
Wanting to apply the same workaround consistently across my application was the tipping point.  The markup rest_in_place wasn’t all that complicated, but was repetitive.  Time for a helper function:
# Usage:
#   <% rest_in_place(obj) do |rip| -%>
#     ... markup ...
#     <%= rip.editable :field %>
#     ... markup ...
#   <% end -%>

def rest_in_place(obj)
  yield RIP_Builder.new(url_for(obj), obj)
end

class RIP_Builder
  def initialize(url, obj)
    @url = url + "?"
    @obj = obj
    @name = ActionController::RecordIdentifier.singular_class_name(obj)
  end

  def editable(field)
    "<span class='rest_in_place' object='#{@name}' attribute='#{field}' url='#{@url}'>#{@obj.send field}</span>" 
  end
end

Attributes
One final note, only of interest to pedants.  The markup above is not conformant in that it invents new attributes.  In order to satisfy the markup orthodoxy, I’d suggest modifying RIP to accept synonyms for each attribute that happen to start with data-.  I would certainly use it on all public facing websites that made use of this feature.  As to what I use on my own private network, that’s between me and my server.]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3029</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
    <item>
      <title>Postando no WordPress via E71</title>
      <description><![CDATA[Uma das coisas complicadas em dispositivos móveis é escrever em um blog usando os mesmos. Sempre procurei e nunca fiquei satisfeito até encontrar uma combinação quase que imbatível no E71 mais WordMobi, uma aplicação para o WordPress na plataforma S60.

Usando a característica de texto preditivo do E71 e a facilidade de edição que o WordMobi [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847733" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/13/postando-no-wordpress-via-e71/#comments</comments>
      <pubDate>Sat, 13 Jun 2009 18:50:24 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847733&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F13%2Fpostando-no-wordpress-via-e71%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Uma das coisas complicadas em dispositivos móveis é escrever em um blog usando os mesmos. Sempre procurei e nunca fiquei satisfeito até encontrar uma combinação quase que imbatível no E71 mais <a href="http://wordmobi.googlecode.com">WordMobi</a>, uma aplicação para o WordPress na plataforma S60.</p>

<p>Usando a característica de texto preditivo do E71 e a facilidade de edição que o WordMobi oferece, é possível compor textos quase com a mesma flexibilidade de escrever em um computador. É possível até mesmo subir imagens e vídeos.</p>

<p>Obviamente, nem tudo é perfeito já que falta ao E71 um navegador que permita copiar e colar links e textos de uma maneira mais geral&#8211;um fator extremamente limitante na plataforma já há um bom tempo. Mas, para as necessidades casuais, já resolve bastante.</p>

<p>Um detalhe tecnológico legal é que o WordMobi é escrito em Python para o S60. Dá seus problemas de quando em quando mas mostra que já é possível fazer muita coisa com o Python em celulares.</p>]]></content:encoded>
      <category>Tecnologia</category>
      <guid>http://logbr.reflectivesurface.com/?p=1279</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Reduzindo nomes no Git e SSH</title>
      <description><![CDATA[Para quem está cansado de digitar longos nomes de repositórios no Git, o Git possui uma modo de criar alias para URLs de maneira bem simples.

Vamos usar o GitHub como exemplo, embora a técnica seja, obviamente, válida para qualquer tipo de repositório e protocolo:

O comando, que deve ser aplicado globalmente, isto é, à sua configuração [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847734" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/04/reduzindo-nomes-no-git-e-ssh/#comments</comments>
      <pubDate>Thu, 04 Jun 2009 17:42:55 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847734&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F04%2Freduzindo-nomes-no-git-e-ssh%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Para quem está cansado de digitar longos nomes de repositórios no Git, o Git possui uma modo de criar <span class="foreign-word" lang="en">alias</span> para URLs de maneira bem simples.</p>

<p>Vamos usar o GitHub como exemplo, embora a técnica seja, obviamente, válida para qualquer tipo de repositório e protocolo:</p>

<p>O comando, que deve ser aplicado globalmente, isto é, à sua configuração geral do Git, tem a seguinte forma (substitua, no comando abaixo, <var>rferraz</var> pelo seu nome do usuário do GitHub):</p>

<pre>git config --global url."git@github.com:rferraz/".insteadOf "github:"</pre>

<p>Com o comando acima, é possível usar o seguinte comando ao clonar um repositório:</p>

<pre>git clone github:eleusis-server.git</pre>

<p>O comando será automaticamente expandido para:</p>

<pre>git clone git@github.com:rferraz/eleusis-server.git</pre>

<p>Para reduzir ainda mais, no caso de repositório cujo protocolo é SSH, pode-se editar o arquivo ~/.ssh/config para adicionar um <span class="foreign-word" lang="en">alias</span> para o próprio servidor em questão. No caso do Git Hub, o trecho de arquivo seria:</p>

<pre>Host github
        Hostname github.com
        User git</pre>

<p>Com essa configuração, o comando original de <span class="foreign-word" lang="en">alias</span> poderia ser reduzido para:</p>

<pre>git config --global url."github:rferraz/".insteadOf "github:"</pre>

<p>E o resultado é o mesmo.</p>

<p>Fica a dica para quem sempre está brincando com vários repositórios, especialmente quando os nomes são longos.</p>]]></content:encoded>
      <category>Desenvolvimento</category>
      <guid>http://logbr.reflectivesurface.com/2009/06/04/reduzindo-nomes-no-git-e-ssh/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Joie de Vivre</title>
      <description><![CDATA[Alguns anos atrás, trabalhei por alguns meses em uma empresa pequena&#8211;quatro funcionários na época&#8211;fazendo aplicações corporativas em PHP. Eu estava cansado de programar em ASP e queria espairecer um pouco em outras arenas.   Infelizmente, a alegria durou pouco. Por várias razões&#8211;falta de planejamento, dificuldade em conseguir recursos, falta de pessoal qualificado, etc&#8211;a empresa [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847735" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/04/joie-de-vivre/#comments</comments>
      <pubDate>Thu, 04 Jun 2009 13:20:18 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847735&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F04%2Fjoie-de-vivre%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Alguns anos atrás, trabalhei por alguns meses em uma empresa pequena&#8211;quatro funcionários na época&#8211;fazendo aplicações corporativas em PHP. Eu estava cansado de programar em ASP e queria espairecer um pouco em outras arenas. <br /> <br /> Infelizmente, a alegria durou pouco. Por várias razões&#8211;falta de planejamento, dificuldade em conseguir recursos, falta de pessoal qualificado, etc&#8211;a empresa não vingou. Na época, meio do primeiro governo Lula, isso não era tão fora do comum mas faltou também uma pitada de sensatez de todo mundo para lidar com a situação. O meu tempo lá não foi de todo perdido. Rendeu boas estórias e duas amizades queridas que ainda preservo mesmo com a distância. <br /> <br /> Por outro lado, foi a única vez em que pedi demissão em ira. Ira por planos que não chegavam a lugar nenhum. Ira por promessas não cumpridas. Ira por várias outras razões que na época pareciam bem válidas. Parti para outra, mas carregando aquele peso comigo de assunto não resolvido. <br /> <br /> Demorou muito tempo para perceber que, na verdade, a minha ira não derivava dos problemas que eu percebia na empresa. Ao contrário, vinha de um sentimento de que faltava <span class="foreign-word" lang="fr">  joie de vivre </span> no ambiente de trabalho. <br /> <br /> E <span class="foreign-word" lang="fr">  joie de vivre </span> &#8211;em uma tradução direta e meia-boca, <em>alegria de viver</em>&#8211;era algo que eu sentia mais falta no intercâmbio com meus pares de desenvolvimento do que em relação à própria empresa. Como em outras empresas que trabalhei desde então, a sensação de que os desenvolvedores ao meu lado não experimentavam isso era a parte mais terrível de qualquer situação. Eu, que sempre tive um pé no mundo livre, em projetos paralelos, conseguia derivar isso mesmo na ausência de outros fatores. <br /> <br /> Não é de se estranhar, por exemplo, que o grande <span class="foreign-word" lang="en">  selling point </span> do Rails tenha sido o fato de que ele devolvia ao programador a alegria de desenvolver. O Rails não se tornou um dos <span class="foreign-word" lang="en">  frameworks </span> mais bem-sucedidos de todos os tempos por causa de suas proezas técnicas. Ruby mais Rails se tornaram um combinação imbatível em trazer <span class="foreign-word" lang="fr">  joie de vivre </span> aos desenvolvedores. <br /> <br /> Não há nada que compre <span class="foreign-word" lang="fr">  joie de vivre </span> . É algo que só você pode conseguir e somente em certas circunstâncias. Não dá para construir nem criar, exceto por prover [condições apropriadas para que ele aconteça][1]. E como eu queria que outros pudessem experimentar isso também. Pena que quase nunca seja o caso nos ambientes que temos. <br /> <br /> [1]: http://logbr.reflectivesurface.com/2009/04/22/a-pobreza-das-conexoes/</p>]]></content:encoded>
      <category>Coisas de Geek</category>
      <guid>http://logbr.reflectivesurface.com/2009/06/04/joie-de-vivre/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Balanço cultural de abril</title>
      <description><![CDATA[Abril foi um mês de mudanças e correrias e, de acordo com meus registros dos últimos três anos, o mês em que menos consegui ler. Em compensação, vi mais filmes do que o normal. O resultado pífio ficou no seguinte:


1 livro
16 filmes


O único livro que li no mês foi Flashforward, do sempre interessante Robert J. [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847736" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/02/balanco-cultural-de-abril-3/#comments</comments>
      <pubDate>Tue, 02 Jun 2009 17:09:40 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847736&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F02%2Fbalanco-cultural-de-abril-3%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Abril foi um mês de mudanças e correrias e, de acordo com meus registros dos últimos três anos, o mês em que menos consegui ler. Em compensação, vi mais filmes do que o normal. O resultado pífio ficou no seguinte:</p>

<ul>
<li>1 livro</li>
<li>16 filmes</li>
</ul>

<p>O único livro que li no mês foi <a href="http://en.wikipedia.org/wiki/Flashforward_(novel)">Flashforward</a>, do sempre interessante Robert J. Saywer. O livro é de 1999 e conta sobre eventos passados em 2009, o que, ironicamente, o torna ao mesmo tempo datado e atual. Datado porque alguns eventos, é claro, não se passaram como o livro mostra. E atual por causa da coincidência de alguns temas que estavam na mídia justamente no tempo que Saywer os descreve nos livros.</p>

<p>O livro conta a estória de um evento acontecido em 2009 quando o <a href="http://en.wikipedia.org/wiki/Large_Hadron_Collider">LHC</a> é ligado em uma tentativa de provar a existência do bóson de Higgs. Ao invés da prova, a tentativa faz com que todos habitantes do planeta experimente durante dois minutos e alguns segundos as suas vidas de cerca de vinte um anos no futuro. O resultado&#8211;além da imediata perda de vidas e semi-colapso econômico&#8211;é um mundo inteiramente mudado pelas visões que alguns acreditam imutáveis e outros não. Sawyer lida com maestria com essas questões, inclusive tecendo um pequeno mistério detetivesco de um homem que descobre ter sido assassinado no futuro e que quer prevenir o acontecimento. Muito bom e leitura recomendada. O livro está agora sendo desenvolvimento em <a href="http://en.wikipedia.org/wiki/Flash_Forward_(2009_TV_series)">uma série para a TV pela ABC</a>.</p>

<p>Nos filmes, o mês foi bem interessante.</p>

<p>Comecei vendo <a href="http://us.imdb.com/title/tt0409459/">Watchmen</a>. Ainda não li a série em quadrinhos que deu origem ao filme, mas gostei muito da representação visual criada para o mesmo em relação ao que já folheei. <em>Watchmen</em> é uma versão gráfica de temas que são constantes na literatura de ficção científica, e tem o mérito de trazer isso para as massas. Se conseguiu ou não, é uma discussão para outra hora.</p>

<p>Segui o mês vendo <a href="http://us.imdb.com/title/tt0110912/">Pulp Fiction</a>, que era um que me faltava dos clássicos do gênero. Como eu provavelmente sou a última pessoa no planeta a ver o filme, não preciso também comentar muito sobre o mesmo. Basta dizer que achei bem melhor que a obra posterior de Tarantino. Em <em>Pulp Fiction</em>, o exagero a que ele recorre normalmente parece bem mais refinado e elaborado do que em seus outros filmes. O que é uma pena.</p>

<p>Na seqüência, vi o esquecível <a href="http://us.imdb.com/title/tt0467197/">Max Payne</a>. Péssima direção, péssima atuação e só terminei de ver porque sou teimoso. Pareceu uma tentativa bem descarada de copiar o clima e surrealidade de <em>Constantine</em> perdendo todo o <span class="foreign-word" lang="en">background</span> desde último no processo.</p>

<p>Continuando, foi a vez de <a href="http://us.imdb.com/title/tt0497465/">Vicky Cristina Barcelona</a>. Minha experiência com Woody Allen é sempre meio confusa. Alguns de seus filmes me impressionaram muito pela sensibilidade e profundidade enquanto outros me deixaram com a sensação de que ele estava simplesmente vomitando idéias sem conseguir uma boa união entre as mesmas. <em>Vicky Cristina Barcelona</em> está no meio do caminho com isso. Tem uma riqueza de situações, uma atuação conjunta muito boa dos atores principais e uma veia mórbida que me atraiu. O final é desencontrado mas acaba não falhando. No geral, foi melhor do que minha experiência usual com os filmes do diretor.</p>

<p><a href="http://us.imdb.com/title/tt1013753/">Milk</a>, o filme seguinte, me impressionou muito. Eu sempre gostei da atuação de Sean Penn e acho que ele mereceu o Oscar que ganhou nesse filme. O assunto continua sendo delicado mesmo na época atual e a direção conseguiu passar a ambigüidade na história de Harvey Milk com tranqüilidade. Tendo saído de duas visitas recentes a São Francisco, ver a cidade e seu desenvolvimento no filme foi um bom complemento para os passeios que fiz.</p>

<p>Os dois filmes seguintes, <a href="http://us.imdb.com/title/tt1068680/">Yes Man</a> e <a href="http://us.imdb.com/title/tt0960731/">Bedtime Stories</a> foram suficientemente divertidos para merecer uma menção aqui mas pouco mais do que isso. Jim Carrey já cansou com suas carretas e o filme só se salva por conta da adorável Zooey Deschanel e Adam Sandler entrou em uma fase exagerada que não adiciona nada a seus filmes.</p>

<p><a href="http://us.imdb.com/title/tt1010048/">Slumdog Millionaire</a> é interessante e bem trabalhado mas sem surpresas. Eu gosto do trabalho de Danny Boyle e esse filme tem o seu toque específico mas muitas das seqüências parecem ser feitas para criar pena no espectador sem acrescentar muito à estória. Funciona em um certo nível mas deixa uma sensação um pouco desagradável ao fim do filme</p>

<p><a href="http://us.imdb.com/title/tt0397892/">Bolt</a>, o filme que vi em seguida, é mais uma divertida e bem-feita animação com bons personagens e uma estória engraçada e bem trabalhada. Gostei especialmente da gata Mittens, mas Travolta se sai muito bem também dando voz ao personagem título. Não chega é claro, aos pés de um <em>The Incredibles</em>, mas vale o tempo gasto.</p>

<p><a href="http://us.imdb.com/title/tt1129442/">Transporter 3</a>, infelizmente, não se salva nem com a sempre divertida atuação de Jason Statham. O filme repete a fórmula dos anteriores, mas exagera justamente no que não deveria e no que deixou o primeiro filme tão interessante (para valores de interessante centrados em diversão inútil mas inteira e completamente aceitável para mim) e transforma o filme inteiro em uma sucessão de buracos de roteiro que não podem ser corrigidos nem por boas cenas de ação.</p>

<p>Na seqüência, <a href="http://us.imdb.com/title/tt0970411/">City of Ember</a> é um pequeno conto de ficção científica sobre uma cidade salva de destruição do mundo cuja intenção era durar apenas duzentos anos mas, quando o conhecimento sobre suas origens e futuro é perdido, se vê as beiras de destruição. Quando os adultos da cidade falham em enxergar o perigo e, ao contrário, se refugiam no passado, um par de adolescentes toma a questão em suas mãos. O filme tem uma fotografia bem agradável e adequado e consegue contar uma boa estória. Vale como um filme sem grandes exageros e que por isso mesmo conta uma boa estória.</p>

<p>Continuando, <a href="http://us.imdb.com/title/tt0870111/">Frost/Nixon</a> é intenso, muito bem elaborado e conta a impressionante história das entrevistas que Frost fez com Nixon. O misto de tentativa de redenção e admissão de erros torna o enredo bem interessante e as atuação são muito boas. Vale cada minuto.</p>

<p><a href="http://us.imdb.com/title/tt0887883/">Burn After Reading</a> é uma comédia surreal e engraçada que deu uma par de horas de diversão. <a href="http://us.imdb.com/title/tt0443274/">Vantage Point</a>, <a href="http://us.imdb.com/title/tt0443701/">X-Files 2</a> e <a href="http://us.imdb.com/title/tt0814022/">Bangkok Dangerous</a> não merecem mais do que uma breve menção. Dá para assistir mas eu teria lido outro livro com o tempo perdido com eles.</p>

<p>Maio vem em breve com mais livros e menos filmes.</p>]]></content:encoded>
      <category>Filmes e Séries</category>
      <guid>http://logbr.reflectivesurface.com/2009/06/02/balanco-cultura-de-abril/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>The Wizard Knight</title>
      <description><![CDATA[Como um leitor antigo de fantasia, o nome de Gene Wolfe sempre figurou na lista dos autores que eu queria ler quando mais jovem. Wolfe, hoje com setenta e oito anos, é considerado um dos melhores autores de fantasia de todos os tempos&#8211;inclusive por outros autores do gênero&#8211;e existe uma certa ironia do fato de [...]<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388847737" />
]]></description>
      <comments>http://logbr.reflectivesurface.com/2009/06/01/the-wizard-knight/#comments</comments>
      <pubDate>Tue, 02 Jun 2009 02:12:13 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388847737&amp;url=http%3A%2F%2Flogbr.reflectivesurface.com%2F2009%2F06%2F01%2Fthe-wizard-knight%2F</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[<p>Como um leitor antigo de fantasia, o nome de <a href="http://en.wikipedia.org/wiki/Gene_Wolfe">Gene Wolfe</a> sempre figurou na lista dos autores que eu queria ler quando mais jovem. Wolfe, hoje com setenta e oito anos, é considerado um dos melhores autores de fantasia de todos os tempos&#8211;inclusive por outros autores do gênero&#8211;e existe uma certa ironia do fato de que, até esse ano, eu ainda não conseguira ler nenhuma de suas obras. Eu me lembro de ter visto várias vezes um ou outro livro de suas multi-voluminosas e épicas obras na biblioteca pública que eu costumava usar mas, por uma razão ou outra, suas obras foram ficando para leituras mais tardias.</p>

<p><span class="foreign-word" lang="en">Fast-forward</span> para duas décadas no futuro e, navegando pela Internet, encontro menções a uma obra mais recente de Wolfe, a duologia chamada <a href="http://en.wikipedia.org/wiki/The_Wizard_Knight">The Wizard Knight</a>. O que mais me chamou a atenção nos livros, além do fato de que eram mais rápidos e que eu poderia usá-los para começar a conhecer um pouco de Wolfe, foi a recomendação de Neil Gaiman na capa, que considerava a série &#8220;importante e maravilhosa&#8221;. Novamente, por ironias do momento, acabei não levando nenhum dos livros. Volta e meia eu via um dos volumes em uma livraria, mas deixava passar. Até, que em uma viagem recente aos EUA, passeando pela Borders, topei com os dois livros de uma só vez e comprei.</p>

<p>Dizer que o estilo de Wolfe é estranho é uma declaração que não expressa o quão diferente é o modo como ele escreve. Obviamente, sendo esses os primeiros livros de Wolfe que eu leio, não sei a que ponto o estilo se estende aos outros livros, mas, pelas resenhas que li, é algo mais ou menos constante em sua obra.</p>

<p>Em <em>The Wizard Knight</em>, Wolfe conta a estória de Able of High Heart, originalmente um adolescente americano que, ao escolher um caminho errado por uma floresta, é transportado a um reino mágico e transformado quase que instantaneamente em um homem adulto de proporções épicas. Able&#8211;que é o nome dado a ele por aqueles que o transformaram&#8211;torna-se um Cavaleiro e recebe a missão de trazer balanço ao mundo em que ele se vê lançado. Esse mundo, composto de sete camadas, cada uma deles visível da inferior como se fosse o seu próprio firmamento e tendo os habitantes da camada superior como deuses, é uma versão convoluta e espetacular de <a href="http://en.wikipedia.org/wiki/Faerie">Faerie</a> recriada por Wolfe para servir seus propósitos. Dragões, aelfs, reis, rainhas, cavaleiros, deuses e deusas, feiticeiros e magos, ogros e gigantes aparecem em igual medida na estória. No meio disso, se encontra também a estória de amor de Able por Disiri, uma rainha Aelf que ajudou em sua transformação por motivos que são vagamente vistos ao longo dos livros.</p>

<p>Contada largamente em primeira pessoa por Able, na forma de cartas, a narrativa é completamente duvidosa e inconstante. Able, que embora tornado adulto, é no fundo um adolescente, conta sua estória da maneira como ela lhe vêm na cabeça, misturando locais, tempos e fatos. Embora a narrativa seja na maioria do seu ponto de vista, algumas vezes Able narra fatos a que não teve acesso a não ser por terceiros e as pessoas e visões da estória se tornam ainda mais estranhas. Em alguns pontos, a própria construção das frases apresenta falhas como se Able estivesse tentando encontrar as palavras apropriadas e se distraísse, criando um efeito vívido e impressionante de estranheza. Mais curiosas ainda são as menções que ele faz de eventos que aconteceram ou vão acontecer, para simplesmente abadoná-los na narrativa&#8211;algumas vezes não sendo mais mencionados ou resolvidos em qualquer ponto do livro.</p>

<p>Essa forma de narrativa não tira, de forma alguma, o brilho de estilo de Wolfe. Pelo contrário, por ser tão diferente da norma, dá ao leitor uma sensação de frescor e vivacidade pouco encontradas em outras obras do gênero. Able, embora um narrador pouco confiável, traduz ao mesmo tempo a segurança de um cavaleiro experimentado e a incerteza adolescente de alguém que sabe que foi tirado de seu mundo e é um joguete de forcas maiores que sua própria compreensão. O resultado dessa mistura improvável é uma estória nostálgica e belíssima.</p>

<p>Agora que conheço Wolfe de fato, seus livros estão seguramente na minha fila de aquisições futuras. Recomendo para qualquer amante de fantasia pouco usual e que se desvia dos clichès gastos e sem brilho da maioria de fantasia atuais.</p>]]></content:encoded>
      <category>Livros e Literatura</category>
      <guid>http://logbr.reflectivesurface.com/2009/06/01/the-wizard-knight/</guid>
      <source url="http://logbr.reflectivesurface.com/feed/">Superfície Reflexiva</source>
      <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/"><![CDATA[Ronaldo]]></dc:creator>
    </item>
    <item>
      <title>Wave Protocol Thoughts</title>
      <description/>
      <pubDate>Mon, 01 Jun 2009 13:33:09 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=380579334&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[An upfront disclaimer, I work for Google. I am not involved in Wave in any way
        and all of the things I discuss below are based on external documentation. 
        

        Before getting into the specifics of the issues I found, I want to point out
        that I'm very excited by Wave, I believe it has tremendous potential. The 
        team has also done a good job re-using existing technologies, and providing 
        different protocols and APIs for the various ways you can interact with a 
        wave server. 
        

        There are actually 3 protocols and 2 APIs that are used in Wave:
        

Federation (XMPP)
            The robot protocol (JSONRPC)
            The gadget API (OpenSocial)
            The wave embed API (Javascript)
            The client-server protocol (As defined by GWT)
        

        The last one in that list is really nothing that needs to be, or will probably ever
        be documented, it is generated by GWT and when you build your own Wave client
        you will need to define how it talks to your Wave server. The rest of the 
        protocols and APIs are based on existing technologies.
        
 The robot protocol looks very easy to use, 
            here is the code for an admittedly simple robot.  Now some
        people have commented that Wave reminds them of Lotus Notes, and I'm
        sure with a little thought you could extend that to Exchange and
        Groove. The difference is that the extension model with Wave is events
        over HTTP, which makes it language agnostic, a feature you get when you
        define things in terms of protocols. That is, as long as you can stand
        up an HTTP server and parse JSON, you can create robots for Wave, which
        is a huge leap forward compared to the extension models for Notes,
        Exchange and Groove, which are all "object" based extension models.
        In the "object" based extension model the application exposes "objects"
        that are bound to locally that you manipulate to control the application,
        which means that your language choices are limited to those that have
        bindings into that object model.
        
All of this is very new, Wave is just starting a developer preview, and 
        the documentation of the protocols and APIs is thin or non-existent in
        areas. In my observations below I've concentrated on the areas that do
        have documentation.
        
Well known location

        The robot protocol uses a "well known location" for the Robot Capabilities files.
        I've just about given up on 
        arguing against 
        protocols that introduce new "well-known locations" in
        URI space. The problem is that all the other alternatives
        are problematic either on the server or the client side.
        If you are going to introduce a new location, at least
        follow the lead of the WebFinger Protocol 
        and put it below the /,wellknown/ path.
        
Hypertext
If you are going to introduce a "well-known location" then
        make good use of it and boot-strap the rest of the URIs
        for the protocol from there. In the case of Wave, put the URI of 
        the robot jsonrpc URI in the capabilities.xml, don't make it
        its own "well-known location". Ditto for the profiles URI.
        
XML and JSON
There's a mix of formats here, XML for the configuration and 
        profiles, but the actual protocol is JSON. Why not simplify and make
        it JSON all the way down?
        
NG and Schema
In the same vein, the federation protocol schema is 
        specified in RelaxNG while the extension manifest is defined via XML Schema.
        
The above points are relatively minor and I'm sure I'll have more
        feedback as more documentation rolls out, but I'm very excited by
        the technology and the direction the team is taking with Wave.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=380579334" />
]]></content:encoded>
      <guid>http://bitworking.org/news/431/wave-first-thoughts</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Instalando o Ruby 1.9 no Ubuntu</title>
      <description><![CDATA[<p>
Ok, a gente já sabe que o <a href="http://www.ubuntu.com">Ubuntu</a> já tem pacotes para <a href="http://www.ruby-lang.org">Ruby</a> 1.9, mas já viu, às vezes a gente precisa da última versão da linguagem e ela não está ainda disponível no repositório blá blá blá whatever, e queremos instalar a danada a partir dos fontes.
</p>

<p>
Em <a href="http://eustaquiorangel.com/posts/500">um post anterior</a> eu havia detalhado como instalar a linguagem, levando em conta uma instalação no <a href="http://www.slackware.com">Slackware</a>, onde era gerado um pacote para a distro. Aqui é praticamente a mesma coisa, mas ao invés de gerar um pacote, vou instalar em um diretório específico, que pode ser removido facilmente depois. É praticamente um merge <a href="http://pragdave.blogs.pragprog.com/pragdave/2007/12/ruby-19right-fo.html">do post do Dave Thomas</a> com o meu anterior e vai me servir como "cola" para instalações novas.
</p>

<ol>
<li>Antes de mais nada, <a href="http://www.ruby-lang.org/en/downloads/">download da última versão da série 1.9</a>.</li>

<li>Descompactar o arquivo e ir para o diretório que foi criado.</li>

<li>Rodar o <tt>configure</tt> dessa maneira (trocando <tt>/home/taq/apps/ruby/</tt> para o diretório onde você quer instalar):<br/>
<tt>./configure --prefix=/home/taq/apps/ruby/ --program-suffix=1.9 </tt>.<br/>
Isso vai instalar essa versão no diretório especificado e colocar um <tt>1.9</tt> no final de cada executável.</li>

<li>Como de costume, agora é <tt>make</tt> e <tt>make install</tt>.</li>

<li>No final a versão está disponível no diretório especificado e agora é só incluir o <i>path</i> do diretório <tt>bin</tt> na sua variável de ambiente <tt>PATH</tt> (provavelmente você vai querer fazer isso dentro do seu <tt>.bashrc</tt>):<br/>
<tt>export PATH=$PATH:/home/taq/apps/ruby/bin</tt></li>
<li>Pronto, temos <tt>ruby1.9</tt>, <tt>irb1.9</tt>, etc e tal.</li>
</ol>

<p>
Talvez alguma coisa precise de mais algum ajuste, mas isso deve prover uma instalação funcional da série 1.9 para darmos uma boa fuçada.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388994439" />
]]></description>
      <pubDate>Mon, 18 May 2009 15:12:21 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388994439&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F562</link>
      <guid>http://eustaquiorangel.com/posts/562</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Convertendo coordenadas para decimais</title>
      <description><![CDATA[<style type="text/css">
<!--
.Regexp { color: #44b4cc; }
.Constant { color: #339999; }
.String { color: #66ff00; }
.Statement { color: #ff6600; }
.Identifier { color: #ffcc00; }
pre { font-family: monospace; color: #eeeeee; background-color: #000000; }
.lnr { color: #ddeeff; background-color: #222222; }
-->
</style>

<p>
Estava fazendo uma aplicação aqui que usa os <a href="http://maps.google.com">mapas do Google</a> para indicar onde alguns veículos a venda estão estacionados, e o cliente informou as coordenadas utilizando graus, minutos e segundos da seguinte maneira: <tt>-20° 47' 26.37", -49° 21' 11.94"</tt>
</p>

<p>
O problema é a classe <a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/reference.html#GLatLng">GLatLng</a> espera valores decimais e não coordenadas, e eu procurei por toda a <a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/reference.html">API do Google Maps</a>, não encontrei nada para converter entre coordenadas e decimais e tive que botar a mão na massa, ou melhor, no código, que está apresentado abaixo.
</p>

<p>
Antes de mais nada temos que retirar as indicações de graus, minutos e segundos e transformar os valores das coordenadas em decimais simples do tipo <tt>-20.472637, -49.211194</tt>, e aí sim enviar para a função abaixo, onde eles se convertem em <tt>-20.790658, -49.353317</tt>, valores que podem ser enviados para a <a href="http://code.google.com/intl/pt-BR/apis/maps/documentation/reference.html#GLatLng">GLatLng</a>.
</p>

<pre>
<span class="lnr"> 1 </span><span class="Identifier">function</span> coordToDec(coord)<span class="Identifier">{</span>
<span class="lnr"> 2 </span>   <span class="Identifier">var</span> match, sig, deg, min, sec, dec;
<span class="lnr"> 3 </span>   match = <span class="Regexp">/(-)?(\d+\.)(\d{2})(\d{2})(\d{2})/</span>.exec(parseFloat(coord).toFixed(<span class="Constant">6</span>));
<span class="lnr"> 4 </span>   sig   = match<span class="Identifier">[</span><span class="Constant">1</span><span class="Identifier">]</span> ? <span class="Constant">-1</span> : <span class="Constant">1</span>;
<span class="lnr"> 5 </span>   deg   = Math.abs(parseFloat(match<span class="Identifier">[</span><span class="Constant">2</span><span class="Identifier">]</span>));
<span class="lnr"> 6 </span>   min   = parseFloat(match<span class="Identifier">[</span><span class="Constant">3</span><span class="Identifier">]</span>);
<span class="lnr"> 7 </span>   sec   = parseFloat(match<span class="Identifier">[</span><span class="Constant">4</span><span class="Identifier">]</span>+<span class="String">&quot;.&quot;</span>+match<span class="Identifier">[</span><span class="Constant">5</span><span class="Identifier">]</span>);
<span class="lnr"> 8 </span>   dec   = (min+sec/<span class="Constant">60</span>.<span class="Constant">0</span>)/<span class="Constant">60</span>.<span class="Constant">0</span>;
<span class="lnr"> 9 </span>   <span class="Statement">return</span> ((deg+dec)*sig).toFixed(<span class="Constant">6</span>);
<span class="lnr">10 </span><span class="Identifier">}</span>
</pre><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388994440" />
]]></description>
      <pubDate>Thu, 23 Apr 2009 13:37:02 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388994440&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F561</link>
      <guid>http://eustaquiorangel.com/posts/561</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Twitter, Scala e Ruby</title>
      <description><![CDATA[<img src="/images/twitter_ruby_scala.jpg" alt="Peguem os hereges!"/>
<p>
E lá vamos nós de novo! Houve um zum-zum-zum por aí onde se comentou que o <a href="http://twitter.com/taq">Twitter</a> estava (está, sei lá) trocando <a href="http://www.ruby-lang.org">Ruby</a> por <a href="http://www.scala-lang.org">Scala</a> que o mundo quase acabou. Teve gente que, se estivéssemos na idade média, com certeza iam ir munidos de cruzes e tochas na sede do Twitter para tentar queimar tudo, bando de hereges. Literalmente choveram posts sobre isso na web, que eu acho que nem compensa linkar por causa de todo o ruído que causaram, com exceção notável <a href="http://logbr.reflectivesurface.com/2009/04/08/eu-fico-com-a-baleia/">desse aqui do Ronaldo Ferraz</a>, onde, como sempre, ele elabora o tema muito bem, mas eu sou mais tosco (como sempre). Quis fazer esse um pouco mais direto, pois isso já está enchendo o saco.
</p>

<p>
<b>QUE MAL TEM O TWITTER TROCAR DE RUBY PARA SCALA (OU WHATEVER)?</b>
</p>

<p>
Isso vai te afetar? Só se você trabalha no Twitter e não sabe programar em porra nenhuma além de Ruby, e está com preguiça de aprender alguma coisa nova, o que é uma vergonha se tem a oportunidade. Bom, eu não trabalho no Twitter, e acredito que muita gente que está lendo isso também não, então qual é problema, diabos? Precisa de todo esse auê? 
</p>

<p>
"Ah, mas isso pode queimar o filme da linguagem, dizendo que ela não escala, não aguenta o tranco, consome muitos recursos blá blá blá". Ok, vamos lá.

<p>
Quem programa na linguagem (ou em qualquer outra) e <b>gosta</b> do que ela faz e dos seus recursos não precisa se preocupar em "queimação de filme". Que coisa de modinha, pô! Talvez só se precisar entrar em um processo de convencimento da linguagem e/ou tecnologia para o chefe, que pode ser aquele tipo de ameba que toca toda a TI da empresa baseado em folders que recebe pelo Correio (sim, esse pessoal investe em papel bem bonito, nada de email), por muita grana e por notícias que ele vê no site da Info. E talvez essa notícia nem saia lá, então fique tranquilo.
</p>

<p>
Só fica "noiado" quem investe muito em uma "aura santa" da dita cuja e podem perder dinheiro e status (ah, esse talvez mande até mais do que o primeiro) se ela deixar de ser "cool", de ficar em evidência, se carregar o mínimo arranhão sobre o que alguém disse sobre ela. Aí se cria todo esse auê onde o marketing excessivo acaba saturando e remendando a situação, afinal, mesmo que não se chegue à uma conclusão o ruído foi criado e pode ser utilizado para disfarçar a coisa. Você não vai querer ser superficial desse jeito, vai? Olhe o que aconteceu com toda a aura que o Java tinha nos últimos anos. Na AURA, eu disse, não na tecnologia!
</p>

<p>
Vejam bem, eu escrevi um livro sobre a linguagem e fico divulgando ela por aí, mas NUNCA vou fazer um regaço desses se alguém disser "migrei de Ruby pra XYZ" (ok, eu posso ficar inconformado se você for para ASP ou coisa do tipo mas aí a discussão é, além de técnica, filosófica e é outra história) e não vejo necessidade de ficar provando que o pipi dela não é menor do que das outras. Putz, parece que xingam a mãe quando dizem que vão fazer uma migração, quando dizem que não gostam da linguagem ou que ela tem as suas limitações. TODA linguagem tem suas limitações, qual é o problema?
</p>

<p>
Apesar de ser grande utilizador e, porque não, "evangelizador" da linguagem, eu prefiro antes de mais nada ser honesto com quem lê minhas opiniões. Tomara que não chegue o dia em que eu fique sem grana e precise ser pago para dizer "ei, isso é legal", mesmo que a coisa seja uma porcaria. A gente tem visto isso acontecer muito ultimamente, e é algo bem nojento. E eu uso a linguagem <b>sim</b> por achar ela muito boa, não porque quero parecer o gostosão da cocada preta de Ruby. Quem acompanha aqui pode ver que sou bem sossegado em termos de marketing. 
</p>

<p>
Acredito que se você gosta da linguagem, está se divertindo fazendo com gosto os seus programas nela, não deve ligar para umas notícias dessas. Se a gente ligasse tanto para o que os outros fazem e falam não teríamos um monte de coisas legais que tem por aí.
</p>

<p>
Agora, você está começando agora a usar Rails, ou está estudando a linguagem, ou pretende migrar a sua aplicação de XYZ para Rails e está preocupado porque o Twitter migrou, sendo que a sua aplicação pode consumir 1/1000 dos recursos que a deles consome ??? Benza Deus hein!!! Se for desistir fácil assim, melhor comprar a revista mais cara que tem na banca de gerentes e escolher a tecnologia mais cara e talvez, mais obscura, onde você nunca precise escutar nada que possa deixar ela menos "cool". Eita palavrinha que rima com outra coisa. 
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388994441" />
]]></description>
      <pubDate>Thu, 09 Apr 2009 01:59:22 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388994441&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F560</link>
      <guid>http://eustaquiorangel.com/posts/560</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Validando XML com Ruby</title>
      <description><![CDATA[<style type="text/css">
<!--
.rubyMethod { color: #dde93d; } 
.Constant { color: #339999; }
.String { color: #66ff00; }
.Identifier { color: #ffcc00; }
.Special { color: #33aa00; }
.Comment { color: #9933cc; font-style: italic; }
.Type { color: #aaaa77; }
pre { font-family: monospace; color: #eeeeee; background-color: #000000; }
.lnr { color: #ddeeff; background-color: #222222; }
-->
</style>

<p>
Recebi essa semana um email de um leitor aqui do blog (alô!) que me perguntou como fazer validação de um arquivo XML com Ruby, usando <a href="http://www.w3.org/XML/Schema">XML</a> <a href="http://pt.wikipedia.org/wiki/XML_Schema">Schema</a>. Fui honesto e disse que eu nunca havia precisado usar esse lance em Ruby mas fiquei curioso sobre como fazer, já que algum tempo atrás usei algo similar em PHP. Vamos dar uma olhada em como fazer alguma coisa básica disso.
</p>

<p>
Antes de mais nada, precisamos dos arquivos. Vou usar esse XML bem simples, que chamei de <tt>catalogo.xml</tt>:
</p>

<pre>
<span class="lnr"> 1 </span><span class="Comment">&lt;?</span><span class="Type">xml</span><span class="Type"> </span><span class="Type">version</span>=<span class="String">&quot;1.0&quot;</span><span class="Comment">?&gt;</span>
<span class="lnr"> 2 </span><span class="Identifier">&lt;</span><span class="Identifier">catalogo</span><span class="Identifier"> </span><span class="Type">loja</span>=<span class="String">&quot;Livraria O Quarto Homem&quot;</span><span class="Identifier"> </span><span class="Type">ano</span>=<span class="String">&quot;2009&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 3 </span>   <span class="Identifier">&lt;</span><span class="Identifier">categorias</span><span class="Identifier">&gt;</span>
<span class="lnr"> 4 </span>      <span class="Identifier">&lt;</span><span class="Identifier">categoria</span><span class="Identifier"> </span><span class="Type">titulo</span>=<span class="String">&quot;ficcao&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 5 </span>         <span class="Identifier">&lt;</span><span class="Identifier">livro</span><span class="Identifier">&gt;</span>
<span class="lnr"> 6 </span>            <span class="Identifier">&lt;</span><span class="Identifier">titulo</span><span class="Identifier">&gt;</span>A Voz do Fogo<span class="Identifier">&lt;/titulo&gt;</span>
<span class="lnr"> 7 </span>            <span class="Identifier">&lt;</span><span class="Identifier">autor</span><span class="Identifier">&gt;</span>Alan Moore<span class="Identifier">&lt;/autor&gt;</span>
<span class="lnr"> 8 </span>         <span class="Identifier">&lt;/livro&gt;</span>
<span class="lnr"> 9 </span>      <span class="Identifier">&lt;/categoria&gt;</span>
<span class="lnr">10 </span>   <span class="Identifier">&lt;/categorias&gt;</span>
<span class="lnr">11 </span><span class="Identifier">&lt;/catalogo&gt;</span>
</pre>

<p>
Agora vamos começar a construir o arquivo XSD para a validação, tipo esse que chamei de <tt>catalogo.xsd</tt>:
</p>

<pre>
<span class="lnr"> 1 </span><span class="Comment">&lt;?</span><span class="Type">xml</span><span class="Type"> </span><span class="Type">version</span>=<span class="String">&quot;1.0&quot;</span><span class="Type"> </span><span class="Type">encoding</span>=<span class="String">&quot;utf-8&quot;</span><span class="Comment">?&gt;</span>
<span class="lnr"> 2 </span><span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">schema</span><span class="Identifier"> </span><span class="Type">xmlns</span><span class="Comment">:</span><span class="Type">xs</span>=<span class="String">&quot;<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 3 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;catalogo&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 4 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr"> 5 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr"> 6 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">ref</span>=<span class="String">&quot;categorias&quot;</span><span class="Identifier"> </span><span class="Type">minOccurs</span>=<span class="String">&quot;1&quot;</span><span class="Identifier"> </span><span class="Type">maxOccurs</span>=<span class="String">&quot;unbounded&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr"> 7 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr"> 8 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">attribute</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;loja&quot;</span><span class="Identifier"> </span><span class="Type">type</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr"> 9 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">attribute</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;ano&quot;</span><span class="Identifier">  </span><span class="Type">type</span>=<span class="String">&quot;xs:integer&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">10 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">11 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">12 </span>
<span class="lnr">13 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;categorias&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">14 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr">15 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr">16 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">ref</span>=<span class="String">&quot;categoria&quot;</span><span class="Identifier"> </span><span class="Type">minOccurs</span>=<span class="String">&quot;1&quot;</span><span class="Identifier"> </span><span class="Type">maxOccurs</span>=<span class="String">&quot;unbounded&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">17 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr">18 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">19 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">20 </span>
<span class="lnr">21 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;categoria&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">22 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr">23 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr">24 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">ref</span>=<span class="String">&quot;livro&quot;</span><span class="Identifier"> </span><span class="Type">minOccurs</span>=<span class="String">&quot;1&quot;</span><span class="Identifier"> </span><span class="Type">maxOccurs</span>=<span class="String">&quot;unbounded&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">25 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr">26 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">attribute</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;titulo&quot;</span><span class="Identifier"> </span><span class="Type">type</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">27 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">28 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">29 </span>
<span class="lnr">30 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;livro&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">31 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr">32 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr">33 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;titulo&quot;</span><span class="Identifier"> </span><span class="Type">type</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">34 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;autor&quot;</span><span class="Identifier"> </span><span class="Type">type</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">35 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr">36 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">37 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">38 </span><span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">schema&gt;</span>
</pre>

<p>
Ok, até agora nenhum segredo. Arquivos básicos com validação básica. O lance agora é: como vamos usar Ruby para validar esse XML com esse XSD? Eu escolhi usar a <a href="http://libxml.rubyforge.org/rdoc/index.html">libxml-ruby</a>. Para instalá-la, apenas um
</p>

<pre>
gem install libxml-ruby
</pre>

<p>
e está tudo pronto para começarmos a fazer o nosso código de validação. No site da <tt>libxml-ruby</tt> há uma documentação ótima, mas vou dar uma resumida na coisa. Criei um arquivo chamado <tt>xsd.rb</tt> com o seguinte código dentro:
</p>

<pre>
<span class="lnr">1 </span><span class="rubyMethod">require</span> <span class="String">&quot;</span><span class="String">rubygems</span><span class="String">&quot;</span>
<span class="lnr">2 </span><span class="rubyMethod">require</span> <span class="String">&quot;</span><span class="String">xml</span><span class="String">&quot;</span>
<span class="lnr">3 </span>
<span class="lnr">4 </span>xml = <span class="Type">XML</span>::<span class="Type">Document</span>.file(<span class="Identifier">ARGV</span>[<span class="Constant">0</span>])
<span class="lnr">5 </span>schema = <span class="Type">XML</span>::<span class="Type">Schema</span>.document(<span class="Type">XML</span>::<span class="Type">Document</span>.file(<span class="Identifier">ARGV</span>[<span class="Constant">1</span>]))
<span class="lnr">6 </span>puts xml.validate_schema(schema)
</pre>

<p>
O código fala por si mesmo: criamos um objeto novo para o arquivo XML, outro para o XSD, e pedimos para fazer a validação:
</p>

<pre>
[taq@]$ ruby xsd.rb catalogo.xml catalogo.xsd 
true
</pre>

<p>
Ok! Tudo funcionando perfeitamente! Para fazer um pequeno teste, vou trocar o <tt>2009</tt> do arquivo XML para, sei lá, "homer", e vamos rodar novamente:
</p>

<pre>
[taq@]$ ruby xsd.rb catalogo.xml catalogo.xsd 
Error: Element 'catalogo', attribute 'ano': 'homer' is not a valid value of the
atomic type 'xs:integer'. at catalogo.xml:2.
xsd.rb:6:in `validate_schema': Error: Element 'catalogo', attribute 'ano':
'homer' is not a valid value of the atomic type 'xs:integer'. at 
catalogo.xml:2. (LibXML::XML::Error)
from xsd.rb:6
</pre>

<p>
A-há! Tivemos o comportamento esperado!
</p>

<p>
Uma das coisas do problema original era utilizar validação de algum elemento usando uma <a href="http://pt.wikipedia.org/wiki/Express%C3%A3o_regular">expressão regular</a>. Vamos brincar um pouco com o nome do autor, dizendo que tem que ser composto por dois nomes <b>ou</b> a palavra <tt>"Desconhecido"</tt>. Para isso vamos mudar nosso arquivo XSD para:
</p>

<pre>
<span class="lnr"> 1 </span><span class="Comment">&lt;?</span><span class="Type">xml</span><span class="Type"> </span><span class="Type">version</span>=<span class="String">&quot;1.0&quot;</span><span class="Type"> </span><span class="Type">encoding</span>=<span class="String">&quot;utf-8&quot;</span><span class="Comment">?&gt;</span>
<span class="lnr"> 2 </span><span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">schema</span><span class="Identifier"> </span><span class="Type">xmlns</span><span class="Comment">:</span><span class="Type">xs</span>=<span class="String">&quot;<a href="http://www.w3.org/2001/XMLSchema">http://www.w3.org/2001/XMLSchema</a>&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 3 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;catalogo&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 4 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr"> 5 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr"> 6 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">ref</span>=<span class="String">&quot;categorias&quot;</span><span class="Identifier"> </span><span class="Type">minOccurs</span>=<span class="String">&quot;1&quot;</span><span class="Identifier"> </span><span class="Type">maxOccurs</span>=<span class="String">&quot;unbounded&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr"> 7 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr"> 8 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">attribute</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;loja&quot;</span><span class="Identifier"> </span><span class="Type">type</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr"> 9 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">attribute</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;ano&quot;</span><span class="Identifier">  </span><span class="Type">type</span>=<span class="String">&quot;xs:integer&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">10 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">11 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">12 </span>
<span class="lnr">13 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;categorias&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">14 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr">15 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr">16 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">ref</span>=<span class="String">&quot;categoria&quot;</span><span class="Identifier"> </span><span class="Type">minOccurs</span>=<span class="String">&quot;1&quot;</span><span class="Identifier"> </span><span class="Type">maxOccurs</span>=<span class="String">&quot;unbounded&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">17 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr">18 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">19 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">20 </span>
<span class="lnr">21 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;categoria&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">22 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr">23 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr">24 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">ref</span>=<span class="String">&quot;livro&quot;</span><span class="Identifier"> </span><span class="Type">minOccurs</span>=<span class="String">&quot;1&quot;</span><span class="Identifier"> </span><span class="Type">maxOccurs</span>=<span class="String">&quot;unbounded&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">25 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr">26 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">attribute</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;titulo&quot;</span><span class="Identifier"> </span><span class="Type">type</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">27 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">28 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">29 </span>
<span class="lnr">30 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;livro&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">31 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType</span><span class="Identifier">&gt;</span>
<span class="lnr">32 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence</span><span class="Identifier">&gt;</span>
<span class="lnr">33 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;titulo&quot;</span><span class="Identifier"> </span><span class="Type">type</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">34 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">ref</span>=<span class="String">&quot;autor&quot;</span><span class="Identifier"> </span><span class="Type">minOccurs</span>=<span class="String">&quot;1&quot;</span><span class="Identifier"> </span><span class="Type">maxOccurs</span>=<span class="String">&quot;unbounded&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">35 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">sequence&gt;</span>
<span class="lnr">36 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">complexType&gt;</span>
<span class="lnr">37 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">38 </span>
<span class="lnr">39 </span>   <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element</span><span class="Identifier"> </span><span class="Type">name</span>=<span class="String">&quot;autor&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">40 </span>      <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">simpleType</span><span class="Identifier">&gt;</span>
<span class="lnr">41 </span>         <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">restriction</span><span class="Identifier"> </span><span class="Type">base</span>=<span class="String">&quot;xs:string&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">42 </span>            <span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">pattern</span><span class="Identifier"> </span><span class="Type">value</span>=<span class="String">&quot;\w+ \w+|Desconhecido&quot;</span><span class="Identifier">/&gt;</span>
<span class="lnr">43 </span>         <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">restriction&gt;</span>
<span class="lnr">44 </span>      <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">simpleType&gt;</span>
<span class="lnr">45 </span>   <span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">element&gt;</span>
<span class="lnr">46 </span><span class="Identifier">&lt;/</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">schema&gt;</span>
</pre>

<p>
Notem as mudanças nas linhas <tt>34</tt> e da <tt>39</tt> até a <tt>45</tt> e brinquem um pouco com o arquivo XML.
</p>

<p>
O <tt>\w</tt> deve funcionar até para todos os caracteres acentuados, mas se por acaso ocorrer algum caso muito específico onde houver a necessidade de deixar explicíta alguma exceção do Unicode, ou você estiver rodando a sua validação em algum lugar onde não tenha controle dos softwares instalados e haja algum problema em relação à libxml com caracteres acentuados, algum problema de encoding dos arquivos, etc. etc.,podemos utilizar alguns <a href="http://unicode.org/unicode/reports/tr18/">padrões bem documentados</a> para contornar isso. Vamos supor que nosso arquivo XML fosse assim:
</p>

<pre>
<span class="lnr"> 1 </span><span class="Comment">&lt;?</span><span class="Type">xml</span><span class="Type"> </span><span class="Type">version</span>=<span class="String">&quot;1.0&quot;</span><span class="Comment">?&gt;</span>
<span class="lnr"> 2 </span><span class="Identifier">&lt;</span><span class="Identifier">catalogo</span><span class="Identifier"> </span><span class="Type">loja</span>=<span class="String">&quot;Livraria O Quarto Homem&quot;</span><span class="Identifier"> </span><span class="Type">ano</span>=<span class="String">&quot;2009&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 3 </span>   <span class="Identifier">&lt;</span><span class="Identifier">categorias</span><span class="Identifier">&gt;</span>
<span class="lnr"> 4 </span>      <span class="Identifier">&lt;</span><span class="Identifier">categoria</span><span class="Identifier"> </span><span class="Type">titulo</span>=<span class="String">&quot;ficção&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr"> 5 </span>         <span class="Identifier">&lt;</span><span class="Identifier">livro</span><span class="Identifier">&gt;</span>
<span class="lnr"> 6 </span>            <span class="Identifier">&lt;</span><span class="Identifier">titulo</span><span class="Identifier">&gt;</span>A Voz do Fogo<span class="Identifier">&lt;/titulo&gt;</span>
<span class="lnr"> 7 </span>            <span class="Identifier">&lt;</span><span class="Identifier">autor</span><span class="Identifier">&gt;</span>Alan Moore<span class="Identifier">&lt;/autor&gt;</span>
<span class="lnr"> 8 </span>         <span class="Identifier">&lt;/livro&gt;</span>
<span class="lnr"> 9 </span>      <span class="Identifier">&lt;/categoria&gt;</span>
<span class="lnr">10 </span>      <span class="Identifier">&lt;</span><span class="Identifier">categoria</span><span class="Identifier"> </span><span class="Type">titulo</span>=<span class="String">&quot;programação&quot;</span><span class="Identifier">&gt;</span>
<span class="lnr">11 </span>         <span class="Identifier">&lt;</span><span class="Identifier">livro</span><span class="Identifier">&gt;</span>
<span class="lnr">12 </span>            <span class="Identifier">&lt;</span><span class="Identifier">titulo</span><span class="Identifier">&gt;</span>Ruby: Conhecendo a Linguagem<span class="Identifier">&lt;/titulo&gt;</span>
<span class="lnr">13 </span>            <span class="Identifier">&lt;</span><span class="Identifier">autor</span><span class="Identifier">&gt;</span>Eustáquio Rangel<span class="Identifier">&lt;/autor&gt;</span>
<span class="lnr">14 </span>         <span class="Identifier">&lt;/livro&gt;</span>
<span class="lnr">15 </span>      <span class="Identifier">&lt;/categoria&gt;</span>
<span class="lnr">16 </span>   <span class="Identifier">&lt;/categorias&gt;</span>
<span class="lnr">17 </span><span class="Identifier">&lt;/catalogo&gt;</span>
</pre>

<p>
Notem o acento no nome desse quem vos escreve, na linha <tt>13</tt>. Agora vamos supor, para efeitos didáticos, que por alguma razão maluca não estamos utilizando o <tt>\w</tt> na expressão para validar o nome do autor, sei lá, de repente ele não funciona, e sim algo do tipo:
</p>

<pre>
<span class="lnr">1 </span><span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">pattern</span><span class="Identifier"> </span><span class="Type">value</span>=<span class="String">&quot;[A-z]+ [A-z]+|Desconhecido&quot;</span><span class="Identifier">/&gt;</span>
</pre>

<p>
O arquivo nunca seria validado:
</p>

<pre>
[taq@]$ ruby xsd.rb catalogo.xml catalogo.xsd
Error: Element 'autor': [facet 'pattern'] The value 'Eustáquio Rangel' is not 
accepted by the pattern '[A-z]+ [A-z]+|Desconhecido'. at catalogo.xml:13.
Error: Element 'autor': 'Eustáquio Rangel' is not a valid value of the local 
atomic type. at catalogo.xml:13.
xsd.rb:6:in `validate_schema': Error: Element 'autor': 'Eustáquio Rangel' is 
not a valid value of the local atomic type. at catalogo.xml:13. 
(LibXML::XML::Error) from xsd.rb:6
</pre>

<p>
Aí poderíamos ter escrito a expressão dessa maneira:
</p>

<pre>
<span class="lnr">1 </span><span class="Identifier">&lt;</span><span class="Special">xs</span><span class="Comment">:</span><span class="Identifier">pattern</span><span class="Identifier"> </span><span class="Type">value</span>=<span class="String">&quot;\p{L}+ \p{L}+|Desconhecido&quot;</span><span class="Identifier">/&gt;</span>
</pre>

<p>
E o arquivo validaria de boa:
</p>

<pre>
[taq@]$ ruby xsd.rb catalogo.xml catalogo.xsd
true
</pre>

<p>
O <tt>\p{L}</tt> ali no caso representa um caracter na categoria "Letra" do Unicode, em qualquer língua. Mais <a href="http://www.regular-expressions.info/unicode.html">um monte de exemplos de categorias do Unicode vocês podem encontrar aqui</a> e podem ser uma mão na roda para alguma situação mais específica que possa aparecer.
</p><img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=388994442" />
]]></description>
      <pubDate>Sun, 05 Apr 2009 17:08:27 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=388994442&amp;url=http%3A%2F%2Feustaquiorangel.com%2Fposts%2F559</link>
      <guid>http://eustaquiorangel.com/posts/559</guid>
      <source url="http://eustaquiorangel.com/feeds/rss/">Blog do TaQ</source>
    </item>
    <item>
      <title>Dry Ice</title>
      <description/>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=380579335&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[We got a gift in the mail of some Kansas City Steaks. The
kids' reaction was "We got dry ice!"<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=380579335" />
]]></content:encoded>
      <guid>http://bitworking.org/news/430/dry-ice</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>URI Templates design experience</title>
      <description/>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=380579336&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[It's been a while since the URI Template draft has been updated, and in the interim
there has been some implementation experience:


http://blog.springsource.com/2009/03/08/rest-in-spring-3-mvc/
http://code.google.com/p/uri-templates/wiki/Implementations


In the intervening months two things have happened:


In all the URI Template examples I've seen, only the simplest case {foo} has even been shown.
   I've been repeatedly asked about "going the other way", i.e. parsing URIs based on templates.


This leads to two questions:


Are there any real-world uses of the more complex URI Templates, or is {foo} enough?
  If the syntax is simplified to {foo} there is an opportunity to support the parsing
   case, ala WSGIDispatcher
    Is that of interest to anyone?

Feedback on the  W3C URI mailing  is appreciated.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=380579336" />
]]></content:encoded>
      <guid>http://bitworking.org/news/429/uri-templates-design-experience</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>The (lack of) design patterns in Python - PyCon 2009</title>
      <description/>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=380579337&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[The video for my design patterns talk at PyCon 2009 has been posted:<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=380579337" />
]]></content:encoded>
      <guid>http://bitworking.org/news/428/the-lack-of-design-patterns-in-python-pycon-2009</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Selected quotes on REST and "empty window" interfaces</title>
      <description/>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=380579338&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[The impetus for this post in part comes from a conversation 
I had at PyCon. A developer had admitted that in
the past he had served up a high-traffic web page that was the same
for every visitor, but then used a bit of Javascript to pull up
the users information separately to customize the page, but he
felt "dirty" doing it.
That was pretty surprising to me because it's a perfect use of Javascript, 
and it highlights a misunderstanding about the role of Javascript in
the web.

Sean McGrath:


    I don't know which way it will go but I would suggest that if we are 
    searching for what exactly the web *is* we have to go further than say it is
    HTML, as Hugh does in this piece.
    

    For me, the web is URIs, a standard set of verbs and a standardized EVAL
    function. The verbs are mostly GET and POST and the standardized EVAL function
    is the concept of a browser that can EVAL HTML and can eval JavaScript. I don't
    thing we can afford to leave JavaScript out of the top level definition of what
    the Web is because there is too much at stake.
    

The short answer is that using Javascript can be RESTful:
Fielding Dissertation - Section 5.1.7:


    The final addition to our constraint set for REST comes from the code-on-demand
    style of Section 3.5.3 (Figure 5-8). REST allows client functionality to be
    extended by downloading and executing code in the form of applets or scripts.
    This simplifies clients by reducing the number of features required to be
    pre-implemented. Allowing features to be downloaded after deployment improves
    system extensibility. However, it also reduces visibility, and thus is only an
    optional constraint within REST.
    


The emphasis is my own, and is the crux of the problem, that using too much Javascript can
reduce visibility, not only to intermediaries, but also to other denizens 
of the web, like crawlers.


There is a broad range on which Javascript can be applied in building
a web site, from sites that use HTML and CSS only, to sites that
require Javascript to access any functionality. 
The latter are what I call "empty window" interfaces, because
if you visit the site with Javascript turned off all you're 
going to see is an "empty window".

GWT and Search Engine indexing:


    You're barking up the wrong tree here. GWT is for writing
    AJAX/RIA/whatever-you-want-to-call-them applications. It makes the
    obnoxious JS bits tolerable. JS applications are inherently unfriendly
    to search engines. You can overcome that (as Ian has done) but it
    isn't going to be as simple as tossing an HTML file on some random web
    server and having it indexed. 
    

It's picking the right range for your application to sit in 
that matters, and picking that range depends on how searchable
you want to be.


Simon Willison:



    Annoyed at Google Moderator http://moderator.appspot.com/ - I can 
    see absolutely no reason why it should be a JavaScript-required service
    


NIST is assembling standards around SaaS, and one component of 
that standard is understanding the value of the data versus the 
risk of it being exposed. We need a similar decision framework 
for web applications, but in this case the reverse, the value of 
the data versus the risk of it not being indexed.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=380579338" />
]]></content:encoded>
      <guid>http://bitworking.org/news/427/js-rest-and-empty-windows</guid>
      <source url="http://bitworking.org/news/feed/">BitWorking | Joe Gregorio</source>
    </item>
    <item>
      <title>Calling JAXP from Ruby</title>
      <description><![CDATA[I’ve now got a Ruby module that calls into the JAXP API.  Why is this a big deal?  Validator.nu has a HtmlDocumentBuilder that complies with HTML 5.  Furthermore, JAXP has full support for XPath and Nokogiri has the ability to convert CSS into XPath.  This may seem like going the long way around, but my intuition is that the expensive parts will be transferring data across the language boundary (especially strings).  Having a DOM entirely on the Java side, probed via CSS selectors and/or XPath expressions and only retrieving the specific nodes across the Java/Ruby boundary for further processing should minimize this issue.  And the end result should be able to pass all of the Nokogiri and Validator.nu tests.<img alt="" src="http://xfruits.com/lsdr/?id=21914&amp;s_item=389124209" />
]]></description>
      <pubDate>Thu, 01 Jan 1970 00:00:00 GMT</pubDate>
      <link>http://xfruits.com/lsdr/planet/?clic=389124209&amp;url=</link>
      <content:encoded xmlns:content="http://purl.org/rss/1.0/modules/content/"><![CDATA[Demo:
ruby domencoding.rb test.xml
iso-8859-7

java domencoding test.xml
iso-8859-7

./domencoding test.xml
iso-8859-7

cd jaxp; ruby -r jaxp -e 'include Jaxp; puts parse("../test.xml")'
iso-8859-7
Backstory:

First, a very simple program in Ruby using an excellent XML parser (based on libxml2 with the API of Hpricot).
Next, an equivalent program in Java using JAXP.
Then, the same program in C++ using JAXP via CNI.  Oddly, I get a NullPointerException if I call parse with a file name, but it works if I first construct a FileInputStream and pass that.  For now, I’ve left in the catching of the Java exception and printing of the stack and decided to press on.
Finally, I wrap the C++ code into a module that can be called by Ruby.  Strings are a bit of a pain, but at least that logic can be refactored into a separate function and reused.


Next step would be to make the API mirror the remainder of the Nokogiri/Hpricot API.  Care will have to be taken to make sure that the Java objects are “pinned” at the appropriate time, don’t leak, and no cycles are created in the graph, but all that should be doable.
Future work could be to convert CNI to JNI.  Or to make Henri’s C++ translator produce output that is independent of Mozilla libraries (and potentially make use of Ruby libraries for things like heap management).  That, and repeat this exercise for languages like Python and PHP.
Why is this a big deal?  Well, validator.nu has a HtmlDocumentBuilder that complies with HTML 5.  Furthermore, JAXP has full support for XPath and Nokogiri has the ability to convert CSS into XPath:
$ irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'nokogiri'
=> true
irb(main):003:0> cssparser = Nokogiri::CSS::Parser.new
=> #<Nokogiri::CSS::Parser:0x7f576c31cb10 @namespaces={}>
irb(main):004:0> cssparser.xpath_for('p.foo a[href$=".pdf"]')
=> ["//p[contains(concat(' ', @class, ' '), ' foo ')]//a[substring(@href, string-length(@href) - string-length(\".pdf\") + 1, string-length(\".pdf\")) = \".pdf\"]"]
This may seem like going the long way around, but my intuition is that the expensive parts will be transferring data across the language boundary (especially strings).  Having a DOM entirely on the Java side, probed via CSS selectors and/or XPath expressions and only retrieving the specific nodes across the Java/Ruby boundary for further processing should minimize this.  And the end result should be able to pass all of the Nokogiri and Validator.nu tests.
Best of breed Ruby API with best of breed HTML parser.  What’s not to like?]]></content:encoded>
      <guid isPermaLink="false">tag:intertwingly.net,2004:3031</guid>
      <source url="http://www.intertwingly.net/blog/index.atom">Sam Ruby</source>
    </item>
  </channel>
</rss>
