<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>H3RALD</title>
    <link>http://www.h3rald.com</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Fabio Cevasco's Writings</description>
    <item>
      <title>Book Review: Design Patterns in Ruby</title>
      <description>&lt;p style="float:right"&gt;&lt;img src="/files/design_patterns_in_ruby.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;I finally got my hands on a shiny new copy of &lt;em&gt;Design Patterns in Ruby&lt;sup&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/em&gt;. The book itself is not brand new and it was already widely praised by many different people online, so I wanted to take a look for myself.&lt;/p&gt;


	&lt;p&gt;To my surprise, the book is a hardcover edition, which makes it look more professional and more durable than the average programming book&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;. It&amp;#8217;s also smaller and shorter than the average programming book&lt;sup&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt; (340 pages), which makes it much easier to carry around and less intimidating to read. It&amp;#8217;s also &lt;em&gt;not&lt;/em&gt; meant to be a reference book, so it is actually pleasant an easy to read all in one go, as you&amp;#8217;ll soon find out.&lt;/p&gt;


	&lt;p&gt;What is it about? &amp;mdash; well, design patters in the Ruby language of course. But it&amp;#8217;s not the usual brainwash of programming theory you would expect by a typical book on patters, it has &lt;em&gt;plenty&lt;/em&gt; of examples of real code. When I say &lt;em&gt;real code&lt;/em&gt; I don&amp;#8217;t mean the usual Dog/Cat/Horse/&amp;lt;insert animal here&amp;gt; classes or juke-box simulations which don&amp;#8217;t work at all etc. etc., I mean actual snippets from well known Ruby applications, like RubyGems, FXRuby and, of course, Rails.
