<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>Luca Guidi - Home</title>
  <id>tag:www.lucaguidi.com,2008:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.3">Mephisto Noh-Varr</generator>
  <link href="http://www.lucaguidi.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://www.lucaguidi.com/" rel="alternate" type="text/html"/>
  <updated>2008-06-30T13:07:10Z</updated>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-06-30:289</id>
    <published>2008-06-30T09:02:00Z</published>
    <updated>2008-06-30T13:07:10Z</updated>
    <category term="Ruby"/>
    <link href="http://www.lucaguidi.com/2008/6/30/sashimi-getting-started-tutorial" rel="alternate" type="text/html"/>
    <title>Sashimi: Getting Started Tutorial</title>
<content type="html">
            &lt;p&gt;
  Here a &lt;strong&gt;getting started&lt;/strong&gt; tutorial for &lt;a href=&quot;http://lucaguidi.com/pages/sashimi&quot; title=&quot;Sashimi&quot;&gt;Sashimi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;.
  &lt;a href=&quot;http://lucaguidi.com/assets/2008/6/30/sashimi_getting_started.mov&quot; title=&quot;Sashimi getting started&quot;&gt;&lt;img src=&quot;http://lucaguidi.com/assets/2008/6/30/sashimi_getting_started.png&quot; height=&quot;450px&quot; alt=&quot;Sashimi getting started tutorial&quot; width=&quot;600px&quot; /&gt;&lt;/a&gt;
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-06-23:285</id>
    <published>2008-06-23T13:58:00Z</published>
    <updated>2008-06-23T18:19:55Z</updated>
    <category term="Ruby"/>
    <link href="http://www.lucaguidi.com/2008/6/23/released-sashimi-0-1-6" rel="alternate" type="text/html"/>
    <title>Released Sashimi 0.1.6</title>
<content type="html">
            &lt;p&gt;
I just released a &lt;strong&gt;new version&lt;/strong&gt; of Sashimi, with tiny fixes and a new home! In fact the project is also hosted on &lt;strong&gt;RubyForge&lt;/strong&gt;, now you can install the gem with:
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ (sudo) gem install sashimi&lt;/code&gt;&lt;/pre&gt;
or with:
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ (sudo) gem install jodosha-sashimi --source=http://gems.github.com&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;If you wish, you can visit the project pages on &lt;a href=&quot;http://github.com/jodosha/sashimi&quot; title=&quot;GitHub Sashimi page&quot;&gt;GitHub&lt;/a&gt; and on &lt;a href=&quot;http://rubyforge.org/projects/sashimi/&quot; title=&quot;RubyForge Sashimi page&quot;&gt;RubyForge&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; The release 0.1.6 is &lt;strong&gt;broken&lt;/strong&gt;, you are strongly encouraged to update your gem with the newest &lt;strong&gt;0.1.7&lt;/strong&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-06-18:283</id>
    <published>2008-06-18T17:23:00Z</published>
    <updated>2008-06-18T17:33:25Z</updated>
    <category term="Annoucements"/>
    <category term="Ruby on Rails"/>
    <link href="http://www.lucaguidi.com/2008/6/18/speaker-at-railsconf-europe-2008" rel="alternate" type="text/html"/>
    <title>Speaker at RailsConf Europe 2008</title>
<content type="html">
            &lt;p&gt;I'm proud to announce my presence as speaker at the &lt;a href=&quot;http://www.railsconfeurope.com/&quot;&gt;RailsConf Europe 2008&lt;/a&gt; with a speech on &lt;a href=&quot;http://lucaguidi.com/pages/click-to-globalize&quot;&gt;Click to Globalize&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-06-03:269</id>
    <published>2008-06-03T16:53:00Z</published>
    <updated>2008-06-04T09:55:32Z</updated>
    <category term="Ruby on Rails"/>
    <link href="http://www.lucaguidi.com/2008/6/3/rails-single-file-app" rel="alternate" type="text/html"/>
    <title>Rails: Single File App</title>
<content type="html">
            &lt;p&gt;I took inspiration from the &lt;a href=&quot;http://m.onkey.org/2008/2/16/single-file-rails-application&quot; title=&quot;Single File Rails Application&quot;&gt;Pratik Naik post&lt;/a&gt;, and realized a more simplistic version of its &lt;a href=&quot;http://rubyonrails.org&quot;&gt;Rails&lt;/a&gt; single file app. My implementation has only &lt;strong&gt;Rails&lt;/strong&gt; as unique dependency.

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;require 'rubygems'
require 'action_controller'
require 'webrick'
require 'webrick_server'

class HelloWorldController &amp;lt; ActionController::Base
  session :off
  def index; render :text =&amp;gt; 'Hello World!' end
end

ActionController::Routing::Routes.draw do |map|
  map.root :controller =&amp;gt; &amp;quot;hello_world&amp;quot;
end

DispatchServlet.dispatch :port =&amp;gt; 3000,
    :server_root  =&amp;gt; File.dirname(__FILE__)&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;
&lt;strong&gt;Update 2008-06-04&lt;/strong&gt;: I just wrote another version which also uses &lt;strong&gt;ActiveRecord&lt;/strong&gt; and a &lt;strong&gt;template&lt;/strong&gt;.
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;require 'rubygems'
require 'activerecord'
require 'action_controller'
require 'webrick'
require 'webrick_server'