OK well, there&amp;#8217;s an exception perhaps: Russ &lt;em&gt;did&lt;/em&gt; include a few wild life simulations (ponds with frogs and similar), but it&amp;#8217;s only for your own good, and for the sake of tradition.&lt;/p&gt;


	&lt;p&gt;Anyhow, let&amp;#8217;s start from the beginning&amp;#8230;&lt;/p&gt;


	&lt;h3&gt;Part I: Patters and Ruby&lt;/h3&gt;


	&lt;p&gt;The first part of the book serves as a general introduction to the other two parts. If you know the basics of both design patterns and Ruby, you can safely skip this as you won&amp;#8217;t find anything of overwhelming interest here.&lt;/p&gt;


	&lt;p&gt;Personally I really liked &lt;strong&gt;Chapter 1&lt;/strong&gt; though, &amp;#8220;Building better Programs with Patterns&amp;#8221;, in which Russ does a great job in summarizing the original GoF book&lt;sup&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt; into four points::&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;em&gt;Separate our the things that change from those that stay the same.&lt;/em&gt;&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;Program to an interface, not an implementation.&lt;/em&gt;&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;Prefer composition over inheritance.&lt;/em&gt;&lt;/li&gt;
		&lt;li&gt;&lt;em&gt;Delegate, delegate, delegate.&lt;/em&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Also, although it does not come from the Design Patterns book but from building real systems, the author adds the &lt;span class="caps"&gt;YAGNI&lt;/span&gt; (You Ain&amp;#8217;t Gonna Need It) principle&lt;sup&gt;&lt;a href="#fn4"&gt;4&lt;/a&gt;&lt;/sup&gt; as a reminder to resist the temptation of implementing things which &lt;em&gt;may&lt;/em&gt; be needed &lt;em&gt;later on&lt;/em&gt;, even if they are not needed right now.
The chapter ends with an outline of the patterns which will be presented throughout the book: 14 out of the original 23 patterns by the Gand of Four will be discussed in Part II and 3 bonus &amp;#8220;Ruby-only&amp;#8221; patterns will be examined in Part &lt;span class="caps"&gt;III&lt;/span&gt;, as a special treat.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Chapter 2&lt;/strong&gt; (&lt;em&gt;Getting started with Ruby&lt;/em&gt;) feels perhaps a bit out of place. As others pointed out&lt;sup&gt;&lt;a href="#fn5"&gt;5&lt;/a&gt;&lt;/sup&gt;, why does a book on advanced Ruby programming techniques include a 35-page-long introduction on the Ruby language? The answer was given by Russ himself in an interview&lt;sup&gt;&lt;a href="#fn6"&gt;6&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;


&lt;blockquote&gt;
&amp;#8220;The reason that I included the introductory chapter about Ruby in there was to make the book accessible to folks with little or no Ruby background.
Now honestly, I don&#8217;t think that you could come to my book with no background in Ruby and walk away from it an expert Ruby programmer &amp;mdash; it&#8217;s not really that kind of introductory book.
But I do think that someone with experience in other languages could read my book and come away knowing about Ruby, understanding what all the shouting is about.&amp;#8221; 
&lt;/blockquote&gt;

	&lt;p&gt;I admit, I skipped this chapter during my first reading because I was eager to move on to the main part of the book, but I did read it afterwards (I had to write this review after all!). It&amp;#8217;s quite a nice introduction aimed at the average .NET/Java developer: Russ provides a step-by-step presentation of the main features of the language while holding the reader by hand when something weird or scary comes about:&lt;/p&gt;


&lt;blockquote&gt;
The slightly strange-looking syntax in this code is actually a tip-off something deep and important: In Ruby, everythng &amp;mdash; and I mean &lt;em&gt;everything&lt;/em&gt; &amp;mdash; is an object.
&lt;/blockquote&gt;

	&lt;p&gt;Of course Chapter 2 won&amp;#8217;t turn you into a Ruby guru, but it definitely fulfills one of the author&amp;#8217;s goals: bringing developers of other languages closer to Ruby, and give them a tiny taste of how Ruby can be &lt;em&gt;wickedly powerful&lt;/em&gt;.&lt;/p&gt;


	&lt;h3&gt;Part II: Patterns in Ruby&lt;/h3&gt;


	&lt;p&gt;Part II constitutes the bulk of the book, describing 14 GoF patterns in 220 pages. The patterns covered are the following:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Template Method&lt;/li&gt;
		&lt;li&gt;Strategy&lt;/li&gt;
		&lt;li&gt;Observer&lt;/li&gt;
		&lt;li&gt;Composite&lt;/li&gt;
		&lt;li&gt;Iterator&lt;/li&gt;
		&lt;li&gt;Command&lt;/li&gt;
		&lt;li&gt;Adapter&lt;/li&gt;
		&lt;li&gt;Proxy&lt;/li&gt;
		&lt;li&gt;Decorator&lt;/li&gt;
		&lt;li&gt;Singleton&lt;/li&gt;
		&lt;li&gt;Factory Method&lt;/li&gt;
		&lt;li&gt;Abstract Factory Method&lt;/li&gt;
		&lt;li&gt;Builder&lt;/li&gt;
		&lt;li&gt;Interpreter&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Why not covering all 23? Well, because to be honest, they are rarely used in Ruby. Furthermore, in some cases some of the ones examined in the book may feel a bit &lt;em&gt;unnatural&lt;/em&gt; to the average Rubyist: how many times did you ever think about using an External Iterator when &lt;code&gt;each&lt;/code&gt; is normally available as default internal iterator for any Array-like class?&lt;/p&gt;


	&lt;p&gt;Each chapter in this part is devoted to a particular pattern and it is organized in more or less the same way, as outlined in the following sections.&lt;/p&gt;


	&lt;h4&gt;Introduction and Personal Anecdotes&lt;/h4&gt;


	&lt;p&gt;Most chapters start with a personal anecdote involving the author: it may be a memory related to his first job at the local grocery store (Chapter 8), or about the day he decided to buy his son a bike (Chapter 14):&lt;/p&gt;


&lt;blockquote&gt;
&amp;#8220;I remember the day we bought my son his first bike.&amp;#8221; [&amp;#8230;] I spent hours trying to pull together a minor junkiard of parts according to instructions that would have baffled the entire National Security Agency. As it turned out, picking the bike was the easy part: putting it together was the real challenge.
&lt;/blockquote&gt;

	&lt;p&gt;This was used to introduce the Builder pattern, and how to use it to configure objects which include different logical parts.
Personally I find this technique particularly useful to introduce a particular problem from a different, more mundane prospective instead of starting off with an abstract theorethical description of the pattern itself. 
The anecdote is then followed by the description of the actual programming problem for which the specific pattern will be used.&lt;/p&gt;


	&lt;h4&gt;Description of the Pattern and Initial Implementation&lt;/h4&gt;


	&lt;p&gt;An initial implementation of the pattern in Ruby will be provided more or less immediately after the introduction of each chapter, often accompanied by a simple &lt;span class="caps"&gt;UML&lt;/span&gt; diagram.
This implementation normally has quite a few conceptual flaws, which are then examined and corrected step-by-step the chapter to obtain a more &amp;#8220;Ruby-friendly&amp;#8221; solution.&lt;/p&gt;


	&lt;h4&gt;A More Rubyfied Version of the Pattern&lt;/h4&gt;


	&lt;p&gt;The final implementation of each pattern is often very different from the initial attempt, and it may contain quite a lot of Ruby-specific code. The author does an excellent job in suggesting pattern implementations which often use blocks, &lt;code&gt;Proc&lt;/code&gt; objects or method redefinitions when needed, to make the code more succint and more readable at the same time, as all Ruby code should be.&lt;/p&gt;


	&lt;p&gt;By doing so, even people who are still learning Ruby will understand how to use some very useful Ruby idioms which can be a bit difficult to grasp otherwise.&lt;/p&gt;


	&lt;h4&gt;Using and Abusing &amp;lt;Pattern&amp;gt;&lt;/h4&gt;


	&lt;p&gt;Patterns are often overused and misused, and some people normally end up wondering if they should be used at all, after all. This section (present as a matter of fact in &lt;em&gt;every&lt;/em&gt; chapter of part II an &lt;span class="caps"&gt;III&lt;/span&gt;) examines the pitfalls of the pattern and the most common mistakes developer make when applying it.
It is by far the most useful section of each chapter, and that&amp;#8217;s what I&amp;#8217;ll be reading and re-reading every time I&amp;#8217;m thinking about using a particular pattern in my code. As a matter of fact, these sections make you realize that &lt;em&gt;every&lt;/em&gt; pattern has its own inherent flaws and dangers, and that it is far from being a Silver Bullet. Even when you&amp;#8217;re &lt;em&gt;supposed&lt;/em&gt; to use a pattern to accomplish something, be aware that &lt;em&gt;something nasty&lt;/em&gt; can happen unless you&amp;#8217;re extra careful: this, perhaps, is the true Golden Rule conveyed throughout the whole book.&lt;/p&gt;


	&lt;h4&gt;&amp;lt;Pattern&amp;gt;s in the Wild&lt;/h4&gt;


	&lt;p&gt;This is another very interesting section which is included in every chapter of part II and &lt;span class="caps"&gt;III&lt;/span&gt;. After describing what a pattern does, how it &lt;em&gt;can&lt;/em&gt; be used and how it &lt;em&gt;should&lt;/em&gt; be used, you&amp;#8217;ll finally find some interesting examples taken from real world applications.
By &amp;#8220;real world application&amp;#8221; I mean something like ActiveRecord&lt;sup&gt;&lt;a href="#fn7"&gt;7&lt;/a&gt;&lt;/sup&gt; (Observer, Command, Adapter, &amp;#8230;), DRb&lt;sup&gt;&lt;a href="#fn8"&gt;8&lt;/a&gt;&lt;/sup&gt; (Proxy) or FXRuby&lt;sup&gt;&lt;a href="#fn9"&gt;9&lt;/a&gt;&lt;/sup&gt; (Composite), for example, i.e. important programs and libraries which are used in production environments.
Personally, I was really glad to find such examples in this book: it definitely helps you feeling design patterns as something more practical and useful than pure software architecture theories.&lt;/p&gt;


	&lt;h4&gt;Wrapping it Up&lt;/h4&gt;


	&lt;p&gt;&amp;#8220;Wrapping it Up&amp;#8221; is the title of the last section of each chapter of Part II and &lt;span class="caps"&gt;III&lt;/span&gt;. It&amp;#8217;s basically a summary of the whole chapter and thus a useful way to recap the most important concepts. I found this section particularly useful when using the book as a design pattern reference, after reading it for the first time: this section provides a quick and essential overview of each pattern&amp;#8212;and the most important DOs and &lt;span class="caps"&gt;DON&lt;/span&gt;&amp;#8217;Ts, too.&lt;/p&gt;


	&lt;h3&gt;Part &lt;span class="caps"&gt;III&lt;/span&gt;: Patterns for Ruby&lt;/h3&gt;


	&lt;p&gt;By the time you get to Part &lt;span class="caps"&gt;III&lt;/span&gt; you&amp;#8217;ll definitely feel that Ruby can do &lt;em&gt;more&lt;/em&gt;. Some of the Ruby implementation of certain patterns described in the book make extensive use of blocks and Proc objects, and the &lt;code&gt;method_missing&lt;/code&gt; method (although potentially dangerous unless extra care is taken) gives us a more immediate way to obtain delegation, for example when creating Proxies. 
Also the fact that objects can be modified at runtime by adding and removing methods &amp;#8220;as needed&amp;#8221; seems quite an underused feature in traditional patterns, simply because those patterns were first conceived for languages which are very different from Ruby and are perhaps less &lt;em&gt;liberal&lt;/em&gt; than Ruby when it comes to dynamic features&lt;sup&gt;&lt;a href="#fn10"&gt;10&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;


	&lt;p&gt;These particular Ruby features can be used (and abused, of course) to implement more Ruby-esque patterns, such as the ones included in this part of the book:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Internal Domain-Specific Languages&lt;/li&gt;
		&lt;li&gt;Meta-Programming&lt;/li&gt;
		&lt;li&gt;Convention Over Configuration&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;These are just examples, of course some may complain because the Active Record or &lt;span class="caps"&gt;ORM&lt;/span&gt; pattern are missing, but this is understandable as it may be considered too specific compared to the others. 
Each pattern is examined in detail, and I particularly like way the &lt;span class="caps"&gt;DSL&lt;/span&gt; pattern was described: Chapter 16 explains how to develop a simple but effective Ruby &lt;span class="caps"&gt;DSL&lt;/span&gt; from scratch for creating file backups. This can be particularly useful for people who never tried creating DSLs before, but also for developers who tried, but want to improve their skills.&lt;/p&gt;


	&lt;p&gt;Chapter 18 (Convention Over Configuration) is sufficiently clear and detailed, perhaps even too much if you already know how Rails was developed (and all the hype which follwed).&lt;/p&gt;


	&lt;p&gt;On the other hand, I was a bit disappointed by Chapter 17 (Meta-Programming). Maybe it&amp;#8217;s because I built up extremely high expectations about it while reading the rest of the book, but it just felt too short and not detailed enough for my liking. If I had to write such a chapter (which would have been actually very hard), I would have started from an excellent post by Ola Bini&lt;sup&gt;&lt;a href="#fn11"&gt;11&lt;/a&gt;&lt;/sup&gt; which introduces &lt;em&gt;eleven&lt;/em&gt; meta-programming techniques, and built up content and examples from there. The only reason why &lt;del&gt;- I think -&lt;/del&gt; Russ didn&amp;#8217;t do it in his book was length/balance constraint: a &lt;em&gt;properly detailed&lt;/em&gt; chapter about meta-programming in Ruby could easily take up over forty pages!&lt;/p&gt;


	&lt;h3&gt;The Verdict&lt;/h3&gt;


	&lt;p&gt;As I said in the beginning: this is not meant to be a complete, in-depth, reference book on everything you may want to know about design patterns in Ruby. That&amp;#8217;s why, as a matter of fact, you can actually read this book all the way through without getting utterly bored. Russ uses an informal, yet appropriate style to turn potentially complex, theorethical computer science principles into easy-to-understand, &lt;em&gt;useful&lt;/em&gt; tools which can truly improve the way you code.&lt;/p&gt;


	&lt;p&gt;The whole book flows very very nicely. I actually recommend reading this book in sequence, without skipping chapters, because each pattern is described in a way that is somehow linked to the following ones, so that you can understand and learn about the pros and cons of each one in a more natural and useful way.&lt;/p&gt;


	&lt;p&gt;OK, I would have loved to see Part &lt;span class="caps"&gt;III&lt;/span&gt; as long as Part II, probably, but overall I&amp;#8217;m very, very satisfied of what the book taught me. The only problem is that it also made me suddenly realize all the naive design mistakes I&amp;#8217;ve been making when coding in Ruby, so I&amp;#8217;ll now feel compelled to fix at least some of them&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Definitely a worthwhile read, I just hope to see more books like this, or even a second edition of this one soon!&lt;/p&gt;


	&lt;h3&gt;Notes&lt;/h3&gt;


	&lt;p id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; &lt;a href="http://www.informit.com/store/product.aspx?isbn=0321490452"&gt;Design Patterns in Ruby&lt;/a&gt; by Russ Olsen, Addison Wesley Professional, 2007.&lt;/p&gt;


	&lt;p id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; Think of &lt;a href="http://www.pragprog.com/titles/ruby"&gt;Programming Ruby: The Pragmatic Programmer&amp;#8217;s Guide, 2nd Ed.&lt;/a&gt; by Dave Thomas with Chad Fowler and Andy Hunt, Pragmatic Programmers, 2004.&lt;/p&gt;


	&lt;p id="fn3"&gt;&lt;sup&gt;3&lt;/sup&gt; &lt;a href="http://www.informit.com/store/product.aspx?isbn=0201633612"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;, by By Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides (a.k.a. the &lt;em&gt;Gang of Four&lt;/em&gt;), Addison Wesley Professional, 1994.&lt;/p&gt;


	&lt;p id="fn4"&gt;&lt;sup&gt;4&lt;/sup&gt; For more information on the &lt;span class="caps"&gt;YAGNI&lt;/span&gt; principle, visit &lt;a href="http://www.xprogramming.com/Practices/PracNotNeed.html"&gt;You&amp;#8217;re &lt;span class="caps"&gt;NOT&lt;/span&gt; gonna need it&lt;/a&gt;, Ronald E Jeffries.&lt;/p&gt;


	&lt;p id="fn5"&gt;&lt;sup&gt;5&lt;/sup&gt; See &lt;a href="http://on-ruby.blogspot.com/2007/12/design-patterns-in-ruby-review.html"&gt;Design Patterns in Ruby, a review&lt;/a&gt;, _On Ruby_blog.&lt;/p&gt;


	&lt;p id="fn6"&gt;&lt;sup&gt;6&lt;/sup&gt; See &lt;a href="http://on-ruby.blogspot.com/2008/01/russ-olsen-interview.html"&gt;Russ Olsen Interview&lt;/a&gt;, _On Ruby_blog.&lt;/p&gt;


	&lt;p id="fn7"&gt;&lt;sup&gt;7&lt;/sup&gt; &lt;a href="http://ar.rubyonrails.com/"&gt;ActiveRecord&lt;/a&gt; is an implementation of the Object-Relational Mapping (ORM) pattern used by the Ruby on Rails framework.&lt;/p&gt;


	&lt;p id="fn8"&gt;&lt;sup&gt;8&lt;/sup&gt; Distributed Ruby, see &lt;a href="http://chadfowler.com/ruby/drb.html"&gt;Intro to DRb&lt;/a&gt; by Chad Fowler.&lt;/p&gt;


	&lt;p id="fn9"&gt;&lt;sup&gt;9&lt;/sup&gt; &lt;a href="http://www.fxruby.org/"&gt;FXRuby&lt;/a&gt;, a graphical toolkit written in Ruby.&lt;/p&gt;


	&lt;p id="fn10"&gt;&lt;sup&gt;10&lt;/sup&gt; This can be a good or bad thing depending on the way you look at it, and what you want to use the language for. The fact that Ruby is dynamically typed makes it easier to do things which are totally impossible in C++ or Java, but it also introduces a whole new set of potential dangers.&lt;/p&gt;


	&lt;p id="fn11"&gt;&lt;sup&gt;11&lt;/sup&gt; &lt;a href="http://ola-bini.blogspot.com/2006/09/ruby-metaprogramming-techniques.html"&gt;Ruby Metaprogramming Techniques&lt;/a&gt;, Ola Bini: Programming Language Synchronicity.&lt;/p&gt;</description>
      <pubDate>Fri, 11 Apr 2008 05:41:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:3a469896-539e-4cec-9288-78108accf7af</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/articles/design-patterns-in-ruby-review</link>
      <category>Articles</category>
      <category>ruby</category>
      <category>review</category>
      <category>books</category>
      <enclosure url="http://www.h3rald.com/files/design_patterns_in_ruby.jpg" type="image/jpeg" length="19218"/>
      <trackback:ping>http://www.h3rald.com/trackback/entries/157</trackback:ping>
    </item>
    <item>
      <title>New Release: RawLine 0.2.0</title>
      <description>&lt;p&gt;&lt;del&gt;InLine&lt;/del&gt; RawLine 0.2.0 is out!&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Raw&lt;/strong&gt;Line is the new name for InLine, in case you didn&amp;#8217;t guess. The name was changed to avoid name collision problems with the RubyInline project.&lt;/p&gt;


	&lt;p&gt;Here&amp;#8217;s what&amp;#8217;s new:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Added /examples and /test directory to gem.&lt;/li&gt;
		&lt;li&gt;Escape codes can now be used in prompt.&lt;/li&gt;
		&lt;li&gt;It is now possible to use bind(key, &amp;#38;block) with a String as key, even if the corresponding escape sequence is not defined.&lt;/li&gt;
		&lt;li&gt;Added Editor#write_line(string) to print a any string (and &amp;#8220;hit return&amp;#8221;).&lt;/li&gt;
		&lt;li&gt;Library name changed to &amp;#8220;RawLine&amp;#8221; to avoid name collision issues (Bug &lt;a href="http://rubyforge.org/tracker/?func=detail&amp;#38;aid=18879&amp;#38;group_id=5622&amp;#38;atid=21788"&gt;18879&lt;/a&gt;).&lt;/li&gt;
		&lt;li&gt;Provided alternative implementation for left and right arrows if terminal
supports escape sequences (on Windows, it requires the Win32Console gem).&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;In particular, I decided to provide an &amp;#8220;optimized implementation&amp;#8221; for the left and right arrows using escape sequences rather than shameful hacks. This is now possible because the Win32Console gem now enables &lt;span class="caps"&gt;ANSI&lt;/span&gt; escape sequences on Windows as well (weehee!).&lt;/p&gt;


	&lt;p&gt;So:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;If you&amp;#8217;re on *nix all good, your terminal is smart and can understand escape sequences =&amp;gt; the new implementation will be used.&lt;/li&gt;
		&lt;li&gt;If you&amp;#8217;re on Windows and you installed Win32Console, your termnal is smart and can understand escape sequences =&amp;gt; the new implementation will be used.&lt;/li&gt;
		&lt;li&gt;If you&amp;#8217;re on Windows and you didn&amp;#8217;t install Win32Console, then your terminal is stupid and it doesn&amp;#8217;t understand escape sequences, so the old implementation will be used.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The new implementation is significantly faster than the old one, on Windows at least, and the cursor now blinks properly when left or right arrows are pressed.&lt;/p&gt;


	&lt;p&gt;I re-emplemented only cursor movement because I&amp;#8217;m still having some problems in getting the delete/insert escapes to work properly (or better: how I want them to work!).&lt;/p&gt;</description>
      <pubDate>Wed, 02 Apr 2008 05:33:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:6241d85c-e816-4c5c-9e9e-61a4f87d59de</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/blog/rawline-020</link>
      <category>Blog</category>
      <category>ruby</category>
      <category>programming</category>
      <category>OpenSource</category>
      <category>RawLine</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/156</trackback:ping>
    </item>
    <item>
      <title>InLine name change: what's your opinion?</title>
      <description>&lt;p&gt;I&amp;#8217;ve been kindly asked by the lead developer of &lt;a href="http://www.zenspider.com/ZSS/Products/RubyInline/"&gt;RubyInLine&lt;/a&gt; to change the name of my &lt;a href="http://rubyforge.org/projects/inline/"&gt;InLine&lt;/a&gt; project, due to potential confusion and conflicts.&lt;/p&gt;


	&lt;p&gt;This makes sense, and I&amp;#8217;m ready to change the name of my project, although I&amp;#8217;m not that good at choosing original and &lt;em&gt;smart&lt;/em&gt; names, so well, any suggestion is more than welcome!&lt;/p&gt;


	&lt;p&gt;I was thinking of something like:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;RawLine&lt;/li&gt;
		&lt;li&gt;EditLine&lt;/li&gt;
		&lt;li&gt;RawInput&lt;/li&gt;
		&lt;li&gt;RubyInput&lt;/li&gt;
		&lt;li&gt;RubyLine&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I personally think that &lt;strong&gt;RawLine&lt;/strong&gt; is probably the best option, but please, if have any better idea just speak up!&lt;/p&gt;


	&lt;p&gt;P.S.: &amp;#8220;RedLine&amp;#8221; is taken, unfortunately, otherwise it would have been my first choice since the beginning.&lt;/p&gt;</description>
      <pubDate>Thu, 27 Mar 2008 06:30:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:cbe78136-e994-4e16-92c2-d6dae16fc9c7</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/blog/inline-name-change</link>
      <category>Blog</category>
      <category>ruby</category>
      <category>programming</category>
      <category>OpenSource</category>
      <category>RawLine</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/153</trackback:ping>
    </item>
    <item>
      <title>RawLine - a 100% Ruby solution for console inline editing</title>
      <description>&lt;p&gt;One of the many things I like about Ruby is its cross-platform nature: as a general rule, Ruby code runs on everything which supports Ruby, regardless of its architecture and platform (yes, there are quite a few exceptions, but let&amp;#8217;s accept this generalization for now).&lt;/p&gt;


	&lt;p&gt;More specifically, I liked the fact that I could use the &lt;a href="http://tiswww.case.edu/php/chet/readline/rltop.html"&gt;&lt;span class="caps"&gt;GNU&lt;/span&gt; Readline library&lt;/a&gt; with Ruby seamlessly on both Windows and Linux.
Readline offers quite a lot of features which are useful for those people like me who enjoy creating command-line scripts, in a nutshell, it provides:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;File/Word completion&lt;/li&gt;
		&lt;li&gt;History support&lt;/li&gt;
		&lt;li&gt;Custom key bindings which can be modified via .inputrc&lt;/li&gt;
		&lt;li&gt;Emacs and Vi edit modes&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Basically it makes your command-line interface fast and powerful, and that&amp;#8217;s not an overstatement. Ruby&amp;#8217;s own &lt;span class="caps"&gt;IRB&lt;/span&gt; can be enhanced by enabling readline and completion, and it works great&amp;#8212;at least on *nix systems.&lt;/p&gt;


	&lt;p&gt;For some weird reason, some people had problems with Readline on Windows: in particular, things get nasty when you start editing long lines. Text gets garbled, the cursor goes up one or two lines and doesn&amp;#8217;t come back, and other similar leprechaun&amp;#8217;s tricks, which are not that funny after a while.&lt;/p&gt;


	&lt;p&gt;Apparently there&amp;#8217;s no alternative to Readline in the Ruby world. If you wan&amp;#8217;t tab completion that&amp;#8217;s it, you&amp;#8217;re stuck. Would it be difficult to implement &lt;em&gt;some&lt;/em&gt; of Readline functionality natively in Ruby? Maybe, but the problem is that for some reason the Ruby Standard Library doesn&amp;#8217;t have low level methods to operate on keystrokes&amp;#8230;&lt;/p&gt;


	&lt;p&gt;&amp;#8230;but luckily, the &lt;a href="http://highline.rubyforge.org/"&gt;HighLine&lt;/a&gt; gem does! James Edward Gray II keeps pointing out here and here that HighLine&amp;#8217;s own &lt;code&gt;get_character&lt;/code&gt; method does just that: it returns the corresponding character code(s) right when a key is pressed, unlike &lt;code&gt;IO#gets()&lt;/code&gt; which waits for the user to press &lt;span class="caps"&gt;ENTER&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Believe it or not, that tiny method can do wonders&amp;#8230;&lt;/p&gt;


	&lt;h2&gt;Reverse-engineering escape codes&lt;/h2&gt;


	&lt;p&gt;So here&amp;#8217;s a little script which uses &lt;code&gt;get_character()&lt;/code&gt; in an endless loop, diligently printing the character codes corresponding to a keystroke:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/local/bin/ruby -w&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;highline/system_extensions&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;include&lt;/span&gt; &lt;span class="constant"&gt;HighLine&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;SystemExtensions&lt;/span&gt;

&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Press a key to view the corresponding ASCII code(s) (or CTRL-X to exit).&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;loop&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;

    &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;=&amp;gt; &lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
    &lt;span class="ident"&gt;char&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;get_character&lt;/span&gt;
    &lt;span class="keyword"&gt;case&lt;/span&gt; &lt;span class="ident"&gt;char&lt;/span&gt;
    &lt;span class="keyword"&gt;when&lt;/span&gt; &lt;span class="char"&gt;?\C&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;x&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;print&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Exiting...&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="ident"&gt;exit&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{char.chr}&lt;/span&gt; [&lt;span class="expr"&gt;#{char}&lt;/span&gt;] (hex: &lt;span class="expr"&gt;#{char.to_s(16)}&lt;/span&gt;)&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;A pretty harmless little thing. Try to run it and press some keys, and see what you get:&lt;/p&gt;


&lt;div style="font-family: Monospace"&gt;
Press a key to view the corresponding &lt;span class="caps"&gt;ASCII&lt;/span&gt; code(s) (or &lt;span class="caps"&gt;CTRL&lt;/span&gt;-X to exit).

	&lt;p&gt;=&amp;gt; a [96] (hex: 61)&lt;/p&gt;


	&lt;p&gt;=&amp;gt; 1 [49] (hex: 31)&lt;/p&gt;


	&lt;p&gt;=&amp;gt; Q [81] (hex: 51)&lt;/p&gt;


	&lt;p&gt;=&amp;gt; &amp;alpha; [224] (hex: e0)&lt;/p&gt;


	&lt;p&gt;=&amp;gt; K [75] (hex: 4b)&lt;/p&gt;


&lt;/div&gt;

	&lt;p&gt;Hang on, what are the last two codes? &lt;em&gt;A left arrow key on Windows&lt;/em&gt;, apparently.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Welcome to the wonderful world of input escape sequences!&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;To cut a long story short, both Windows and *nix system &amp;#8220;terminals&amp;#8221; translate special keystrokes into sequences of two or more codes. This applies to things like &lt;span class="caps"&gt;DEL&lt;/span&gt;, INSERT, arrows, etc. etc.
For some ideas, check out:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.microsoft.com/whdc/device/input/Scancode.mspx"&gt;Windows Scancodes&lt;/a&gt; (Thanks &lt;a href="http://64.223.189.234/node/92"&gt;Huff&lt;/a&gt;)&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://www.connectrf.com/Documents/vt220.html"&gt;&lt;span class="caps"&gt;VT220&lt;/span&gt; Terminal Input Sequences&lt;/a&gt; (Thanks &lt;a href="http://www.grayproductions.net/"&gt;James&lt;/a&gt;)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Let&amp;#8217;s now assume that we&amp;#8217;re smart and we can write a program which can parse keystroke properly, including handling different input escape sequences according to the OS, what can it be used for?
Well:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;For normal characters, just print them back to the screen (&lt;code&gt;get_character&lt;/code&gt; doesn&amp;#8217;t print anything, it &amp;#8220;steals&amp;#8221; the keystroke)&lt;/li&gt;
		&lt;li&gt;For special characters, do something nice!&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;We could setup &lt;span class="caps"&gt;TAB&lt;/span&gt; to auto-complete the current word according to an array of matches, or bind the up arrow to load the last line typed in by the user, for example, that&amp;#8217;s basically something Readline does, right?&lt;/p&gt;


	&lt;h2&gt;RawLine: how it works and what it does&lt;/h2&gt;


	&lt;p&gt;I created a small project on RubyForge called &lt;a href="http://rubyforge.org/projects/rawline/"&gt;RawLine&lt;/a&gt; (not to be confused with RubyInline, a completely different thing altogether, sorry about that) to play around with the possibilities offered by the &lt;code&gt;get_character&lt;/code&gt; method. The library is just a preview of things which can be done, but it&amp;#8217;s already usable, provided that you&amp;#8217;re brave enough to try it out, that is.&lt;/p&gt;


	&lt;p&gt;The basic idea behind RawLine is to be able to parse keystrokes properly on different platforms and re-bind them to a set of predefined, cross-platform actions or a user-defined code block.&lt;/p&gt;


	&lt;h3&gt;Basic line-editing operations&lt;/h3&gt;


	&lt;p&gt;The first challenge was to re-invent the wheel, i.e. re-bind keystrokes to their typical actions: a left arrow moves the cursor left, a backspace deletes the character at the left of the cursor and so on. Yes, because &lt;code&gt;get_characters&lt;/code&gt; gives you the right character codes at the price of &lt;em&gt;cancelling their normal effects&lt;/em&gt;, which is a great thing, as you&amp;#8217;ll soon find out.&lt;/p&gt;


	&lt;p&gt;Printing a character on the screen was one of the easiest tasks (at first). &lt;code&gt;IO#putc&lt;/code&gt; does the job pretty well: it prints a character out.
What about moving left? Easy: print a non-descructive backspace (\b) and hope it is really not destructive. I did some tests and it seems to do as it&amp;#8217;s told and move the cursor back by one position.&lt;/p&gt;


	&lt;p&gt;Moving right was a little trickier: the easiest thing I found was to re-print the character under the cursor, which will then move the cursor forward (as naive as it may seem, it does the job!). If there&amp;#8217;s nothing under the cursor, then we must be at the end of the line and it shouldn&amp;#8217;t move anywhere, so there we go.&lt;/p&gt;


	&lt;p&gt;What if I move left a bit and then start typing normal characters? Well, everything is rewritten of course: this will be our &amp;#8220;character replace mode&amp;#8221;. Unfortunately users don&amp;#8217;t like this behavior that much, so what I did was this:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Copy all characters from the one at the left of the cursor till the end of the line&lt;/li&gt;
		&lt;li&gt;Print the character to be inserted&lt;/li&gt;
		&lt;li&gt;Re-print the previously-copied characters&lt;/li&gt;
		&lt;li&gt;Move the cursor back at the right place&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Again, a primitive solution which works seamlessly on all platforms, and yes, it&amp;#8217;s fast enough that you don&amp;#8217;t notice the difference.&lt;/p&gt;


	&lt;p&gt;As you may have guessed, this of course means that I always had to keep track of:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;The cursor position within the line&lt;/li&gt;
		&lt;li&gt;The text currently printed to the screen&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Backspace and delete were implemented in a similar way, you can figure it out yourself or look at the source code: I won&amp;#8217;t bore you any further!&lt;/p&gt;


	&lt;h3&gt;History management&lt;/h3&gt;


	&lt;p&gt;The next step was to implement a history for both the characters inputted by the user (to allow undoing and redoing operations) and for the whole lines. This was just an ordinary programming exercise: a simple buffer with some extra controls here and there, nothing too scary.&lt;/p&gt;


	&lt;p&gt;So every &amp;#8220;modification&amp;#8221; to the current line being typed is saved in a line history buffer and all the lines entered are saved in another history buffer. All is left is to allow users to navigate through these buffers back and forth. 
Nothing impossible: all I had to do was keeping track of the current element of the history being retrieved and then overwrite the current line with a new line stored in the buffer? How&amp;#8217;s this line overwriting done? Same old:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Move the cursor to the beginnig of the line&lt;/li&gt;
		&lt;li&gt;Print X spaces, where X is the line length, so that the characters are no longer displayed in the console&lt;/li&gt;
		&lt;li&gt;Move the cursor back to the beginning of the line&lt;/li&gt;
		&lt;li&gt;Print the new line.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Easy and naive, as usual. But again, it works well enough.&lt;/p&gt;


	&lt;h3&gt;Word completion&lt;/h3&gt;


	&lt;p&gt;The other challange was word completion. The current implementation can be summarized as follows:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;If &lt;span class="caps"&gt;TAB&lt;/span&gt; (or another character, if you wish) is pressed, call a user-defined &lt;code&gt;completion_proc&lt;/code&gt; method which returns an array and show the first element of the array (in this case I actually used a cyclic RawLine::HistoryBuffer, not an array)&lt;/li&gt;
		&lt;li&gt;If the user presses &lt;span class="caps"&gt;TAB&lt;/span&gt; again, show another match, and so &lt;em&gt;ad infinitum&lt;/em&gt; if the user keeps pressing &lt;span class="caps"&gt;TAB&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;If the user presses another key, accept the default completion and move on.&lt;/li&gt;
	&lt;/ul&gt;


Obviously this means that:
	&lt;ul&gt;
	&lt;li&gt;RawLine has to keep track of the current &amp;#8220;word&amp;#8221;. A word is everything separated by a user defined &lt;code&gt;word_separator&lt;/code&gt;, which can obviously modified at runtime, with care.&lt;/li&gt;
		&lt;li&gt;Regarding the &lt;code&gt;completion_proc&lt;/code&gt;, typically you may want to return only the elements matching the word which is currently being written, so that&amp;#8217;s given as default parameter for your proc. Exactly like with ReadLine, the only difference is that you can access other things like &lt;em&gt;the whole line&lt;/em&gt; and &lt;em&gt;the whole history&lt;/em&gt; in real time, which can be really handy at times!&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Here&amp;#8217;s a simple example:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;completion_proc&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;
        &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;select&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;update&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;delete&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;debug&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;destroy&lt;/span&gt;&lt;span class="punct"&gt;'].&lt;/span&gt;&lt;span class="ident"&gt;find_all&lt;/span&gt;    &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;e&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;e&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;^&lt;span class="expr"&gt;#{Regexp.escape(word)}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;h3&gt;Custom key bindings&lt;/h3&gt;


	&lt;p&gt;All these pretty things are obviously bound to some keystrokes. If the key corresponds to only one code, everything is fine, but because special keys typically aren&amp;#8217;t so it was necessary to implement a mechanism to track an escape key (e.g. 0xE0 and 0 on Windows and \e on Linux) and listen to further characters, in case a known sequence is found. Anyhow, the final result of the method used for character binding is the following:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;bind(key, &amp;#38;block)&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;Where key can be:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;A &lt;code&gt;Fixnum&lt;/code&gt; corresponding to a single character code&lt;/li&gt;
		&lt;li&gt;An &lt;code&gt;Array&lt;/code&gt; of one or more character codes&lt;/li&gt;
		&lt;li&gt;A &lt;code&gt;String&lt;/code&gt; corresponding to an escape sequence&lt;/li&gt;
		&lt;li&gt;A &lt;code&gt;Symbol&lt;/code&gt; corresponding to a known escape sequence or key&lt;/li&gt;
		&lt;li&gt;A &lt;code&gt;Hash&lt;/code&gt; to define a new key or escape sequences&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So, in the end you can do things like this:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:left_arrow&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;move_left&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\e&lt;/span&gt;test&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;overwrite_line&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Test!!&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="char"&gt;?\C&lt;/span&gt;&lt;span class="punct"&gt;-&lt;/span&gt;&lt;span class="ident"&gt;z&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;undo&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="number"&gt;24&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;exit&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Which, for Rubyists, it&amp;#8217;s far sexier and more flexible than editing an .inputrc file.&lt;/p&gt;


	&lt;h3&gt;How do I use it, anyway?&lt;/h3&gt;


	&lt;p&gt;A code example is better than a thousand words, right? So here you are:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="comment"&gt;#!/usr/local/bin/ruby -w&lt;/span&gt;

&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rubygems&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;rawline&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;*** Inline Editor Test Shell ***&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; * Press CTRL+X to exit&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; * Press CTRL+C to clear command history&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; * Press CTRL+D for line-related information&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt; * Press CTRL+E to view command history&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;

&lt;span class="ident"&gt;editor&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;RawLine&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;

&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:ctrl_c&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;clear_history&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:ctrl_d&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;debug_line&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:ctrl_e&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;show_history&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;bind&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:ctrl_x&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt;&lt;span class="punct"&gt;;&lt;/span&gt; &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;Exiting...&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;;&lt;/span&gt; &lt;span class="ident"&gt;exit&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;

&lt;span class="ident"&gt;editor&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;completion_proc&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;lambda&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;word&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;word&lt;/span&gt;
        &lt;span class="punct"&gt;['&lt;/span&gt;&lt;span class="string"&gt;select&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;update&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;delete&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;debug&lt;/span&gt;&lt;span class="punct"&gt;',&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;destroy&lt;/span&gt;&lt;span class="punct"&gt;'].&lt;/span&gt;&lt;span class="ident"&gt;find_all&lt;/span&gt;    &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;e&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;e&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;match&lt;/span&gt;&lt;span class="punct"&gt;(/&lt;/span&gt;&lt;span class="regex"&gt;^&lt;span class="expr"&gt;#{Regexp.escape(word)}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;loop&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt;
    &lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;You typed: [&lt;span class="expr"&gt;#{editor.read(&amp;quot;=&amp;gt; &amp;quot;).chomp!}&lt;/span&gt;]&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;This example can be found in examples/rawline_shell.rb within the RawLine source code or gem package.&lt;/p&gt;


	&lt;h2&gt;Current status and availability&lt;/h2&gt;


	&lt;p&gt;I currently &lt;a href="http://rubyforge.org/forum/forum.php?forum_id=22543"&gt;released&lt;/a&gt; RawLine 0.1.0 on &lt;a href="http://rubyforge.org/projects/rawline"&gt;SourceForge&lt;/a&gt;, and it can be installed via:&lt;/p&gt;


	&lt;p&gt;&lt;code&gt;gem install -r rawline&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;The RDoc documentation is available &lt;a href="http://rawline.rubyforge.org/"&gt;here&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Feel free to try it out. First of all try the &lt;code&gt;rawline_shell.rb&lt;/code&gt; example, and see if it works on your machine. If it doesn&amp;#8217;t than maybe you try re-binding some keys (use &lt;code&gt;key_tester.rb&lt;/code&gt; to &amp;#8220;reverse-engineer&amp;#8221; your terminal&amp;#8217;s input escape sequences), and let me know!&lt;/p&gt;


	&lt;p&gt;Status information and limitations:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;It has been tested on Windows (XP, using the usual command prompt) and on Linux (ZenWalk, using &lt;span class="caps"&gt;XFCE&lt;/span&gt; Terminal). &lt;/li&gt;
		&lt;li&gt;It can handle lines no longer than the maximum terminal width &amp;#8211; 2. This is to ensure that the cursor never &amp;#8220;falls down&amp;#8221; to the next line.&lt;/li&gt;
		&lt;li&gt;On Windows, the cursor doesn&amp;#8217;t blink immedialy when moving left, but it moves, don&amp;#8217;t worry.&lt;/li&gt;
		&lt;li&gt;On Linux, you should really consider installing the &lt;a href="http://raa.ruby-lang.org/project/ruby-termios/"&gt;Termios&lt;/a&gt; library for a faster experience (otherwise &lt;code&gt;get_character&lt;/code&gt; won&amp;#8217;t parse characters correctly if you press and hold a key, and that, trust me, is a real mess!).&lt;/li&gt;
		&lt;li&gt;RawLine is very far from being a complete replacement for the ReadLine library, and it is currently in alpha stage.&lt;/li&gt;
		&lt;li&gt;Release 0.1.0 has been created after 2 weeks of sporadic coding during lunch breaks and week-ends.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;For any ideas on where to go from here, comments and feedback, just reply below or send an email to my usual email address.&lt;/p&gt;</description>
      <pubDate>Mon, 10 Mar 2008 06:59:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:63fe570a-0c27-4ab4-9a8f-cf32e1cdf551</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/blog/inline-introduction</link>
      <category>Blog</category>
      <category>ruby</category>
      <category>programming</category>
      <category>OpenSource</category>
      <category>RawLine</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/152</trackback:ping>
    </item>
    <item>
      <title>Book Review: Writing Efficient Ruby Code</title>
      <description>&lt;p style="float:right"&gt;&lt;img src="/files/efficient_ruby_shortcut.jpeg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;The second shortcut from Addison-Wesley Professional series I&amp;#8217;m going to review is called &lt;a href="http://www.informit.com/store/product.aspx?isbn=0321540034"&gt;Writing Efficient Ruby Code&lt;/a&gt;. A very promising title, especially considering that this book is only 50 pages long.&lt;/p&gt;


	&lt;p&gt;As usual, this shortcut can be intended as a sort of programmer-friendly detailed cheatsheet: like the other ones in this series it sports a monitor-friendly landscape layout and does not go to deep into the details unless strictly necessary to understand a particular concept.&lt;/p&gt;


	&lt;h3&gt;The Author&lt;/h3&gt;


	&lt;p&gt;&lt;a href="http://railsexpress.de/blog/"&gt;Dr. Stefan Kaes&lt;/a&gt;, the author, contributed a lot to improve Ruby on Rails&amp;#8217; performance by refactoring portions of its core and try to &amp;#8220;get maximum speed out of performance-critical sections of code&amp;#8221;. This short but interesting shortcut groups together a lot of performance tweaks, tips and tricks but also some &amp;#8220;anti-patterns&amp;#8221; Kaes was able to identify through his career as programming teacher Ruby software consultant and key Rails contributor.&lt;/p&gt;


	&lt;h3&gt;The Contents&lt;/h3&gt;


	&lt;p&gt;Like with the previously-covered &lt;a href="/articles/mongrel-shortcut-review"&gt;Mongrel shortcut&lt;/a&gt;, &lt;em&gt;Writing Efficient Ruby Code&lt;/em&gt; always goes straight to the point when it comes to identify problems. The first one mentioned is of course that the &lt;em&gt;Ruby Interpreter is Slow&lt;/em&gt;, most people are aware of that, due to their direct experience or because this argument is normally used by non-Rubyists to argue the language&amp;#8217;s usability in commercial projects. What you may not know is why that is so, and that&amp;#8217;s where the first part of this book comes into play.&lt;/p&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;em&gt;&amp;#8220;Ruby is a highly dynamic language: Almost all language entities are first-class citizens in that they can be created, changed, and destroyed at runtime. This comprises classes, modules, methods, constants, and class and instance variables. Only local variables are second-class citizens in Ruby: Whether a name refers to a local variable is determined at parse time.&lt;/em&gt;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;This makes Ruby extremely flexible, but also more complex. Whever you use a name to refer to an object, Ruby has to search for the object it refers to, and this costs in terms of processing time.&lt;/p&gt;


	&lt;p&gt;As a matter of fact, one of the most recurring tips in the book to improve code performance is the following:&lt;/p&gt;


	&lt;p style="text-align:center;"&gt;&lt;strong&gt;Method calls are expensive, use variables directly when possible.&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Keep this in mind: &lt;code&gt;self.something&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; the same as &lt;code&gt;@something&lt;/code&gt;. The end result is the same, but the first way costs more in terms of performance because Ruby has to look up the method name.
Similarly, &lt;strong&gt;local variables &lt;em&gt;should&lt;/em&gt; be introduced as a way to &amp;#8220;cache&amp;#8221; the result of method calls&lt;/strong&gt;. Often you may feel &amp;#8220;guilty&amp;#8221; to introduce a new variable and keep calling the same method over and over: this should definitely be avoided.&lt;/p&gt;


	&lt;p&gt;Other useful tips include, for example:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Use syntax constructs (e.g. assignments) as expressinons. Use evaluation precedences.&lt;/li&gt;
		&lt;li&gt;Use interpolated strings &lt;code&gt;"... #{string_variable}"&lt;/code&gt; (there&amp;#8217;s also no performance difference if constant strings are used between &lt;code&gt;"&lt;/code&gt; or &lt;code&gt;'&lt;/code&gt;)&lt;/li&gt;
		&lt;li&gt;Use operators which update the data structure without copying it (when possible). Use &lt;code&gt;update&lt;/code&gt; or &lt;code&gt;merge&lt;/code&gt; to update hashes.&lt;/li&gt;
		&lt;li&gt;Iterating using &lt;code&gt;for a in  A&lt;/code&gt; is slightly faster than performing the same iteration using &lt;code&gt;each&lt;/code&gt;, (it is the opposite in Ruby 1.9 though)&lt;/li&gt;
		&lt;li&gt;do not use &lt;code&gt;return&lt;/code&gt; unless you have to&lt;/li&gt;
		&lt;li&gt;test in order of expected case frequency&lt;/li&gt;
		&lt;li&gt;Use parallel assignment (&lt;code&gt;a, b = 5, 6&lt;/code&gt;) where applicable&lt;/li&gt;
		&lt;li&gt;If a module gets included in only one other class (or module), it&#8217;s preferable to open the class instead.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I deliberately chose not to elaborate any further on the tips listed above because otherwise I&amp;#8217;ll give a big chunk of the contents of the book itself. If you know Ruby enough, you may already know why such reccommendations make sense, but if you don&amp;#8217;t, &lt;em&gt;Writing Efficient Ruby Code&lt;/em&gt; can be a short but very interesting read.&lt;/p&gt;


	&lt;h3&gt;The Good&lt;/h3&gt;


	&lt;p&gt;For each of the 30 &amp;#8220;coding patterns&amp;#8221; (and consequent anti-patterns) described in the book, the author does a great job explaining the reasons of doing something in a particular way, also through examples and benchmarks, where possible.&lt;/p&gt;


	&lt;p&gt;Furthermore, this &lt;em&gt;shortcut&lt;/em&gt; can really be useful to grasp a few difference between Ruby 1.8.5, 1.8.6 and 1.9 in terms of performance: not all the patters apply to all Ruby implementations, and when that&amp;#8217;s the case it is clearly stated.&lt;/p&gt;


	&lt;h3&gt;The Bad&lt;/h3&gt;


	&lt;p&gt;My only complaint about the book is probably the lack of details and more &amp;#8220;specialized&amp;#8221; patterns. Everything (except for a few Rails-specific tips) normally apply to Ruby &lt;em&gt;as a whole&lt;/em&gt;, without going deeply to analyze specific libraries or third-party gems. As a result, once you get the general idea, some of the patters may seem pretty obvious or a logic consequence of others.&lt;/p&gt;


	&lt;p&gt;It is also true that this is meant to be a &lt;em&gt;shortcut&lt;/em&gt;, not a comprehensive analysis on code optimization techniques which can be applied to specific cases: something like this would require much more than 50 pages!&lt;/p&gt;


	&lt;h3&gt;The Bottom Line&lt;/h3&gt;


	&lt;p&gt;Read it, re-read a few bits of it to make sure you grasp the most important concepts, and keep its table of contents in front of you as a reminder when refactoring your code!&lt;/p&gt;</description>
      <pubDate>Mon, 21 Jan 2008 05:47:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:6712bd59-655a-4682-a2f5-4dafc0c1a69b</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/articles/efficient-ruby-code-shortcut-review</link>
      <category>Articles</category>
      <category>ruby</category>
      <category>review</category>
      <category>books</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/151</trackback:ping>
    </item>
    <item>
      <title>A Firefox Lover's Guide to Opera</title>
      <description>&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article can be considered a sequel for &lt;a href="http://www.h3rald.com/articles/ie-lovers-guide-to-firefox"&gt;An IE Lover&amp;#8217;s Guide to Firefox&lt;/a&gt;, which described Firefox through the eyes of an Internet Explorer fan. Similarly, this article describes Opera&amp;#8217;s features from the point of view of a user &amp;ndash; myself &amp;ndash; who has been using Firefox for years and is now considering another browser switch.&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p&gt;I am a Firefox fan. I&amp;#8217;ve been using Firefox since it was named &amp;#8220;Firebird&amp;#8221; and calling it &amp;#8220;stable&amp;#8221; was a big overstatement. Firefox dragged me out of Internet Explorer, and that was definitely one of its biggest achievements.&lt;/p&gt;


	&lt;p&gt;Because I&amp;#8217;m addicted to trying out new tools, however, I always kept testing new browsers I discovered here and there. K-Meleon, Flock, Sleipnir&amp;#8230; When Safari came out for Windows I immediately installed it and used it for about 2 hours, only to realize that it wasn&amp;#8217;t &amp;ndash; and it still isn&amp;#8217;t &amp;ndash; usable at all, mainly due to sporadic crashes.&lt;/p&gt;


	&lt;p style="float:right"&gt;&lt;img src="/files/opera/fast.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;Similarly, I&amp;#8217;ve been trying out &lt;a href="http://www.opera.com/"&gt;Opera&lt;/a&gt; periodically, as new releases came out, but again it didn&amp;#8217;t seem to work for me. The biggest complaint I had was its inability to render heavily-ajaxified web sites properly. However, now it seems that the Opera Development Team made a big effort to improve the browser, and I was pleased to notice that &lt;a href="http://www.opera.com/products/desktop/next/"&gt;Opera 9.5b&lt;/a&gt; (&amp;#8220;Kestrel&amp;#8221;) doesn&amp;#8217;t seem to have this sort of problems at all.&lt;/p&gt;


	&lt;h3&gt;Planning the Switch&lt;/h3&gt;


	&lt;p&gt;Firefox has extensions. Plenty of them actually. Some are useful, like the newish Del.icio.us one made by Yahoo, and also crappy ones you&amp;#8217;ll never use unless you want to have a fancy button on one of your over-cluttered toolbars which enables you to interface more easily with X or Y web services you hardly ever use.&lt;/p&gt;


	&lt;p&gt;By contrast, Opera never attempted to add full-blown extension support to its venerable and yet very powerful browser. Instead, they kept building more and more features right into its core, being careful not to undermine the browser&amp;#8217;s two proverbial qualities: &lt;em&gt;speed&lt;/em&gt; and &lt;em&gt;stability&lt;/em&gt;. What seemed a doomed philosophy at first turned out to be a good thingin the long run. More and more people are getting more and more worried about Firefox&amp;#8217;s memory issues and begin to &lt;em&gt;wander off&lt;/em&gt; to explore new things, exactly like I did.&lt;/p&gt;


	&lt;p&gt;The first step to switch from Firefox to Opera is to reduce the number of Firefox extensions to the bare minimum you need:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Colorzilla&lt;/li&gt;
		&lt;li&gt;Web Developer&lt;/li&gt;
		&lt;li&gt;MeasureIt&lt;/li&gt;
		&lt;li&gt;Search Status&lt;/li&gt;
		&lt;li&gt;Gmail Manager&lt;/li&gt;
		&lt;li&gt;Secure Login&lt;/li&gt;
		&lt;li&gt;Del.icio.us

	&lt;p&gt;How many extensions do you &lt;em&gt;actually&lt;/em&gt; use? Here&amp;#8217;s a short analysis for the ones above:&lt;/p&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;ul&gt;
	&lt;li&gt;The first three are related to Web Development only, which means that I don&amp;#8217;t need them unless I&amp;#8217;m doing some web-development tests during which I&amp;#8217;m always going to have more than one browser open anyway. &lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; there are a few &lt;a href="http://widgets.opera.com/search/?order=name&amp;#38;q=ruler"&gt;Ruler&lt;/a&gt; widget which can be used instead of MeasureIt &lt;em&gt;(thanks &lt;strong&gt;Ameer&lt;/strong&gt;)&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;SearchStatus gives me Alexa Rank and Google Pagerank: I think I can survive without those for a while. &lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; if not, there&amp;#8217;s always &lt;a href="http://www.puzzleclub.ru/files/seobar/"&gt;SEObar&lt;/a&gt; &lt;em&gt;(thanks &lt;strong&gt;Ameer&lt;/strong&gt;)&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;I use Gmail Manager because my girlfriend uses Gmail on the same computer. I&amp;#8217;m switching to Opera and she&amp;#8217;ll stick with Firefox, so no problem there&amp;#8230;&lt;/li&gt;
		&lt;li&gt;Secure Login? It&amp;#8217;s called &lt;em&gt;Wand&lt;/em&gt; and it has been built-in into Opera for the last decade or so.&lt;/li&gt;
		&lt;li&gt;Del.icio.us &amp;ndash; OK, I won&amp;#8217;t be able to access my favorite tags as quickly, but &lt;a href="http://erlang.no/2005/10/06/delicious-opera-buttons-2/"&gt;someone&lt;/a&gt; already came out with a few handy buttons for a better integration with the popular social bookmarking service.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;blockquote&gt;
		&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:&lt;/strong&gt; For a list of the features provided by Firefox extensions which are included in Opera, see Rijk&amp;#8217;s &lt;a href="http://files.myopera.com/Rijk/blog/extensions.html"&gt;Top 150 Popular Firefox Extensions and Opera&lt;/a&gt;&lt;/p&gt;
	&lt;/blockquote&gt;


	&lt;p style="float:right"&gt;&lt;img src="/files/opera/opera_navigation.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;Because I&amp;#8217;m addicted to betas, I immediately downloaded &lt;a href="http://www.opera.com/products/desktop/next/"&gt;Opera Kestrel&lt;/a&gt;, i.e. Opera 9.50 beta 1. I never actually liked Opera&amp;#8217;s default theme, so I started looking around for &lt;strong&gt;&lt;a href="http://my.opera.com/community/customize/skins/"&gt;new skins&lt;/a&gt;&lt;/strong&gt; (yes, eye-candy matters sometimes) and came across the Ximple series by &lt;a href="http://my.opera.com/community/customize/skins/author/?id=serafins"&gt;serafins&lt;/a&gt;. In particular, &lt;a href="http://my.opera.com/community/customize/skins/info/?id=3835"&gt;2nd thought &amp;#8211; Jimple&lt;/a&gt; quickly became my favorite.&lt;/p&gt;


	&lt;h3&gt;Tabs&lt;/h3&gt;


	&lt;p&gt;&lt;em&gt;&amp;#8220;Opera is the Web pioneer that delivered tabbed browsing in 2000 [&amp;#8230;]&amp;#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;Opera tabs &lt;em&gt;feel&lt;/em&gt; stable and mature. Why? Probably because tabs are used more consistently to open not only web pages but also:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Downloads (&amp;#8220;Transfers&amp;#8221;)&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;RSS&lt;/span&gt; feeds&lt;/li&gt;
		&lt;li&gt;Notes&lt;/li&gt;
		&lt;li&gt;Emails&lt;/li&gt;
		&lt;li&gt;Bookmarks&lt;/li&gt;
		&lt;li&gt;Widget Management &lt;/li&gt;
		&lt;li&gt;Contacts&lt;/li&gt;
		&lt;li&gt;History&lt;/li&gt;
		&lt;li&gt;Page Links&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I think this is a great feature and Firefox should definitely consider it: v3.0 comes with new download and bookmark managers, but they&amp;#8217;re still dialogs. Yes, I know, there&amp;#8217;s probably some extension which allows you to display them in the sidebar, but that&amp;#8217;s not the point: Opera brings more consistency to the overall browsing experience by using tabs wherever they should be used.&lt;/p&gt;


	&lt;p&gt;Additionally, Opera tabs&amp;#8230;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Can be rearranged, exactly like Firefox tabs&lt;/li&gt;
		&lt;li&gt;Can be restored, if closed accidently, by re-opening them from the Trash can&lt;/li&gt;
		&lt;li&gt;Can be locked, meaning that they can&amp;#8217;t be closed accidently&lt;/li&gt;
		&lt;li&gt;Can be duplicated&lt;/li&gt;
		&lt;li&gt;Can be saved in groups (sessions) and re-opened later on&lt;/li&gt;
		&lt;li&gt;Can be restored if Opera crashes&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Speed Dial&lt;/h3&gt;


	&lt;p&gt;When you open Opera for the first time, and &lt;em&gt;whenever you open a new empty tab&lt;/em&gt; the Speed Dial is displayed. What I originally thought it was one of the most annoying things introduced by Opera 9 turned out to be actually useful and very addictive.&lt;/p&gt;


	&lt;p&gt;The idea behind it is simple:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Show a default page with 9 slots&lt;/li&gt;
		&lt;li&gt;Allow users to drag links to those slots&lt;/li&gt;
		&lt;li&gt;Display preview of each slot (which is cached and can be updated by refreshing the page)&lt;/li&gt;
		&lt;li&gt;Allow users to quickly access pages saved in the Speed Dial via &lt;span class="caps"&gt;CTRL&lt;/span&gt;+1 .. &lt;span class="caps"&gt;CTRL&lt;/span&gt;+9 or simply by clicking them.

	&lt;p&gt;Simple and effective. Once you get going with it, you&amp;#8217;ll overcome the initial feeling of imposition and you&amp;#8217;ll use it more and more: I literally can&amp;#8217;t live without it now!&lt;/p&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Right-click goodies&lt;/h3&gt;


	&lt;p&gt;While I was testing Opera, my girlfriend came along and asked me to look something up on &lt;a href="http://www.imdb.com/"&gt;&lt;span class="caps"&gt;IMDB&lt;/span&gt;&lt;/a&gt;. I normally had &lt;span class="caps"&gt;IMDB&lt;/span&gt; as custom search engine in Firefox, but unfortunately Opera didn&amp;#8217;t seem to allow users to customize their search engines&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Totally wrong. Not only Opera lets you add any search engine to the search bar, it also does it with style and in the easiest way possible:&lt;/p&gt;


	&lt;p style="float:right"&gt;&lt;img src="/files/opera/search_engines.png" alt="" /&gt;&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Go to your search engine or any website with a search form&lt;/li&gt;
		&lt;li&gt;Right click the search field&lt;/li&gt;
		&lt;li&gt;Click &lt;strong&gt;Create Search&amp;#8230;&lt;/strong&gt;&lt;/li&gt;
		&lt;li&gt;Specify a name and a keyword for your search engine&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Done. You&amp;#8217;ll now be able to search that particular site directly from the search bar. As you can see, I added Wikipedia, &lt;span class="caps"&gt;IMDB&lt;/span&gt; and even the &lt;a href="http://www.uesp.net/wiki/Main_Page"&gt;Unofficial Elder Scrolls Pages&lt;/a&gt; in this way.&lt;/p&gt;


	&lt;p&gt;Besides creating searches, Opera lets you do a lot by right-clicking anywhere on a page:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Block Content&lt;/strong&gt;: Right-click an empty area of any webpage and select &lt;strong&gt;Block Content&lt;/strong&gt; to select which ads, scripts and images will be blocked from now on.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Validate&lt;/strong&gt;: Validate the &lt;span class="caps"&gt;HTML&lt;/span&gt; source code of the current page.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Translate&lt;/strong&gt;: Translate the current page into a foreign language with just two clicks.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Open With&lt;/strong&gt;: Open the current page in another browser installed on your system.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Edit Site Preferences&amp;#8230;&lt;/strong&gt;: Choose to block/allow cookies and popups, identify Opera as another browser, set a different encoding, enable/disable scripts, images, flash, etc. These setting apply to the &lt;em&gt;current web site only&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;View source, reload page every X seconds/minutes, send by email, etc.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Widgets&lt;/h3&gt;


	&lt;p&gt;&lt;a href="http://widgets.opera.com/"&gt;Opera Widgets&lt;/a&gt; must not be considered as Opera&amp;#8217;s counterpart to Firefox extensions. Instead, Opera Widgets can be used as &lt;em&gt;poor man&amp;#8217;s Vista Gadgets&lt;/em&gt; on Windows XP, and they do their job most remarkably.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;m personally very fond of these ones:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://widgets.opera.com/widget/3683/"&gt;The Free Dictionary&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://widgets.opera.com/widget/8461/"&gt;Wikipedia&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://widgets.opera.com/widget/3687/"&gt;Calendar&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://widgets.opera.com/widget/4513/"&gt;Whois Widget&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://widgets.opera.com/widget/3689/"&gt;Currency Converter&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://widgets.opera.com/widget/5118/"&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; Entities&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href="http://widgets.opera.com/widget/7206/"&gt;Twitter&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;They all have a common trait: they all behave as standalone programs, as they should be. The Wikipedia one, for example, can display Wikipedia entries directly inside the widget, unlike some others which just take you to Wikipedia, which is rather pointless.&lt;/p&gt;


	&lt;p&gt;Although widgets live within Opera, they can be displayed &amp;#8220;always behind&amp;#8221;, which means they&amp;#8217;ll be glued to your desktop and therefore will be visible whenever Opera and other applications are minimized.&lt;/p&gt;


	&lt;p&gt;Needless to say that anyone brave enough can make widgets for Opera by following a simple &lt;a href="http://dev.opera.com/articles/view/opera-widgets-specification-1-0/"&gt;Widget Specification&lt;/a&gt;.&lt;/p&gt;


	&lt;h3&gt;Everything you can do on the Internet&lt;/h3&gt;


	&lt;p&gt;The term &lt;em&gt;browser&lt;/em&gt; applied to Opera is somehow misleading. Personally I would have called it something like &amp;#8220;Internet Suite&amp;#8221;, because that would be a better choice due to the features it offers and the things it can do.&lt;/p&gt;


	&lt;p&gt;Traditionally speaking, a web browser can be used to browse web pages, read feeds (sometimes) and navigate through &lt;span class="caps"&gt;FTP&lt;/span&gt; directories. Here&amp;#8217;s what Opera can handle:&lt;/p&gt;


	&lt;p style="float:right"&gt;&lt;img src="/files/opera/files.png" alt="" /&gt;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Web Pages &amp;ndash; No need of explanations here.&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;FTP&lt;/span&gt; &amp;ndash; &lt;span class="caps"&gt;FTP&lt;/span&gt; directories are listed very clearly, overriding server&amp;#8217;s settings with a more user-friendly layout.&lt;/li&gt;
		&lt;li&gt;Local Files &amp;ndash; This was a surprise for me. Typing &lt;code&gt;file://&lt;/code&gt; will automatically load a list of the drives currently available on your machine. Similarly, auto-completion for directory and file names is supported! I almost started using Opera as my everyday&amp;#8217;s file manager (almost).&lt;/li&gt;
		&lt;li&gt;Feeds &amp;ndash; An embedded feed reader can be used to subscribe to &lt;span class="caps"&gt;RSS&lt;/span&gt;/Atom feeds and view them&amp;#8230; in a tab, of course.&lt;/li&gt;
		&lt;li&gt;E-mails &amp;ndash; Opera &lt;em&gt;is&lt;/em&gt; also a pretty decent email client. As of version 9.5 full &lt;span class="caps"&gt;IMAP&lt;/span&gt; support has been added, which definitely makes the difference.&lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;IRC&lt;/span&gt; &amp;ndash; Opera can be used as an client, which works pretty well. Who needs ChatZilla anymore?&lt;/li&gt;
		&lt;li&gt;News &amp;ndash; Opera can be used to signup and retrieve news from newsgroups.&lt;/li&gt;
		&lt;li&gt;Gopher/WAIS &amp;ndash; Although not used everyday, Opera can handle these old protocols as well.&lt;/li&gt;
		&lt;li&gt;BitTorrent Files &amp;ndash; By default, Opera can act as a BitTorrent client as well, so you can just open .torrent files through the program and then monitor the download progress in the Transfers window, like with any other normal download. While this feature is indeed useful, it is also possible to &lt;a href="http://www.opera.com/support/search/view/840/"&gt;disable it&lt;/a&gt; and still use your favorite BitTorrent client.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Portability and Synchronization&lt;/h3&gt;


	&lt;p&gt;Let&amp;#8217;s spend some words about &lt;em&gt;portability&lt;/em&gt;. Sure, there are two &amp;#8220;Portable Opera&amp;#8221; apps out there, and they work well enough, but one thing I&amp;#8217;d like about a web browser is the ability to synchronize my preferences, customizations, themes, passwords etc. etc. across multiple computers. 
Firefox is &lt;a href="http://labs.mozilla.com/2007/12/introducing-weave/"&gt;getting there&lt;/a&gt;, although the technology is still at a very early stage.
Opera is doing something similar through &lt;a href="http://link.opera.com/"&gt;Opera Link&lt;/a&gt;, which allows you to synchronize automatically your Bookmarks, your Personal Bar and your Speed Dial. All you need is to get a (free) Opera account, login to Opera Link and enable the synchronization feature from the &lt;em&gt;File&lt;/em&gt; menu. From now on every time you&amp;#8217;ll modify your Speed Dial or Bookmarks, the changes will be sent to your Opera Link page. Similarly, whenever you start using opera somewhere else, if you login to your Opera Account you should be able to synchronize your Bookmarks and Speed Dial.&lt;/p&gt;


	&lt;p&gt;Here are some thoughts on this type of technology:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;It&amp;#8217;s not totally private yet. While it&amp;#8217;s great to be able to sync bookmarks and speed dial, the problems arise when you finish using your friend&amp;#8217;s computer for example&amp;#8230; what happens to the bookmarks you just sync&amp;#8217;ed? The only way to delete them would be to have your friend to log in to his Opera account and re-sync them. Not enough privacy for my liking.&lt;/li&gt;
		&lt;li&gt;Your passwords, notes, widgets, etc. etc. cannot be synchronized yet, but that will hopefully be possible in near future.&lt;/li&gt;
		&lt;li&gt;Sync&amp;#8217;ing bookmarks is pointless for me. Although Opera still hopes to compete with Del.icio.us &amp;#38; Co., that will be very hard to achieve. I stopped using in-browser bookmarks long ago. &lt;/li&gt;
		&lt;li&gt;Link seems and interesting feature considering that Opera is available on virtually &lt;em&gt;any operating system&lt;/em&gt; and a lot of different devices (mobile phones, Nintendo DS &amp;#38; Wii, &amp;#8230;).&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;At any rate, it is still possible to &amp;#8220;carry around&amp;#8221; your personal opera settings by following the instructions provided on &lt;a href="http://help.opera.com/Windows/9.50/en/backup.html"&gt;this page&lt;/a&gt; which explains pretty much everything you need to know aboud Opera files and local storage.&lt;/p&gt;


	&lt;h3&gt;Advanced Features&lt;/h3&gt;


	&lt;p&gt;Opera looks more &amp;#8220;polished up&amp;#8221; than Firefox in most cases. The superb usage of tabs for nearly everything is one example, and another one is the possibility to apply skins (themes) on-the-fly, without having to restart the browser. 
Firefox &lt;em&gt;can&lt;/em&gt; do this via the &lt;a href="http://labs.mozilla.com/2007/12/personas-for-firefox/"&gt;Personas&lt;/a&gt; extension, but Opera had this built-in for a long time.&lt;/p&gt;


	&lt;p&gt;To apply a new skin:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Go to the &lt;a href="http://my.opera.com/community/customize/skins/"&gt;Skins Directory&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Download a skin you like&lt;/li&gt;
		&lt;li&gt;Opera will download and apply the skin immediately, &lt;strong&gt;and it will ask you whether you want to keep it or not&lt;/strong&gt;. If you choose not to, it won&amp;#8217;t save it in your profile (very useful for quick previews). Neat.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Another quality opera always excelled to is accessibility. Besides using the interface in the traditional way, it is also possible to:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Use &lt;a href="http://www.opera.com/products/desktop/mouse"&gt;mouse gestures&lt;/a&gt;&lt;/strong&gt; &amp;ndash; I wasn&amp;#8217;t a big fan of this until I bothered reading the excellent documentation Opera provided for them (which is significantly better than &lt;a href="http://www.mousegestures.org/"&gt;the Firefox&amp;#8217;s equivalent&lt;/a&gt;). It can be quite useful at times.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Use &lt;a href="http://www.opera.com/products/desktop/keyboard/"&gt;keyboard shortcuts&lt;/a&gt;&lt;/strong&gt; &amp;ndash; Believe it or not, you can literally &lt;a href="http://www.opera.com/support/tutorials/nomouse/"&gt;use Opera without a mouse&lt;/a&gt;.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;&lt;a href="http://www.opera.com/products/desktop/voice/"&gt;Speak&lt;/a&gt; to it&lt;/strong&gt; &amp;ndash; Opera&amp;#8217;s voice integration is getting better and better. Not only you can effectively &lt;a href="http://www.opera.com/support/tutorials/voice/"&gt;tell your browser what to do&lt;/a&gt;, you can also use the built-in text-to-speech function (Windows only) to have it read entire pages for you. It actually works quite well and it can parse punctuation well enough to apply the right intonation. Just for fun, I had it read it an Italian page&amp;#8230; and it actually worked as expected: it was like listening to an American reading an Italian text using US pronuntiation!&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Finally, power users will be delighted of the way opera lets you hack the program settings, as you can:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Use &lt;strong&gt;Tools &amp;gt; Quick Preferences&lt;/strong&gt; to block/unblock popups, cookies, Java applets, images, etc.&lt;/li&gt;
		&lt;li&gt;Use &lt;strong&gt;Tools &amp;gt; Advanced&lt;/strong&gt; to access detailed information concerning cookies, cache (it lists every image/object cached!), plug-ins, Wand passwords, etc.&lt;/li&gt;
		&lt;li&gt;Use &lt;strong&gt;Tools &amp;gt; Appearence&amp;#8230;&lt;/strong&gt; to access and manage appearance-related settings, like skins, toolbars, buttons and panels&lt;/li&gt;
		&lt;li&gt;Use &lt;strong&gt;Tools &amp;gt; Preferences&amp;#8230;&lt;/strong&gt; to access general preferences (all the rest)&lt;/li&gt;
		&lt;li&gt;Type in &lt;strong&gt;opera:config&lt;/strong&gt; to view and tweak Opera&amp;#8217;s internal settings, somehow like Firefox&amp;#8217;s about:config, but much cleaner and easier to use.&lt;/li&gt;
		&lt;li&gt;Download the &lt;strong&gt;&lt;a href="http://dev.opera.com/tools/"&gt;Developer Console&lt;/a&gt;&lt;/strong&gt; to have a simpler alternative to Firefox&amp;#8217;s Web Developer Toolbar extension, to view &lt;span class="caps"&gt;DOM&lt;/span&gt; elements, &lt;span class="caps"&gt;CSS&lt;/span&gt; and Javascript information.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Annoyances&lt;/h3&gt;


	&lt;p&gt;After using as main browser for a few weeks now, I can say that it&amp;#8217;s great but not perfect yet. It&amp;#8217;s very advanced, faster and more mature than any other browser, of course,but there are a few things which should be fixed or improved.&lt;/p&gt;


	&lt;p&gt;In particular:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;It&amp;#8217;s not open source&lt;/strong&gt; &amp;ndash; This may not matter to someone, but some people consider this an essential requirement for their browser, and that&amp;#8217;s why Firefox is their most obvious choice. Although Opera is free, it is proprietary software after all, which means is definitely not as open as you may want it to be. Personally I&amp;#8217;m not too bothered, as I&amp;#8217;m starting to think that too much openness may lead to too many unuseful and bloated extensions and make the program somehow &amp;#8220;unpredictable&amp;#8221; and heavy.&lt;/li&gt;
		&lt;li&gt;&lt;del&gt;&lt;strong&gt;No address bar search&lt;/strong&gt; &amp;ndash; Amazingly, only Firefox seems to have this feature built-in. I&amp;#8217;m referring to the ability to type whatever in the address bar to be redirected to the site returned by a Google&amp;#8217;s &lt;em&gt;I&amp;#8217;m feeling lucky&lt;/em&gt; search. It is possible to emulate this feature in Opera by creating a custom search for &lt;em&gt;I&amp;#8217;m Feeling Lucky&lt;/em&gt; and assign it a short keyword like &amp;#8220;l&amp;#8221;. In this way, for example, typing in &lt;code&gt;l h3rald&lt;/code&gt; should lead you to this website. Not quite as immediate as in Firefox though.&lt;/del&gt;&lt;/li&gt;
		&lt;li&gt;&lt;del&gt;&lt;strong&gt;No find as you type&lt;/strong&gt; &amp;ndash; Another big disappointment for who comes from Firefox or Safari: Opera still uses a dialog box to perform page searches.&lt;/del&gt;&lt;/li&gt;
		&lt;li&gt;&lt;del&gt;&lt;strong&gt;No spell clecking&lt;/strong&gt; &amp;ndash; Again, both Firefox and Safari now offer text fields spell checking. Opera doesn&amp;#8217;t yet.&lt;/del&gt;&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;No &lt;span class="caps"&gt;HTML&lt;/span&gt; mail composer&lt;/strong&gt; &amp;ndash; Opera&amp;#8217;s built-in mail client can display &lt;span class="caps"&gt;HTML&lt;/span&gt; emails but doesn&amp;#8217;t yet allow users to create them.&lt;/li&gt;
		&lt;li&gt;&lt;del&gt;&lt;strong&gt;Auto-start widgets?&lt;/strong&gt; &amp;ndash; This is a feature enhancement Opera Dev Team should consider: allow users to configure certain widgets to start automatically when Opera starts.&lt;/del&gt;&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Google Reader + Flash problems&lt;/strong&gt; &amp;ndash; Sometimes I experiences some scrolling problems when reading news which contain embedded flash movies on Google Reader.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Corporate Sites&lt;/strong&gt; &amp;ndash; Unfortunately some corporate web site do not support Opera or are not displayed correctly in Opera. Unfortunately there&amp;#8217;s nothing much we can do about it but trying to &amp;#8220;mask&amp;#8221; Opera as another browser (via &lt;strong&gt;right-click &amp;gt; Edit Site Preferences&amp;#8230;&lt;/strong&gt;)&lt;/li&gt;
		&lt;li&gt;&lt;del&gt;&lt;strong&gt;Default Browser Problems&lt;/strong&gt; &amp;ndash; Setting Opera as default browser on Windows doesn&amp;#8217;t seem to set the file icons accordingly (or worse, it resets them to the default file icon).&lt;/del&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;strong&gt;&lt;span class="caps"&gt;ERRATA&lt;/span&gt;:&lt;/strong&gt;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;It is possible to have Opera to redirect you to the right after typing a few words in thr address bar by setting Google&amp;#8217;s &amp;#8220;I&amp;#8217;m feeling lucky&amp;#8221; as default search engine &lt;em&gt;(thanks &lt;strong&gt;&lt;span class="caps"&gt;EJ902&lt;/span&gt;&lt;/strong&gt;)&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;Spell Checking is &lt;a href="http://www.opera.com/support/tutorials/opera/spellcheck/"&gt;supported&lt;/a&gt; via &lt;span class="caps"&gt;GNU&lt;/span&gt; Aspell &lt;em class="thanks &lt;strong :redsh" id="109:&gt;cvm&lt;/strong&gt;&amp;#8220;&gt;_ or by using &lt;a href="http://opera.gt500.org/ospell/"&gt;Ospell&lt;/a&gt; for inline spell checking _(thanks &lt;strong&gt;Dava&lt;/strong&gt;)&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;Find as you type can be triggered by pressing &lt;code&gt;.&lt;/code&gt; and typing &lt;em&gt;(thanks &lt;strong&gt;cvm&lt;/strong&gt;)&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;It is possible to auto-start widgets by saving a session with all your widget open and reloading it at every startup [CTRL+F12 &amp;gt; General &amp;gt; Startup &amp;gt; Continue saved sessions] &lt;em&gt;(thanks &lt;strong&gt;Tamil&lt;/strong&gt; &amp;#38; &lt;strong&gt;Ameer&lt;/strong&gt;)&lt;/em&gt;.&lt;/li&gt;
		&lt;li&gt;As of the &lt;a href="http://my.opera.com/desktopteam/blog/"&gt;latest snapshot&lt;/a&gt;, setting Opera as default browser and handler for &lt;span class="caps"&gt;HTML&lt;/span&gt; files doesn&amp;#8217;t cause any problems &lt;em&gt;thanks &lt;strong&gt;Ayush&lt;/strong&gt;)&lt;/em&gt;.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h3&gt;Conclusion&lt;/h3&gt;


	&lt;p&gt;Despite the few annoyances listed in the previous section, Opera 9.5 beta 1 truly impressed me. I was waiting for Opera to get better before switching and now I&amp;#8217;ve not been using Firefox for a few weeks.
Although Opera offers a lot of features, there&amp;#8217;s still room for improvements, especially for what concerns integration with third party services: I would really like to see some sort of integration with del.icio.us, and that could be possible via widgets at least. 
Regarding the new Opera Link feature, it looks very promising and a potential competitor for Mozilla Weave even though it will be used mainly to get more and more users to register to the Opera community (I did, at least), which is indeed very active any way.&lt;/p&gt;


	&lt;p&gt;To conclude this article, which still barely scratches the surface of this very powerful application, I&amp;#8217;d like to praise two more things about Opera:&lt;/p&gt;


	&lt;p&gt;&lt;span style="float:right; margin:3px;"&gt;
&lt;script type="text/javascript"&gt;
digg_url = &amp;#8216;http://digg.com/software/A_Firefox_Lover_s_Guide_to_Opera&amp;#8217;;
&lt;/script&gt;
&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;/span&gt;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Their website network, and in particular their truly excellent documentation knowledge base, which is very comprehensive of references, tutorials and interesting articles. I am a full time technical writer myself, and I&amp;#8217;ve hardly ever come across better documentation.&lt;/li&gt;
		&lt;li&gt;Their extensive &lt;a href="http://www.opera.com/docs/specs/"&gt;support and compliance to web standards&lt;/a&gt;, which makes Opera the most advanced browser ever made.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;If you&amp;#8217;ve not tried Opera before, or if you&amp;#8217;ve always dismissed it because &amp;#8220;X browser is better&amp;#8221;, you may want to &lt;a href="http://www.opera.com/products/desktop/"&gt;give it another shot&lt;/a&gt;: for me it was definitely worthwhile!&lt;/p&gt;</description>
      <pubDate>Fri, 28 Dec 2007 14:19:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:8d31c3da-549a-41be-9db4-4c699acd102c</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/articles/firefox-lovers-guide-to-opera</link>
      <category>Articles</category>
      <category>browsers</category>
      <category>review</category>
      <category>software</category>
      <category>Opera</category>
      <category>Firefox</category>
      <category>IE</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/149</trackback:ping>
    </item>
    <item>
      <title>Beware of sudden upgrades!</title>
      <description>&lt;p&gt;Yesterday I got a rather annoying early Christmas present: when visiting my site, I noticed that the raw source code of my dispatch.fcgi file (yes, I&amp;#8217;m on shared hosting with FastCGI, for now) was displayed &amp;#8220;as it is&amp;#8221; instead of being interpreted.&lt;/p&gt;


	&lt;p&gt;After the initial moment of anger and stress (I immediately realized it was BlueHost&amp;#8217;s fault, not mine), I opened two tickets and went to bed, hoping to see everything solved in the morning.&lt;/p&gt;


	&lt;p&gt;Unluckily it wasn&amp;#8217;t the case, so I posted on BlueHost forum trying to be as polite as possible complaining because the issue wasn&amp;#8217;t being dealt with. It turns out that for such issues you&amp;#8217;re supposed to use the &amp;#8220;Live Chat&amp;#8221; feature instead of the tickets, so that&amp;#8217;s what I did.&lt;/p&gt;


	&lt;p&gt;After a quick chat with &amp;#8220;Christian&amp;#8221;, it turns out that BlueHost decided to perform a server upgrade &amp;#8220;silently&amp;#8221; upgrading to Apache2, &lt;span class="caps"&gt;PHP5&lt;/span&gt;, MySQL4.1, etc. etc.
Cool, pity that nobody told me that!&lt;/p&gt;


	&lt;p&gt;I was expecting some sort of &lt;span class="caps"&gt;PHP&lt;/span&gt; upgrade (not that I care like that), which was supposed to happen according to the last BlueHost newsletter:&lt;/p&gt;


&lt;blockquote&gt;
&lt;em&gt;&amp;#8220;To alleviate any issues in the future with certain scripts that only run on one
version of &lt;span class="caps"&gt;PHP&lt;/span&gt; we have developed the ability to run &lt;span class="caps"&gt;PHP4&lt;/span&gt; and &lt;span class="caps"&gt;PHP5&lt;/span&gt; on the same server
simultaneously. This will be rolled out to all users in the next couple of weeks. Some
servers already have this ability while most will see it in the next two weeks.&amp;#8221;&lt;/em&gt;
&lt;/blockquote&gt; 

	&lt;p&gt;But&amp;#8230; hang on? Does it say anything about migrating to Apache2? I don&amp;#8217;t think so! What&amp;#8217;s worse, is that quite a few things changed with Apache2, in particular the way FastCGI handlers are declared:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;# Apache 1.3:
AddHandler fastcgi-script .fcgi

# Apache 2:
AddHandler fcgid-script .fcgi&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;See? Different. This is due to the fact that &lt;a href="http://wiki.rubyonrails.org/rails/pages/Debian+mod_fastcgi+Notes"&gt;&lt;code&gt;mod_fcgid&lt;/code&gt; is used instead of &lt;code&gt;mod_fastcgi&lt;/code&gt; on Apache 2&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The fix was easy, of course, and now my site is up and running again (and actually running faster)&amp;#8230; but, I wonder, why the hell wasn&amp;#8217;t I informed? Is it acceptable? It sounds like I might end up on a &lt;span class="caps"&gt;VPS&lt;/span&gt; sooner than expected, unless BlueHost doesn&amp;#8217;t roll out some new exciting feature soon, as I think it might&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Thu, 20 Dec 2007 07:41:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c033d1c9-f0f1-4990-a37c-5c80fec26a90</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/blog/apache2-upgrade</link>
      <category>Blog</category>
      <category>website</category>
      <category>Rails</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/146</trackback:ping>
    </item>
    <item>
      <title>Announcement: RedBook v0.5.0 released</title>
      <description>&lt;p&gt;This new beta release of RedBook introduces quite a few changes when it comes to configuration and setup. Here&amp;#8217;s some highlights&amp;#8230;&lt;/p&gt;


	&lt;h3&gt;Regexp changes&lt;/h3&gt;


	&lt;p&gt;It is now necessary to enter &amp;#8220;proper&amp;#8221; regular expressions for &lt;code&gt;:select&lt;/code&gt;. Proper means between slashes, like the following:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;/Work Day/&lt;/li&gt;
		&lt;li&gt;/mail/i&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;I changed this in order to support case-insensitive searches using the &lt;code&gt;i&lt;/code&gt; switch. This makes queries much more powerful.&lt;/p&gt;


	&lt;h3&gt;Variables&lt;/h3&gt;


	&lt;p&gt;A new, interesting feature I decided to introduce in this release is &lt;em&gt;variables&lt;/em&gt;. For now you define them inside your rbconfig.yml file, like this:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;:var_monday_morning: &amp;quot;monday at 8 am&amp;quot;

:var_friday_evening: &amp;quot;friday at 8 pm&amp;quot;

:var_week_report: &amp;quot;:select :duration :from :%monday_morning :to :%friday_evening&amp;quot; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;In this way, every time you type in :%week_report in RedBook, it will expand to: &lt;code&gt;:select :duration :from monday at 8 am :to friday at 8 pm&lt;/code&gt;. By the way, completion is supported, so you&amp;#8217;ll only have to type in something like &lt;code&gt;:%we&lt;/code&gt; and hit &lt;tab&gt;.&lt;/p&gt;


	&lt;p&gt;It is possible to define variables as &lt;code&gt;:var_&amp;lt;something&amp;gt;&lt;/code&gt; in the rbconfig.yml file and then used them inside RedBook as &lt;code&gt;:%&amp;lt;something&amp;gt;&lt;/code&gt;.&lt;/p&gt;


	&lt;h3&gt;New Operations&lt;/h3&gt;


	&lt;p&gt;Five new operations have been added:&lt;/p&gt;


	&lt;h4&gt;:blank&lt;/h4&gt;


	&lt;p&gt;This will blank your current log after asking you if you really want to do so.&lt;/p&gt;


	&lt;h4&gt;:restore&lt;/h4&gt;


	&lt;p&gt;This operation will overwrite your current log with the last saved backup. Like with the &lt;code&gt;:blank&lt;/code&gt; operation, you&amp;#8217;re asked if you really want to proceed or not.&lt;/p&gt;


	&lt;h4&gt;:archive&lt;/h4&gt;


	&lt;p&gt;By typing &lt;code&gt;:archive&lt;/code&gt;, the current log file will be archived to your &lt;code&gt;:archives_folder:&lt;/code&gt; directory specified in the rbconfig.yml file (similarly, it is now possible to specify a :backups_folder: for your logs&amp;#8217; backup files).&lt;/p&gt;


	&lt;h4&gt;:dataset&lt;/h4&gt;


	&lt;p&gt;A simple operation to display the messages inthe current dataset.&lt;/p&gt;


	&lt;h4&gt;:dump&lt;/h4&gt;


	&lt;p&gt;This operation will dump the output of the last &lt;code&gt;:select&lt;/code&gt; operation to a text file. Useful for saving the average, total time and duration of a set of activities.&lt;/p&gt;


	&lt;h3&gt;Portable edition&lt;/h3&gt;


	&lt;p&gt;Some Windows users will definitely love this. I finally found an easy way to run RedBook confined within the current directory, by using a simple &lt;code&gt;start.bat&lt;/code&gt; batch file to set the &lt;span&gt;&lt;span class="caps"&gt;INPUTRC&lt;/span&gt;&lt;/span&gt; and &lt;span&gt;&lt;span class="caps"&gt;HOME&lt;/span&gt;&lt;/span&gt; variables temporarily to the path to the .inputrc file and the directory of RedBook executable. This makes RedBook 100% portable and suitable to be used on &lt;span class="caps"&gt;USB&lt;/span&gt; sticks &amp;#38;similar.&lt;/p&gt;


	&lt;p style="text-align:center;"&gt;&lt;strong&gt;&lt;a href="http://redbook.googlecode.com/files/RedBook-0.5_Win32-portable.zip"&gt;Get RedBook Portable&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;


	&lt;h3&gt;New Development Page&lt;/h3&gt;


	&lt;p&gt;I decided to move the primary RedBook repository from &lt;a href="http://www.assembla.org"&gt;Assembla&lt;/a&gt; to Google Code. Why? Well, nothing wrong with Assembla per se, I still think it&amp;#8217;s an excellent free service to host your public &lt;em&gt;and private&lt;/em&gt; projects, but Google Code is faster and offers only the features I need:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Public &lt;span class="caps"&gt;SVN&lt;/span&gt; repository access&lt;/li&gt;
		&lt;li&gt;Simple-to-use issue tracker&lt;/li&gt;
		&lt;li&gt;Very nicely developed downloads section, with download counts, and &amp;#8220;normal&amp;#8221; filenames.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So here&amp;#8217;s the new RedBook Development Home:&lt;/p&gt;


	&lt;p style="text-align:center;"&gt;&lt;strong&gt;&lt;a href="http://code.google.com/p/redbook/"&gt;http://code.google.com/p/redbook/&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Additionally I also setup a &lt;a href="http://groups.google.com/group/redbook-support/"&gt;RedBook Support Google Group&lt;/a&gt;, so if you have any question concerning the program, you know where to go!&lt;/p&gt;</description>
      <pubDate>Sun, 16 Dec 2007 08:07:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:e1a7f2c4-2e24-4e6c-b8f2-4deed6504804</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/blog/redbook-050-released</link>
      <category>Blog</category>
      <category>OpenSource</category>
      <category>productivity</category>
      <category>redbook</category>
      <category>ruby</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/145</trackback:ping>
    </item>
    <item>
      <title>Book Review: Mongrel Digital Shortcut</title>
      <description>&lt;p&gt;If you ever considered about developing an deploying a Rails application in the last year or so, you must have heard of &lt;a href="http://mongrel.rubyforge.org/index.html"&gt;Mongrel&lt;/a&gt; before. If you didn&amp;#8217;t, I&amp;#8217;d recommend you learn more about it because up to now it proved to be one of the few essential ingredients for deploying &lt;em&gt;scalable&lt;/em&gt; Rails applications.&lt;/p&gt;


	&lt;p&gt;Mongrel is a creation of &lt;a href="http://www.zedshaw.com/"&gt;Zed Shaw&lt;/a&gt; who started writing a replacement for FastCGI to use with Rails, and ended up creating a brand new, &lt;span class="caps"&gt;HTTP&lt;/span&gt; web server who turned out to be one of the best things the Rails community ever saw happening.&lt;/p&gt;


	&lt;p&gt;It was created to be simple to use and configure, nevertheless it &lt;em&gt;does&lt;/em&gt; require some skill to set it up and tune it. Documentation is there, along with plenty of blog posts, but there&amp;#8217;s also an interesting &lt;a href="http://www.informit.com/store/product.aspx?isbn=0321483502&amp;#38;rl=1"&gt;book&lt;/a&gt; from &lt;a href="http://www.awprofessional.com/"&gt;Addison Wesley Professional&lt;/a&gt; which is definetely worth a read.&lt;/p&gt;


	&lt;p style="float:right"&gt;&lt;img src="/files/mongrel_shortcut.jpeg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;&amp;#8220;Mongrel: Serving, Deploying, and Extending Your Ruby Applications&amp;#8221; &amp;ndash; that&amp;#8217;s the title of the book. A &lt;em&gt;Digital Shortcut&lt;/em&gt;, 100-odd pages long, in &lt;em&gt;landscape&lt;/em&gt; format to make it easier to read on a computer, straight to the point with no added sugar for just 15$ (PDF only). I must say Addison Wesley got it right: the book&amp;#8217;s format is, as a matter of fact, &lt;em&gt;optimized for web developers&lt;/em&gt;, especially those who can&amp;#8217;t afford to read a 500-pages book covering everything about a subject just to find that one thing they don&amp;#8217;t know about.
This &lt;em&gt;shortcut&lt;/em&gt; can be seen, essentially, as an expanded cheatsheet which will teach you the basics about Mongrel and also give you plenty of advice on how to learn more about it.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s have a closer look at it.&lt;/p&gt;


	&lt;h3&gt;Overview, Introduction &amp;#38; Getting Started&lt;/h3&gt;


	&lt;p&gt;The first three &lt;del&gt;chapters&lt;/del&gt; sections (there are no chapters, just &lt;em&gt;sections&lt;/em&gt;) of the book are meant to be a gentle introduction to Mongrel and its world. The main author is &lt;a href="http://www.informit.com/authors/bio.aspx?a=0260912e-6ed8-4ed1-882a-c357e644feec"&gt;Matt Pelletier&lt;/a&gt;, but Zed Show&amp;#8217;s contributions are definitely one of the book&amp;#8217;s best selling points. 
Zed&amp;#8217;s thoughts are scattered here and there in many &lt;em&gt;sidebars&lt;/em&gt; throughout the book (there&amp;#8217;s at least one in each section): you&amp;#8217;ll see an odd-looking face (Zed&amp;#8217;s self-caricature) with some text next to it; when you read it, you&amp;#8217;ll notice that they are &lt;em&gt;actually&lt;/em&gt; Zed&amp;#8217;s own thoughts, straight from his mind, with no editorial filter whatsoever in-between. 
Be warned: the text included within the &lt;strong&gt;Zed Sez&lt;/strong&gt; sidebars is highly opinionated, that&amp;#8217;s precisely what Zed &lt;em&gt;feels&lt;/em&gt; to say about something, and he&amp;#8217;ll just say it: just the plain, simple thoughts of an experienced programmer. As the author explains in &lt;strong&gt;Section 1&lt;/strong&gt;: &lt;em&gt;&amp;#8220;[&amp;#8230;] You may not agree with everything he says, but you probably should.&amp;#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Section 2&lt;/strong&gt; is a general introduction about Mongrel. It explains &lt;em&gt;what&lt;/em&gt; it is, &lt;em&gt;when&lt;/em&gt; and &lt;em&gt;why&lt;/em&gt; it was made, and &lt;em&gt;how&lt;/em&gt; it works. There&amp;#8217;s nothing new to learn if you already used Mongrel before, probably, but it&amp;#8217;s definitely the first thing to show to someone who&amp;#8217;s new to Mongrel and its world, and possibly a bit skeptical about it. 
The last subsection &lt;em&gt;&amp;#8220;What can Mongrel do for me&amp;#8221;&lt;/em&gt; is an attempt to &lt;del&gt;brainwash&lt;/del&gt; persuade you to fully embrace Mongrel and its philosophy, whether you are a developer, a sysadmin or even a manager: assertions like &lt;em&gt;&amp;#8220;Mongrel is pretty damned secure.&amp;#8221;&lt;/em&gt; and &lt;em&gt;&amp;#8220;Mongrel&amp;#8217;s license is capitalist-friendly.&amp;#8221;&lt;/em&gt; will definitaly make some of you (managers) happy.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Section 3&lt;/strong&gt; is slightly more juicy than the previous one, as it explains how to install and use Mongrel. Basically that&amp;#8217;s what everyone who ever used it already knows, but it&amp;#8217;s still necessary for the book&amp;#8217;s consistency, after all. After reading this section, you&amp;#8217;ll probably have your first Mongrel up and running and serving your little Rails application&amp;#8217;s pages, and you&amp;#8217;ll begin to wonder why the hell you need to keep reading this book now that everything seems to work already&amp;#8230;&lt;/p&gt;


	&lt;h3&gt;Section 4: Configurations&lt;/h3&gt;


	&lt;p&gt;&amp;#8230;aka &amp;#8220;a truly useful Mongrel cheatsheet&amp;#8221;. This section dives deep(er) into Mongrel&amp;#8217;s configuration by explaining what each start parameter does in detail. The parameters are presented in tabular form in a very well-organized way. As you would expect from an high-quality cheatsheet.&lt;/p&gt;


	&lt;p&gt;Then the author will explore a few commonly used deployment scenarios, in particular:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Standalone&lt;/strong&gt; &amp;ndash; The simplest configuration possible, with just one Mongrel instance serving both static and dynamic pages.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;mongrel&amp;#95;cluster&lt;/strong&gt; &amp;ndash; How to use &lt;em&gt;&amp;#8220;a pack of mongrels&amp;#8221;&lt;/em&gt; together to handle more traffic.&lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Behind a static web server&lt;/strong&gt; &amp;ndash; The most common (and most scalable) option, used to serve static content faster using a front-end server and use Mongrel only to handle Ruby pages.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Towards the end of the section, for the developer&amp;#8217;s delight, the author will discuss two common, useful scenarios where Mongrel can be used:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;Apache 2 + mod_proxy_balancer + mongrel&amp;#95;cluster&lt;/strong&gt; &lt;/li&gt;
		&lt;li&gt;&lt;strong&gt;Nginx + mongrel&amp;#95;cluster&lt;/strong&gt;&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;The difference here is that detailed instructions are provided on how to setup and configure each server, including example file sources. This can be particularly useful for the Nginx example, as most of the documentation for this fantastic, lightweight Mongrel fron-end is scattered around the web (or written in Russian in a &lt;a href="http://sysoev.ru/nginx/"&gt;well known place&lt;/a&gt;).&lt;/p&gt;


	&lt;h3&gt;Section 5: Production Deployment&lt;/h3&gt;


	&lt;p&gt;This section introduces one of the most important part of the life cycle of a Rails application: the deployment on a production server. The author is pretty honest about the whole subject:&lt;/p&gt;


&lt;blockquote&gt;
&lt;em&gt;&amp;#8220;You will not do this in a day. If you are expecting to code until 1 minute before your deadline and then simply point and click and have an instant server then you need to take some kind of
medication because you are violently hallucinating. You will need at least a week of 8 hours days to make sure your first deployment works and to have the time to do it right.&amp;#8221;&lt;/em&gt;
&lt;/blockquote&gt;

	&lt;p&gt;Sounds terribly true. Especially for larger projects demanding good performance under heavy traffic. Scared? Probably, if you never deployed a Rails application &amp;#8220;properly&amp;#8221; before, but at least the book comes to the rescue by providing an overview of what you need to perform a deployment and why it is such a complex and delicate process.&lt;/p&gt;


	&lt;p&gt;Not only this, but also a &amp;#8220;Best Practices Rubric&amp;#8221; is also provided for the developer&amp;#8217;s own private enjoyement. It&amp;#8217;s written as a list of questions like:&lt;/p&gt;


	&lt;p&gt;&lt;em&gt;11. Do you have a shared location where you can document the deployment, such as a Wiki or &lt;span class="caps"&gt;CMS&lt;/span&gt;?&lt;/em&gt;
&lt;em&gt;12. Do you know how to use httperf or ab and know what the statistics mean?&lt;/em&gt;&lt;/p&gt;


	&lt;p&gt;After these 13 questions, the author provides the key to give a meaning to your answers:&lt;/p&gt;


&lt;blockquote&gt;
&lt;em&gt;&amp;#8220;For each question you answer with &amp;#8220;NO&amp;#8221;, add 10 hours to your time estimate for completion. This may seem unrealistic, since saying &amp;#8220;NO&amp;#8221; to everything means it&amp;#8217;ll take 190 hours (about one
month), but this estimate is actually low according to most first deployment experiences.&amp;#8221;&lt;/em&gt;
&lt;/blockquote&gt;

	&lt;p&gt;If you answered &amp;#8220;NO&amp;#8221; too many times to these questions, you may want to read on through the next subsection which states 17 &amp;#8220;worst practices&amp;#8221;: an invaluable read for beginners!&lt;/p&gt;


	&lt;p&gt;But after all this section is not only about stating the obvious (&amp;#8230;right?): a full example scenario is describedand examined throughly to give you an idea of how a deployment &lt;em&gt;should&lt;/em&gt; be made, using three different machines:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;One for Apache (as a front-end to Mongrel)&lt;/li&gt;
		&lt;li&gt;One for the Mongrel cluster and the Rails application&lt;/li&gt;
		&lt;li&gt;One for the database&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Maybe something you&amp;#8217;ll never do if you just want to run your grandma&amp;#8217;s site on Rails, but certainly something you may want to start looking at if your grandma becomes really popular and your small server gets grounded by several thousands of visitors per day.&lt;/p&gt;


	&lt;p&gt;The last part of the section will give you a brief introduction on monitoring your applications and on which tools you should be using, although it does not discuss the subject in detail at all, it&amp;#8217;s just meant to point you to the right direction.&lt;/p&gt;


	&lt;h3&gt;Section 6: Extending Mongrel&lt;/h3&gt;


	&lt;p&gt;This section digs deeper into the software code internals and describes &lt;em&gt;how to teach new tricks to your Mongrel&lt;/em&gt;, i.e. how to extend its functionality.&lt;/p&gt;


	&lt;p&gt;Before you begin, though, don&amp;#8217;t forget what Zed himself has to say about Mongrel&amp;#8217;s simplicity:&lt;/p&gt;


&lt;blockquote&gt;
&lt;em&gt;&amp;#8220;I&amp;#8217;ve always had a different aesthetic sense when I write my software. I value simplicity and directness and try to write software that follows this approach. I jokingly call it the Shibumi School of Software Structure. All I do is apply this rule: When given two possible designs with equal end results, pick the simpler one. I then ruthlessly strip the solution down to its finest elements, but no more.&amp;#8221;&lt;/em&gt;
&lt;/blockquote&gt;

	&lt;p&gt;Mongrel&amp;#8217;s architecture is not that complex, and this section is sufficient to get you started by providing an overview of the main classes involved (HttpServer, HttpRequest, HttpResponse, HttpHandler, URIClassifier), and how they work together.
Note that the book won&amp;#8217;t describe anything about the APIs of these classes. but after all, the project&amp;#8217;s &lt;a href="http://mongrel.rubyforge.org/rdoc/files/README.html"&gt;RDoc documentation&lt;/a&gt; should cover all the details you need.&lt;/p&gt;


	&lt;p&gt;The rest of the section focuses on how to extend Mongrel, by:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Writing custom handlers in Ruby&lt;/li&gt;
		&lt;li&gt;Creating custom filters to perform security checks, clean up requests and preliminary file processing&lt;/li&gt;
		&lt;li&gt;Creating plugins and distributing them as rubygems&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Two working examples are also provided:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;An example handler to deflate content (if the browser supports deflate)&lt;/li&gt;
		&lt;li&gt;An example &amp;#8220;duck&amp;#8221; plugin, to make Mongrel quack like a duck when it&amp;#8217;s started (not the most useful thing in the world, but serves the purpose)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h2&gt;Debugging, Performance &amp;#38; Security&lt;/h2&gt;


	&lt;p&gt;The last three sections deals with other important aspects concerning the deployment of your application, how to debug, how to improve performance and how to secure your application.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Section 7&lt;/strong&gt; introduces two debugging modes:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Dash-Bee logging (-B) &lt;/li&gt;
		&lt;li&gt;&lt;span class="caps"&gt;USR1&lt;/span&gt; logging (lighter)&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;And also gives you an idea on what to look for when debugging an application. Nothing too detailed, granted, but enough to make sure you are pointed in the right direction.&lt;/p&gt;


	&lt;p&gt;Again, Zed&amp;#8217;s wisdom and wit are remarkable:&lt;/p&gt;


&lt;blockquote&gt;
&lt;em&gt;&amp;#8220;These people&amp;#8217;s problem is they suffer from Potpourri Turd Syndrome&#8212;a belief that their you-know-what don&amp;#8217;t stink and smells like fine dew on freshly cut grass. Whenever there&amp;#8217;s a bug, they go
running like kids in a candy store to other people&amp;#8217;s code trying to find fault and just assume that it&amp;#8217;s nothing they wrote.
[&amp;#8230;]
When you run into a problem with your application, always assume it&amp;#8217;s your fault first. Mongrel&amp;#8217;s not perfect, but its code is minuscule compared to the size of Rails and most likely even your own appli-cation code. Mongrel also powers many large and medium deployments without any problems. If there&amp;#8217;s an error, the evidence already says it&amp;#8217;s in your code, so bite the bullet and start investigating it as if it&amp;#8217;s your problem.&amp;#8221;&lt;/em&gt;
&lt;/blockquote&gt;

	&lt;p&gt;Similarly, &lt;strong&gt;Section 8&lt;/strong&gt; is a short but useful overview on performance tips and tricks and deployment tuning. The most useful thing is probably the checklist of the &amp;#8220;tuning process&amp;#8221;, which illustrates the simple steps to take to tune your application.&lt;/p&gt;


	&lt;p&gt;Finally, &lt;strong&gt;Section 9&lt;/strong&gt; addresses some common security concerns and clarifies how Mongrel deals with them. The answer is normally &amp;#8220;Mongrel strictly does this&amp;#8221; or &amp;#8220;Mongrel doesn&amp;#8217;t support this feature&amp;#8221;. After all, you should have understood by now that Mongrel is an example of simplicity and that it deliberately does not aim to offer all the feature you&amp;#8217;d expect by a server like Apache:&lt;/p&gt;


&lt;blockquote&gt;
&lt;em&gt;&amp;#8220;As you probably see, Mongrel say, &amp;#8220;No&amp;#8221; in many places where most Web servers say, &amp;#8220;Yes, OK.&amp;#8221; Sometimes this is because no one using Mongrel has needed it yet, sometimes it&amp;#8217;s because there&amp;#8217;s a
better, simpler way to accomplish the same goal. Mongrel is a different kind of Web server, and frequently you can solve your problem with a different solution.&amp;#8221;&lt;/em&gt; 
&lt;/blockquote&gt;

	&lt;h2&gt;Conclusion&lt;/h2&gt;


	&lt;p&gt;If Mongrel is opinionated software, this is definitely an opinionated book which fully embraces the project&amp;#8217;s philosopy of simplicity above everything else. It&amp;#8217;s an interesting read and it won&amp;#8217;t bore you to death by deliberately skipping long and potentially tedious subjects and adding interesting insights instead (like the Zed Sez sidebars). Perhaps it is a bit too direct towards certain people, who may get even get offended (as planned) by some of the author&amp;#8217;s assertions.&lt;/p&gt;


	&lt;p&gt;Despite being a 100-pages book, this &lt;em&gt;shortcut&lt;/em&gt; covers pretty much everything you need to know &lt;strong&gt;about Mongrel&lt;/strong&gt;. It will &lt;em&gt;not&lt;/em&gt; teach you everything about deployment, security, performance tweaks and debugging though: as the authors often state throughout the book, a lot of (big) books are available on those subject, and it wouldn&amp;#8217;t make sense to even attempt to discuss them in this shortcut.&lt;/p&gt;


	&lt;p&gt;Similarly, you won&amp;#8217;t find complex examples either, but that&amp;#8217;s acceptable because simple examples are often the only thing you need to grasp the basics of a concept or feature, and then use them as a &amp;#8220;scaffold&amp;#8221; for your own code.&lt;/p&gt;


	&lt;p&gt;Globally, the book is well balanced and &lt;em&gt;optimized&lt;/em&gt; for its size: lightweight introductory sections at first, then the &amp;#8220;real juice&amp;#8221; in the middle, and a few overview sections on advanced topics towards the end. You can read it easily in a few hours, perhaps less, and whenever you need to look something up in a hurry it will be fairly easy to locate.&lt;/p&gt;


	&lt;p&gt;A good read, and a &lt;em&gt;must&lt;/em&gt; for everyone who wants to learn more about Mongrel or Rails deployment.&lt;/p&gt;</description>
      <pubDate>Sat, 15 Dec 2007 03:42:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:e9705e1b-6dd5-49f0-b5df-1a6681e6ceb2</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/articles/mongrel-shortcut-review</link>
      <category>Articles</category>
      <category>review</category>
      <category>books</category>
      <category>Rails</category>
      <category>ruby</category>
      <enclosure url="http://www.h3rald.com/files/mongrel_shortcut.jpeg" type="image/jpeg" length="11113"/>
      <trackback:ping>http://www.h3rald.com/trackback/entries/144</trackback:ping>
    </item>
    <item>
      <title>Review Services</title>
      <description>&lt;p&gt;When it comes to software, I definitely like to try out new things. My collegues takes the piss out of me because every &lt;del&gt;week&lt;/del&gt; day I come up with &amp;#8220;some new tool they &lt;em&gt;have&lt;/em&gt; to start using&amp;#8221; and so on.
As a matter of fact, I like reviewing software as well. I enjoy writing and analyzing new things, evaluating all the new possibilities they may offer, and I also tend to have a rather critical eye for what doesn&amp;#8217;t &lt;em&gt;feel&lt;/em&gt; right. I&amp;#8217;ll use a tool for months but still try out new ones which claim to do the same thing &#8212; but better &#8212; as they come out.
Unfortunately &#8212; or fortunately, depends how you look at it &#8212; when it comes to software, there are very few &lt;em&gt;silver bullets&lt;/em&gt;, and things keep changing: that&amp;#8217;s the way it is and the way it will be.&lt;/p&gt;


	&lt;p&gt;I must try to write up a page (and ideally update it regularly, that&amp;#8217;s the hard part) listing all the tools I use, at some point&amp;#8230; but at any rate, if you coded some new app you think kicks ass or you found a hidden jewel in the labyrinth of freeware, just let me know: I&amp;#8217;ll definitely try it out, and if it&amp;#8217;s worth a post I&amp;#8217;ll blog about it.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;The same applies to books&lt;/strong&gt;, actually, as I like reading, especially those which are related to Ruby or programming, nowadays.&lt;/p&gt;


	&lt;p&gt;The cost of such reviews and articles? Depends! Certainly I wouldn&amp;#8217;t mind donations or some compensation of some form, especially from publishers or software companies. It may be money, books, software or even nothing: it really depends on what I have to review.
Please be aware that I am &lt;strong&gt;not&lt;/strong&gt; doing this full time, and I already have a job and a fianc&#233;e to look after, but I&amp;#8217;ll do my best to publish as much as I can on my site or even elsewhere elsewhere [Note: on e-zines, magazines &amp;#38; similar, not on your brother&amp;#8217;s friend&amp;#8217;s mother-in-law&amp;#8217;s crappy blog!].&lt;/p&gt;


	&lt;p&gt;For any inquiries, contact me (&lt;strong&gt;h3rald [&#8212;at&#8212;] h3rald.com&lt;/strong&gt;).&lt;/p&gt;</description>
      <pubDate>Fri, 14 Dec 2007 12:24:00 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:3125dba7-1b4d-41a6-90b8-82bcd5740d44</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/blog/review-services</link>
      <category>Blog</category>
      <category>review</category>
      <category>website</category>
      <category>personal</category>
      <category>tools</category>
      <category>books</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/143</trackback:ping>
    </item>
  </channel>
</rss>