ActiveRecord::Base.establish_connection(
  :adapter  =&amp;gt; 'sqlite3',
  :database =&amp;gt; 'tiny_rails.sqlite3',
  :timeout  =&amp;gt; 5000)

ActiveRecord::Schema.define do
  create_table :people, :force =&amp;gt; true do |t|
    t.string :first_name
  end
end
class Person &amp;lt; ActiveRecord::Base; end
Person.create :first_name =&amp;gt; 'Luca'

File.open('index.html.erb', 'w') do |f|
  f &amp;lt;&amp;lt; &amp;quot;Hello, my name is &amp;lt;%=h @person.first_name %&amp;gt;!\n&amp;quot;
end

class HelloWorldController &amp;lt; ActionController::Base
  session :off
  def index
    @person = Person.find :first
    render :file =&amp;gt; 'index.html.erb'
  end
end

ActionController::Routing::Routes.draw do |map|
  map.root :controller =&amp;gt; &amp;quot;hello_world&amp;quot;
end

DispatchServlet.dispatch :port =&amp;gt; 3000,
    :server_root  =&amp;gt; File.dirname(__FILE__)&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Just start the script and point your browser at &lt;strong&gt;http://localhost:3000&lt;/strong&gt;!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-05-29:268</id>
    <published>2008-05-29T15:12:00Z</published>
    <updated>2008-05-29T15:13:43Z</updated>
    <category term="Ruby"/>
    <link href="http://www.lucaguidi.com/2008/5/29/ruby-class-methods-proxy" rel="alternate" type="text/html"/>
    <title>Ruby: Class Methods Proxy</title>
<content type="html">
            &lt;p&gt;
  Did you ever used class methods inside your instance methods? If yes, you probably noticed how &lt;strong&gt;frustrating&lt;/strong&gt; can be to use the &lt;code&gt;self.class.my_class_method&lt;/code&gt; syntax. A solution could be to create a private method which encapsulates the class one.
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Repository
  def self.path
    @@path
  end
  
  def print_path
    puts path
  end
  
  private
    def path
      self.class.path
    end
end&lt;/code&gt;&lt;/pre&gt;
  In the above example, &lt;code&gt;#print_path&lt;/code&gt; can print the &lt;code&gt;@@code&lt;/code&gt; value, without worrying about it's a class value, because we have wrapped it.
&lt;/p&gt;

&lt;p&gt;
  When I developed &lt;a href=&quot;http://lucaguidi.com/pages/sashimi&quot;&gt;Sashimi&lt;/a&gt; I've widely used this technique, with a bad impact on the code duplication, and in order to DRY-up my code I extended the Ruby's &lt;code&gt;Class&lt;/code&gt; class in this way:
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Class
  def class_method_proxy(*method_names)
    method_names.each do |m|
      self.class_eval %{
        # Proxy method for &amp;lt;tt&amp;gt;#{self.class.name}##{m}&amp;lt;/tt&amp;gt;
        def #{m}(*args)
          self.class.#{m}(*args)
        end
        private :#{m}
      }, __FILE__, __LINE__
    end
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
  This approach allow us to annotate our classes, choosing which class methods should be available as private methods.&lt;br /&gt;
  Now, our example class should look like the following:
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Repository
  def self.path
    @@path
  end
  class_method_proxy :path

  def print_path
    puts path
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
  Of course you can pass multiple symbols to proxy many methods at the same time.
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class_method_proxy :path, :another_path, :a_third_one&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-05-28:265</id>
    <published>2008-05-28T16:58:00Z</published>
    <updated>2008-05-29T09:43:44Z</updated>
    <category term="Javascript"/>
    <link href="http://www.lucaguidi.com/2008/5/28/faster-javascript-trim" rel="alternate" type="text/html"/>
    <title>Faster JavaScript Trim</title>
<content type="html">
            &lt;p&gt;I've recently discovered the very interesting &lt;a href=&quot;http://blog.stevenlevithan.com/archives/faster-trim-javascript&quot;&gt;Steven Levithan post&lt;/a&gt; about the &lt;strong&gt;JavaScript's trim&lt;/strong&gt; function of the &lt;strong&gt;String&lt;/strong&gt; class.&lt;/p&gt;
&lt;p&gt;
  So, here my version:
&lt;pre&gt;&lt;code class=&quot;JavaScript&quot;&gt;function trim13 (str) {
  var ws = /\s/, _start = 0, end = str.length;
  while(ws.test(str.charAt(_start++)));
  while(ws.test(str.charAt(--end)));
  return str.slice(_start - 1, end + 1);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;h3&gt;More numbers, please!&lt;/h3&gt;
&lt;p&gt;
  I tested my function against the &lt;a href=&quot;http://stevenlevithan.com/demo/trim.cfm&quot;&gt;benchmarking page&lt;/a&gt; of the original post.&lt;br /&gt;
  &lt;strong&gt;Note&lt;/strong&gt;: times are expressed in &lt;acronym title=&quot;milliseconds&quot;&gt;MS&lt;/acronym&gt; and are the average of ten executions per browser.&lt;br /&gt;
  &lt;strong&gt;Update [2008-05-29]:&lt;/strong&gt; I re-runned all the tests and updated results, because &lt;a href=&quot;http://blog.stevenlevithan.com/&quot;&gt;Steven&lt;/a&gt; noticed that test suite was wrong (few whitespaces).
  &lt;table&gt;
    &lt;tr&gt;
      &lt;th&gt;&lt;/th&gt;
      &lt;th&gt;Mac&lt;/th&gt;
      &lt;th&gt;Windows&lt;/th&gt;
      &lt;th&gt;&lt;/th&gt;
    &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;&lt;/th&gt;
        &lt;th&gt;Safari 3.1&lt;/th&gt;
        &lt;th&gt;Firefox 2.0.0.14&lt;/th&gt;
        &lt;th&gt;Firefox 3.0b5&lt;/th&gt;
        &lt;th&gt;Opera 9.27&lt;/th&gt;
        &lt;th&gt;Opera 9.50b2&lt;/th&gt;
        &lt;th&gt;Internet Explorer 6&lt;/th&gt;
        &lt;th&gt;Internet Explorer 7&lt;/th&gt;
        &lt;th&gt;Firefox 2.0.0.14&lt;/th&gt;
        &lt;th&gt;Opera 9.27&lt;/th&gt;
        &lt;th&gt;Opera 9.50b2&lt;/th&gt;
        &lt;th&gt;Average&lt;/th&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim1&lt;/th&gt;
        &lt;td&gt;25&lt;/td&gt;
        &lt;td&gt;40&lt;/td&gt;
        &lt;td&gt;19&lt;/td&gt;
        &lt;td&gt;100&lt;/td&gt;
        &lt;td&gt;93&lt;/td&gt;
        &lt;td&gt;12&lt;/td&gt;
        &lt;td&gt;12&lt;/td&gt;
        &lt;td&gt;38&lt;/td&gt;
        &lt;td&gt;124&lt;/td&gt;
        &lt;td&gt;111&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;57&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim2&lt;/th&gt;
        &lt;td&gt;25&lt;/td&gt;
        &lt;td&gt;52&lt;/td&gt;
        &lt;td&gt;29&lt;/td&gt;
        &lt;td&gt;100&lt;/td&gt;
        &lt;td&gt;98&lt;/td&gt;
        &lt;td&gt;6&lt;/td&gt;
        &lt;td&gt;11&lt;/td&gt;
        &lt;td&gt;44&lt;/td&gt;
        &lt;td&gt;125&lt;/td&gt;
        &lt;td&gt;116&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;61&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim3&lt;/th&gt;
        &lt;td&gt;32&lt;/td&gt;
        &lt;td&gt;54&lt;/td&gt;
        &lt;td&gt;46&lt;/td&gt;
        &lt;td&gt;156&lt;/td&gt;
        &lt;td&gt;148&lt;/td&gt;
        &lt;td&gt;15&lt;/td&gt;
        &lt;td&gt;31&lt;/td&gt;
        &lt;td&gt;57&lt;/td&gt;
        &lt;td&gt;209&lt;/td&gt;
        &lt;td&gt;184&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;93&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim4&lt;/th&gt;
        &lt;td&gt;43&lt;/td&gt;
        &lt;td&gt;43&lt;/td&gt;
        &lt;td&gt;37&lt;/td&gt;
        &lt;td&gt;151&lt;/td&gt;
        &lt;td&gt;139&lt;/td&gt;
        &lt;td&gt;15&lt;/td&gt;
        &lt;td&gt;38&lt;/td&gt;
        &lt;td&gt;49&lt;/td&gt;
        &lt;td&gt;198&lt;/td&gt;
        &lt;td&gt;186&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;90&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim5&lt;/th&gt;
        &lt;td&gt;64&lt;/td&gt;
        &lt;td&gt;102&lt;/td&gt;
        &lt;td&gt;104&lt;/td&gt;
        &lt;td&gt;134&lt;/td&gt;
        &lt;td&gt;116&lt;/td&gt;
        &lt;td&gt;65&lt;/td&gt;
        &lt;td&gt;908&lt;/td&gt;
        &lt;td&gt;323&lt;/td&gt;
        &lt;td&gt;291&lt;/td&gt;
        &lt;td&gt;274&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;238&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim6&lt;/th&gt;
        &lt;td&gt;69&lt;/td&gt;
        &lt;td&gt;115&lt;/td&gt;
        &lt;td&gt;109&lt;/td&gt;
        &lt;td&gt;195&lt;/td&gt;
        &lt;td&gt;171&lt;/td&gt;
        &lt;td&gt;47&lt;/td&gt;
        &lt;td&gt;1.497&lt;/td&gt;
        &lt;td&gt;364&lt;/td&gt;
        &lt;td&gt;436&lt;/td&gt;
        &lt;td&gt;338&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;334&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim7&lt;/th&gt;
        &lt;td&gt;69&lt;/td&gt;
        &lt;td&gt;120&lt;/td&gt;
        &lt;td&gt;107&lt;/td&gt;
        &lt;td&gt;142&lt;/td&gt;
        &lt;td&gt;129&lt;/td&gt;
        &lt;td&gt;31&lt;/td&gt;
        &lt;td&gt;900&lt;/td&gt;
        &lt;td&gt;345&lt;/td&gt;
        &lt;td&gt;330&lt;/td&gt;
        &lt;td&gt;271&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;244&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim8&lt;/th&gt;
        &lt;td&gt;4&lt;/td&gt;
        &lt;td&gt;118&lt;/td&gt;
        &lt;td&gt;104&lt;/td&gt;
        &lt;td&gt;112&lt;/td&gt;
        &lt;td&gt;97&lt;/td&gt;
        &lt;td&gt;4&lt;/td&gt;
        &lt;td&gt;5&lt;/td&gt;
        &lt;td&gt;540&lt;/td&gt;
        &lt;td&gt;255&lt;/td&gt;
        &lt;td&gt;180&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;142&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim9&lt;/th&gt;
        &lt;td&gt;34&lt;/td&gt;
        &lt;td&gt;126&lt;/td&gt;
        &lt;td&gt;116&lt;/td&gt;
        &lt;td&gt;1.825&lt;/td&gt;
        &lt;td&gt;1.218&lt;/td&gt;
        &lt;td&gt;23&lt;/td&gt;
        &lt;td&gt;74&lt;/td&gt;
        &lt;td&gt;113&lt;/td&gt;
        &lt;td&gt;1.667&lt;/td&gt;
        &lt;td&gt;1.417&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;662&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim10&lt;/th&gt;
        &lt;td&gt;0&lt;/td&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;6&lt;/td&gt;
        &lt;td&gt;5&lt;/td&gt;
        &lt;td&gt;3&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;0&lt;/td&gt;
        &lt;td&gt;6&lt;/td&gt;
        &lt;td&gt;0&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;2&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim11&lt;/th&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;3&lt;/td&gt;
        &lt;td&gt;11&lt;/td&gt;
        &lt;td&gt;3&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;10&lt;/td&gt;
        &lt;td&gt;5&lt;/td&gt;
        &lt;td&gt;7&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim12&lt;/th&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;3&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;4&lt;/td&gt;
        &lt;td&gt;6&lt;/td&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;10&lt;/td&gt;
        &lt;td&gt;4&lt;/td&gt;
        &lt;td&gt;4&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;4&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;th&gt;trim13&lt;/th&gt;
        &lt;td&gt;0&lt;/td&gt;
        &lt;td&gt;0&lt;/td&gt;
        &lt;td&gt;3&lt;/td&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;0&lt;/td&gt;
        &lt;td&gt;1&lt;/td&gt;
        &lt;td&gt;2&lt;/td&gt;
        &lt;td&gt;0&lt;/td&gt;
        &lt;td&gt;5&lt;/td&gt;
        &lt;td&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/table&gt;
&lt;/p&gt;

&lt;p&gt;Please download the &lt;a href=&quot;http://lucaguidi.com/assets/2008/5/29/trim_benchmark.zip&quot;&gt;benchmark suite&lt;/a&gt;, and test against your browsers.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-05-20:260</id>
    <published>2008-05-20T16:33:00Z</published>
    <updated>2008-05-20T16:49:43Z</updated>
    <category term="Ruby"/>
    <link href="http://www.lucaguidi.com/2008/5/20/sashimi-just-received-a-tasteful-update" rel="alternate" type="text/html"/>
    <title>Sashimi: Just Received A Tasteful Update</title>
<content type="html">
            &lt;p&gt;Yesterday &lt;a href=&quot;http://lucaguidi.com/2008/5/19/sashimi-a-rails-plugins-manager-gem&quot; title=&quot;Sashimi: A Rails Plugins Manager Gem&quot;&gt;I announced&lt;/a&gt; &lt;a href=&quot;http://lucaguidi.com/pages/sashimi&quot;&gt;Sashimi&lt;/a&gt; and now it's already time of tasteful updates.&lt;/p&gt;

&lt;h3&gt;Changes&lt;/h3&gt;
&lt;p&gt;First, thanks to all the people that appreciated my work. Second, new commands and options are avaliable for Sashimi.&lt;/p&gt;

&lt;p&gt;Update all plugins in your repository:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ sashimi update --all&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Install a plugin to your Rails app:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ sashimi install --rails click-to-globalize&lt;/code&gt;&lt;/pre&gt;
&lt;strong&gt;NOTE&lt;/strong&gt; this is an alias for the &lt;code&gt;add&lt;/code&gt; command.
&lt;/p&gt;

&lt;p&gt;Update a plugin of a Rails app:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ sashimi update --rails click-to-globalize&lt;/code&gt;&lt;/pre&gt;
&lt;strong&gt;NOTE&lt;/strong&gt; If your application is versioned with Svn or Git, Sashimi will automatically schedules for add/remove the added/removed files.
&lt;/p&gt;

&lt;h3&gt;How To Update&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ (sudo) gem update jodosha-sashimi --source=http://gems.github.com&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I hope you enjoy those addictional options.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-05-19:258</id>
    <published>2008-05-19T13:33:00Z</published>
    <updated>2008-05-19T13:44:31Z</updated>
    <category term="Ruby"/>
    <link href="http://www.lucaguidi.com/2008/5/19/sashimi-a-rails-plugins-manager-gem" rel="alternate" type="text/html"/>
    <title>Sashimi: A Rails Plugins Manager Gem</title>
<content type="html">
            &lt;p&gt;I have a really, really bad memory: each time I need to install a &lt;a href=&quot;http://rubyonrails.org&quot; title=&quot;Ruby on Rails home page&quot;&gt;Rails&lt;/a&gt; plugin, I Google to find the repository, then try to download the code. Often, I remember the url, but the server is down. Damn!&lt;/p&gt;
&lt;p&gt;All this annoying issues kill the Rails rapidity on application prototyping. But, what if all the plugins which I need are available &lt;strong&gt;offline&lt;/strong&gt; on my notebook? I can forget about all that urls, and I should stop to worry about the server status.&lt;/p&gt;
&lt;p&gt;To solve this problems, I wrote &lt;a href=&quot;http://lucaguidi.com/pages/sashimi&quot; title=&quot;Sashimi page&quot;&gt;Sashimi&lt;/a&gt;, it's a gem that manages you favourite Rails plugins in a local repository.&lt;/p&gt;

&lt;h3&gt;How It Works?&lt;/h3&gt;
&lt;p&gt;First you need to install it with:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ (sudo) gem install jodosha-sashimi --source=http://gems.github.com&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Now you can install a plugin on your local repository:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ sashimi install git://github.com/jodosha/click-to-globalize.git&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Ta-daaaa!! Now &lt;a href=&quot;http://lucaguidi.com/pages/click-to-globalize&quot;&gt;Click to Globalize&lt;/a&gt; is available offline:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ sashimi list

click-to-globalize&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
If you need to add it to your Rails app, just move to your app root, then type:&lt;br /&gt;
&lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;$ sashimi add click-to-globalize&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I found &lt;strong&gt;Sashimi&lt;/strong&gt; really useful, I hope you too.&lt;/p&gt;
&lt;p&gt;For the complete reference, please check out at the &lt;a href=&quot;http://lucaguidi.com/pages/sashimi&quot; title=&quot;Sashimi page&quot;&gt;official gem page&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-05-14:256</id>
    <published>2008-05-14T12:21:00Z</published>
    <updated>2008-05-14T12:34:10Z</updated>
    <category term="Ruby on Rails"/>
    <link href="http://www.lucaguidi.com/2008/5/14/acts-as-resource-rails-2-1-ready-and-moved-to-github" rel="alternate" type="text/html"/>
    <title>Acts As Resource: Rails 2.1 ready and moved to GitHub</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://lucaguidi.com/pages/acts-as-resource&quot;&gt;Acts As Resource&lt;/a&gt; is &lt;strong&gt;ready&lt;/strong&gt; for the imminent &lt;strong&gt;Rails 2.1&lt;/strong&gt;!&lt;/p&gt;
&lt;p&gt;I also moved it to &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;, the new repo is &lt;a href=&quot;http://github.com/jodosha/acts-as-resource/tree/master&quot;&gt;http://github.com/jodosha/acts-as-resource/tree/master&lt;/a&gt;, the SVN one is &lt;strong&gt;deprecated&lt;/strong&gt;.&lt;/p&gt;

If you enjoyed this post, feel free to recommend me on &lt;a href=&quot;http://www.workingwithrails.com/recommendation/new/person/8829-luca-guidi&quot;&gt;Working With Rails&lt;/a&gt;.
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-05-12:255</id>
    <published>2008-05-12T17:47:00Z</published>
    <updated>2008-05-13T18:03:42Z</updated>
    <category term="Ruby on Rails"/>
    <link href="http://www.lucaguidi.com/2008/5/12/click-to-globalize-rewritten-and-moved-to-github" rel="alternate" type="text/html"/>
    <title>Click to Globalize: rewritten and moved to GitHub</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://lucaguidi.com/pages/click-to-globalize&quot;&gt;Click to Globalize&lt;/a&gt; has been rewritten, in order to use all instance methods of the &lt;strong&gt;JavaScript&lt;/strong&gt; class, instead of class methods.&lt;/p&gt;
&lt;p&gt;
I also fixed some tiny issues: &lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;form_authentication_token&lt;/code&gt; method is called only if the application is protected against the CSRF attacks (&lt;code&gt;protect_against_forgery?&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;It uses as parameter key what &lt;code&gt;request_forgery_protection_token&lt;/code&gt; returns, instead of the hard-coded &lt;code&gt;authenticity_token&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;JavaScript&lt;/strong&gt; class uses &lt;strong&gt;Prototype&lt;/strong&gt;'s &lt;strong&gt;dom:loaded&lt;/strong&gt; custom event.&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;

&lt;p&gt;I also migrated the plugin &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;. The new repo is &lt;a href=&quot;http://github.com/jodosha/click-to-globalize/tree/master&quot;&gt;http://github.com/jodosha/click-to-globalize/tree/master&lt;/a&gt;, so the oldest one is &lt;strong&gt;deprecated&lt;/strong&gt;.&lt;br /&gt;
Have a nice globalization!&lt;/p&gt;

&lt;p&gt;If you enjoyed this post, feel free to recommend me on &lt;a href=&quot;http://www.workingwithrails.com/recommendation/new/person/8829-luca-guidi&quot;&gt;Working With Rails&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-04-28:219</id>
    <published>2008-04-28T10:49:00Z</published>
    <updated>2008-04-28T11:54:36Z</updated>
    <category term="Ruby on Rails"/>
    <link href="http://www.lucaguidi.com/2008/4/28/ruby-on-rails-test-model-domain-changes" rel="alternate" type="text/html"/>
    <title>Ruby on Rails: Test Model Domain Changes</title>
<content type="html">
            You know how tests are fundamental for a well-developed project, for this reason we should create step-by-step a net of test cases. Of course we also should be able to change rapidly our tests as the same we do with our code. &lt;a href=&quot;http://rubyonrails.org&quot;&gt;Ruby on Rails&lt;/a&gt; is a great framework, because its shortcuts, the wide usage of &lt;acronym title=&quot;Domain Specific Language&quot;&gt;DSL&lt;/acronym&gt; etc.. All this stuff can save a lot of time, but what about tests? Are we really able to &lt;em&gt;follow&lt;/em&gt; our code?

&lt;h3&gt;Create and Destroy&lt;/h3&gt;
&lt;strong&gt;ActiveSupport&lt;/strong&gt; provides few useful tools to improve our test, I really appreciate &lt;code&gt;assert_difference&lt;/code&gt; and &lt;code&gt;assert_no_difference&lt;/code&gt;.

Basically, this two methods accepts as arguments a code chunk (as string) and a block. When the test run, it binds the block first, then it assert if the changements caused by the block call are the same expected by first argument.

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def test_should_be_created
  assert_difference 'Person.count' do
    create_person
  end
end&lt;/code&gt;&lt;/pre&gt;

We are testing a &lt;code&gt;Person&lt;/code&gt; creation, we pass as first argument &lt;code&gt;'Person.count'&lt;/code&gt;, and the code that should correctly save the person. If the model will be saved, a new record should exists into the database table. At this moment &lt;code&gt;assert_difference&lt;/code&gt; evaluates the first argument, and assert if there are &lt;strong&gt;differences&lt;/strong&gt; in the &lt;code&gt;Person&lt;/code&gt; count.

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def test_should_be_destroyed
  assert_difference 'Person.count', -1 do
    destroy_person
  end
end&lt;/code&gt;&lt;/pre&gt;

This example is just a bit different, we are also passing a &lt;code&gt;Fixnum&lt;/code&gt; as argument. This because we want assert another difference from the default one, which is &lt;strong&gt;+1&lt;/strong&gt;. So, if the model will be correctly saved, we will have a negative difference, of one, into the &lt;code&gt;Person&lt;/code&gt; count.

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def test_should_require_first_name_on_create
  assert_no_difference 'Person.count' do
    create_person
    assert person.errors.on(:first_name)
  end
end&lt;/code&gt;&lt;/pre&gt;

The third example uses &lt;code&gt;assert_no_difference&lt;/code&gt;, to test aganist model validations. &lt;strong&gt;ActiveRecord&lt;/strong&gt;, by default, prevents the creation of a model if a validation doesn't pass. In this case our model requires &lt;code&gt;first_name&lt;/code&gt; as mandatory attribute, but unfortunately it's nil, so the creation fails and the brand new record will be not created.

&lt;h3&gt;Update&lt;/h3&gt;
As you can see, those two methods are very useful for test creation and destruction of models, but totally missing the goal of the update. In fact, the update process of a record, doesn't produces numerical differences.

I created two methods to supply this lack.
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def assert_updated(model, message = nil, &amp;amp;block) 
  yield
  assert_not_equal model.attributes, model.reload.attributes, message
end&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def assert_not_updated(model, message = nil, &amp;amp;block)
  yield
  assert_equal model.attributes, model.reload.attributes, message
end&lt;/code&gt;&lt;/pre&gt;

Just add them to your &lt;code&gt;test/test_helper.rb&lt;/code&gt;, and they will be available in all your test cases.

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def test_should_update
  assert_updated person do
    update_person
  end
end&lt;/code&gt;&lt;/pre&gt;

First, you should notice that the first argument it isn't a string but an &lt;code&gt;ActiveRecord&lt;/code&gt;. The behaviour of this method is similar to the previous I illustrated, it first bind the block, then assert if the attributes of the model are different.
It internally uses &lt;code&gt;ActiveRecord::Base#attributes&lt;/code&gt; which returns an hash of model attributes, then assert the differences with &lt;strong&gt;Ruby&lt;/strong&gt;'s &lt;code&gt;assert_not_equal&lt;/code&gt;.

&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def test_should_require_first_name_on_update
  assert_not_updated person do
    update_person
    assert person.errors.on(:first_name)
  end
end&lt;/code&gt;&lt;/pre&gt;

Similarly to all other examples, it first performs the block, call then assert there are no changes in the model attributes.

&lt;h3&gt;Conclusion&lt;/h3&gt;
Those methods should provide a rapid way to write and mantain your test cases.



If you enjoyed this post, feel free to recommend me on &lt;a href=&quot;http://www.workingwithrails.com/recommendation/new/person/8829-luca-guidi&quot;&gt;Working With Rails&lt;/a&gt;.
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-04-04:214</id>
    <published>2008-04-04T23:29:00Z</published>
    <updated>2008-04-04T23:33:28Z</updated>
    <category term="Art"/>
    <link href="http://www.lucaguidi.com/2008/4/4/bit-fall" rel="alternate" type="text/html"/>
    <title>Bit.Fall</title>
<content type="html">
            &amp;lt;object height=&quot;355&quot; width=&quot;425&quot;&gt;&amp;lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/ygQHj1W0PPM&amp;hl=en&quot;&gt;&amp;lt;/param&gt;&amp;lt;param name=&quot;wmode&quot; value=&quot;transparent&quot;&gt;&amp;lt;/param&gt;&amp;lt;embed type=&quot;application/x-shockwave-flash&quot; src=&quot;http://www.youtube.com/v/ygQHj1W0PPM&amp;hl=en&quot; height=&quot;355&quot; wmode=&quot;transparent&quot; width=&quot;425&quot;&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;

&lt;p&gt;&lt;strong&gt;Bit.Fall&lt;/strong&gt; by &lt;strong&gt;&lt;a href=&quot;http://sphericalrobots.org/&quot; title=&quot;Julius Popp&quot;&gt;Julius Popp&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-03-19:213</id>
    <published>2008-03-19T12:54:00Z</published>
    <updated>2008-03-19T17:13:15Z</updated>
    <category term="Javascript"/>
    <link href="http://www.lucaguidi.com/2008/3/19/make-your-elements-draggables-and-resizeables-with-resizeable-js" rel="alternate" type="text/html"/>
    <title>Make your elements draggables and resizeables with Resizeable.js</title>
<content type="html">
            &lt;p&gt;Hello, I'm still alive and I want to share a useful &lt;strong&gt;JavaScript&lt;/strong&gt; class: &lt;strong&gt;Resizeable.js&lt;/strong&gt;. It allows to make &lt;strong&gt;draggable and resizeable&lt;/strong&gt; your DOM elements!&lt;/p&gt;

&lt;h3&gt;How it works?&lt;/h3&gt;
&lt;p&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;new Resizeable('element');&lt;/code&gt;&lt;/pre&gt;&lt;/p&gt;

&lt;p&gt;Your element has now &lt;strong&gt;two sensible areas&lt;/strong&gt;: the border area and the central area. If you click on the central area and move the mouse around, keeping the left button pressed, your element will be &lt;strong&gt;dragged&lt;/strong&gt;. If you are on the border area, and perform the same gesture, your element will be &lt;strong&gt;resized&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;
  The default size of the border area is &lt;strong&gt;6px&lt;/strong&gt;, but you can customize it via the options passed to the constructor:
  &lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;new Resizeable('element', {top:12, right:12, bottom:12, left:12});&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;h3&gt;Try it now!&lt;/h3&gt;
&lt;p&gt;Try it now on the &lt;a href=&quot;http://lucaguidi.com/assets/2008/3/19/resizeable.html&quot;&gt;demo page&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Credits and License&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Resizeable.js&lt;/strong&gt; is based on &lt;strong&gt;&lt;a href=&quot;http://craz8.com&quot;&gt;Thomas Fakes&lt;/a&gt;&lt;/strong&gt; homonym class and on &lt;strong&gt;&lt;a href=&quot;http://mir.aculo.us&quot;&gt;Thomas Fuchs&lt;/a&gt;&lt;/strong&gt; &lt;a href=&quot;http://script.aculo.us&quot;&gt;Scriptaculous&lt;/a&gt;, this means it depends on &lt;a href=&quot;http://prototypejs.org&quot;&gt;Prototype&lt;/a&gt;(&lt;em&gt;1.6.0+&lt;/em&gt;) and Scriptaculous (&lt;em&gt;1.8.0+&lt;/em&gt;) itself.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resizeable.js&lt;/strong&gt; is &lt;strong&gt;Free-Software&lt;/strong&gt;, distributed under the &lt;a href=&quot;http://www.opensource.org/licenses/mit-license.php&quot;&gt;MIT License&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;Download&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;http://lucaguidi.com/assets/2008/3/19/resizeable.js&quot;&gt;&lt;strong&gt;Resizeable.js&lt;/strong&gt;&lt;/a&gt; (md5: &lt;em&gt;aae8256ab0eff3972a03ed67e238e623&lt;/em&gt;).&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-01-30:199</id>
    <published>2008-01-30T14:37:00Z</published>
    <updated>2008-01-30T14:42:08Z</updated>
    <category term="Ruby"/>
    <link href="http://www.lucaguidi.com/2008/1/30/ruby-xml-parsing-with-sax" rel="alternate" type="text/html"/>
    <title>Ruby: XML Parsing With SAX</title>
<content type="html">
            &lt;p&gt;&lt;strong&gt;&lt;acronym title=&quot;Simple API for XML&quot;&gt;SAX&lt;/acronym&gt;&lt;/strong&gt; is an &lt;a href=&quot;http://en.wikipedia.org/wiki/Event-driven&quot;&gt;&lt;strong&gt;event-driven&lt;/strong&gt;&lt;/a&gt; parser for &lt;acronym title=&quot;eXtensible Markup Language&quot;&gt;XML&lt;/acronym&gt;.&lt;/p&gt;
It &lt;strong&gt;sequentially&lt;/strong&gt; reads the xml and generates special events. So, if you want to use SAX, you should implement the code to handle them. It's quite different from the &lt;strong&gt;&lt;acronym title=&quot;Document Object Model&quot;&gt;DOM&lt;/acronym&gt;&lt;/strong&gt; model, where the whole xml is parsed and loaded in an &lt;a href=&quot;http://en.wikipedia.org/wiki/Tree_(data_structure)&quot; title=&quot;Tree (data structure)&quot;&gt;tree&lt;/a&gt;.&lt;br /&gt;
As you can see, the first approach is more difficult than the DOM one. Why we should use it? Depends.&lt;br /&gt;
If you want to extract certain informations from a big file, probably you should choose a SAX implementation, in this way you can avoid the initial DOM loading overhead.&lt;/p&gt;

&lt;h3&gt;The Ruby XML Library&lt;/h3&gt;
&lt;p&gt;The Ruby core library has a built-in XML parser (both DOM and SAX) called &lt;strong&gt;REXML&lt;/strong&gt;, but it's terribly slow, it's highly advisable to use &lt;a href=&quot;http://libxml.rubyforge.org/&quot;&gt;&lt;strong&gt;libxml&lt;/strong&gt;&lt;/a&gt;. It's a binding to the popular library from &lt;strong&gt;Gnome&lt;/strong&gt; and it was released as gem.&lt;/p&gt;

&lt;h3&gt;The Ruby Implementation&lt;/h3&gt;
&lt;p&gt;In first instance we need an &lt;strong&gt;handler&lt;/strong&gt;, to deal with the SAX events.&lt;br /&gt;
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Handler
  def method_missing(method_name, *attributes, &amp;amp;block)
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;Libxml generates several events and it expects to find certain methods into the class assigned ad handler. With &lt;code&gt;method_missing&lt;/code&gt; we simply avoid any exception.&lt;/p&gt;

&lt;h3&gt;A More Useful Example&lt;/h3&gt;
&lt;p&gt;We try to extract the most recent headlines of a blog.&lt;/p&gt;
&lt;p&gt;Download the feed:&lt;br /&gt;
  &lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;curl http://feeds.feedburner.com/LucaGuidi &amp;gt;&amp;gt; luca.xml&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;Now we need our custom SAX parser:&lt;br /&gt;
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;require 'rubygems'
require 'xml/libxml'
require 'handler'

class SaxParser
  def initialize(xml)
    @parser = XML::SaxParser.new
    @parser.string = xml
    @parser.callbacks = Handler.new
  end

  def parse
    @parser.parse
    @parser.callbacks.elements
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;We have just wrapped the SAX parser from &lt;strong&gt;libxml&lt;/strong&gt; and we have registered our first class as callback handler.&lt;/p&gt;

&lt;p&gt;Now we are going to improve the handler to recognize and save the post titles:&lt;br /&gt;
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;class Handler
  attr_accessor :elements

  def initialize
    @elements = []
  end

  def on_start_element(element, attributes)
    @print = true if element == 'title'
  end

  def on_characters(characters = '')
    @elements &amp;lt;&amp;lt; characters if @print
  end

  def on_end_element(element)
    @print = false
  end

  # Handle all missing methods of the SAX events chain.
  # You can implement or omit one or many of those methods, without any raising Exception.
  # 
  # The complete chain is:
  #   on_start_document
  #   on_processing_instruction(instruction, arguments)
  #   on_start_element(element, attributes)
  #   on_characters(characters = '')
  #   on_end_element(element)
  #   on_end_document
  def method_missing(method_name, *attributes, &amp;amp;block)
  end
  end&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;When the handler is instantiated we create an internal array to store our results, then when we find and &lt;code&gt;title&lt;/code&gt; element we set on &lt;code&gt;true&lt;/code&gt; the &lt;code&gt;print&lt;/code&gt; flag. When it's &lt;code&gt;true&lt;/code&gt; we can store the data into &lt;code&gt;elements&lt;/code&gt;, then we set on &lt;code&gt;false&lt;/code&gt; on the ending handler of the element.&lt;/p&gt;

&lt;h3&gt;Usage&lt;/h3&gt;
&lt;p&gt;We create a trivial script:&lt;br /&gt;
  &lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;#!/usr/bin/env ruby
require 'sax_parser'

xml = open(ARGV[0], 'r').collect { |l| l }.join
puts SaxParser.new(xml).parse&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;
&lt;p&gt;From the shell:&lt;br /&gt;
  &lt;pre&gt;&lt;code class=&quot;shell&quot;&gt;./parse luca.xml&lt;/code&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;SAX is less elegant and easy than DOM, but could be very useful in certain cases.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.lucaguidi.com/">
    <author>
      <name>luca</name>
    </author>
    <id>tag:www.lucaguidi.com,2008-01-26:173</id>
    <published>2008-01-26T14:32:00Z</published>
    <updated>2008-01-26T14:58:55Z</updated>
    <category term="Ruby on Rails"/>
    <link href="http://www.lucaguidi.com/2008/1/26/click-to-globalize-high-resolution-video-tutorial" rel="alternate" type="text/html"/>
    <title>Click To Globalize: High Resolution Video Tutorial</title>
<content type="html">
            &lt;p&gt;&lt;a href=&quot;http://www.lucaguidi.com/videos/click_to_globalize_getting_started.mov&quot; title=&quot;Click To Globalize: Getting Started&quot;&gt;&lt;img src=&quot;http://lucaguidi.com/assets/2008/1/26/click_to_globalize_getting_started.png&quot; height=&quot;300&quot; alt=&quot;Click To Globalize: Getting Started [High Resolution]&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The video tutorial for &lt;a href=&quot;http://www.lucaguidi.com/pages/click-to-globalize&quot; title=&quot;Click to Globalize&quot;&gt;Click to Globalize&lt;/a&gt; is now available in high resolution: &lt;a href=&quot;http://www.lucaguidi.com/videos/click_to_globalize_getting_started.mov&quot; title=&quot;Click To Globalize: Getting Started&quot;&gt;Click To Globalize: Getting Started&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
</feed>
