<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Mike Burns, Coder</title>
	<atom:link href="http://mikeburnscoder.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://mikeburnscoder.wordpress.com</link>
	<description></description>
	<lastBuildDate>Sat, 06 Jun 2009 21:42:10 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='mikeburnscoder.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/4a53b41a99e7b67d96d3392aefd33388?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Mike Burns, Coder</title>
		<link>http://mikeburnscoder.wordpress.com</link>
	</image>
			<item>
		<title>An Infinite List of Fibonacci Numbers in Ruby</title>
		<link>http://mikeburnscoder.wordpress.com/2009/06/06/an-infinite-list-of-fibonacci-numbers-in-ruby/</link>
		<comments>http://mikeburnscoder.wordpress.com/2009/06/06/an-infinite-list-of-fibonacci-numbers-in-ruby/#comments</comments>
		<pubDate>Sat, 06 Jun 2009 21:11:47 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[benchmarks]]></category>
		<category><![CDATA[fibonacci]]></category>
		<category><![CDATA[infinite lists]]></category>
		<category><![CDATA[lazy lists]]></category>
		<category><![CDATA[memory profiling]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scanl]]></category>
		<category><![CDATA[space complexity]]></category>
		<category><![CDATA[time complexity]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/?p=60</guid>
		<description><![CDATA[So I was reading through the Haskell Prelude when I stumbled across `scanl' as a kind of abstraction over `foldl'. I stared, and thought, and stared some more, and couldn&#8217;t come up with a use for it; a quick Web search revealed exactly one use: Fibonacci numbers.
(In retrospect: duh.)
So here are all the Fibonacci numbers [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=60&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>So I was reading through the Haskell <a href="http://www.haskell.org/onlinereport/standard-prelude.html">Prelude</a> when I stumbled across <code>`<a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:scanl">scanl</a>'</code> as a kind of abstraction over <code>`<a href="http://haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:foldl">foldl</a>'</code>. I stared, and thought, and stared some more, and couldn&#8217;t come up with a use for it; a quick Web search revealed exactly one use: Fibonacci numbers.</p>
<p>(In retrospect: duh.)</p>
<p>So here are all the Fibonacci numbers in Haskell:</p>
<pre>fibs = 0 : scanl (+) 1 fibs</pre>
<p>As you can see this makes use of infinite, recursive lists. So I wrote this in Ruby.</p>
<p>First I needed infinite lists:</p>
<pre class="brush: ruby;">
class LazyEmpty
  def empty?
    true
  end
end

class LazyCons
  attr_reader :first

  def initialize(first, &amp;rest)
    @first = first
    @rest = rest
    @rest_called = false
  end

  def rest
    if @rest_called
      @rest
    else
      @rest_called = true
      @rest = @rest.call
    end
  end

  def empty?
    false
  end
end
</pre>
<p>And now that I have such a thing, I need behavior on it. For example, <code>#take</code> will produce the first <var>n</var> elements of such a list:</p>
<pre class="brush: ruby;">
class LazyEmpty
  def take(n)
    LazyEmpty.new
  end
end
class LazyCons
  def take(n)
    if n &lt; 0
      self
    elsif n.zero?
      [self.first]
    else
      self.rest.take(n-1) + [self.first]
    end
  end
end
</pre>
<p>So now I can get at the elements:</p>
<pre class="brush: ruby;">
irb(main):001:0&gt; l = LazyCons.new(1) { LazyCons.new(2) { LazyCons.new(3) { LazyCons.new(4) { LazyEmpty.new }}}}
=&gt; #&lt;LazyCons:0x7f656ee21208 @rest_called=false, @rest=#&lt;Proc:0x00007f656ee212a8@(irb):2&gt;, @first=1&gt;
irb(main):002:0&gt; l.take(2)
=&gt; [3, 2, 1]
</pre>
<p>To get the most fun definition for the list of Fibonacci numbers I need <code>#scanl</code>:</p>
<pre class="brush: ruby;">
class LazyEmpty
  def scanl(q, &amp;f)
    LazyCons.new(q) { LazyEmpty.new }
  end
end

class LazyCons
  def scanl(q, &amp;f)
    LazyCons.new(q) { self.rest.scanl(f.call(q, self.first), &amp;f) }
  end
end
</pre>
<p>So now I have all the parts needed:</p>
<pre class="brush: ruby;">
def fibs
  LazyCons.new(0) { fibs.scanl(1) {|x,y| x + y} }
end
</pre>
<p>See?</p>
<pre class="brush: ruby;">
irb(main):008:0&gt; fibs.take(10)
=&gt; [55, 34, 21, 13, 8, 5, 3, 2, 1, 1, 0]
</pre>
<p>That is to say, the <var>n</var>th Fibonacci number is the first element from <code>take(<var>n</var>)</code>.</p>
<pre class="brush: ruby;">
def fib(n)
  fibs.take(n).first
end
</pre>
<p>At this point I wondered how it performed, especially against the na&iuml;ve implementation. So I used <a href="http://www.ruby-doc.org/core/classes/Benchmark.html">Benchmark.rb</a> and <a href="http://ruby-prof.rubyforge.org/">ruby-prof</a> to compare <code>#fib_naive</code>, <code>#fib_tail</code> (the tail-call rewrite of the na&iuml;ve implementation), <code>#fib_while</code> (the while loop rewrite of the tail-call rewrite), and <code>#fib_inf_list</code> (as defined above) &hellip; and the infinite list was not in last place!</p>
<pre>
       user       system      total        real
naive 12.020000   2.140000  14.160000 ( 14.174045)
tail   0.000000   0.000000   0.000000 (  0.010399)
while  0.020000   0.000000   0.020000 (  0.008730)
inf    3.360000   0.150000   3.510000 (  3.513216)

naive memory:
Thread ID: 70118283774380
Total: 970.630000

 %self     total     self     wait    child    calls  name
  5.11    970.63    49.61     0.00   921.02 17710000  Object#fib_naive-1 (fib_benchmarks.rb:6}
  1.01      9.79     9.79     0.00     0.00 17710000  Fixnum#- (ruby_runtime:0}
  0.94      9.16     9.16     0.00     0.00 17710500  Fixnum#&lt; (ruby_runtime:0}
  0.53      5.17     5.17     0.00     0.00  8855000  Fixnum#+ (ruby_runtime:0}
  0.00     73.73     0.00     0.00    73.73        1  Integer#times (ruby_runtime:0}
  0.00     73.73     0.00     0.00    73.73      500  Proc#call (ruby_runtime:0}
</pre>
<pre>
  0.00     73.73     0.00     0.00    73.73      500  Object#fib_naive (fib_benchmarks.rb:6}
  0.00     73.73     0.00     0.00    73.73        1  Object#profile (fib_benchmarks.rb:48}

tail memory:
Thread ID: 70118283774380
Total: 0.630000

 %self     total     self     wait    child    calls  name
  6.35      0.63     0.04     0.00     0.59    10500  Object#fib_tail_aux-1 (fib_benchmarks.rb:18}
  1.59      0.01     0.01     0.00     0.00    10500  Fixnum#+ (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00    10500  Fixnum#- (ruby_runtime:0}
  0.00      0.05     0.00     0.00     0.05      500  Object#fib_tail_aux (fib_benchmarks.rb:18}
  0.00      0.05     0.00     0.00     0.05      500  Object#fib_tail (fib_benchmarks.rb:14}
  0.00      0.05     0.00     0.00     0.05        1  Integer#times (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00    11000  Fixnum#zero? (ruby_runtime:0}
  0.00      0.05     0.00     0.00     0.05        1  Object#profile (fib_benchmarks.rb:48}
  0.00      0.05     0.00     0.00     0.05      500  Proc#call (ruby_runtime:0}

while memory:
Thread ID: 70118283774380
Total: 0.040000

 %self     total     self     wait    child    calls  name
 50.00      0.04     0.02     0.00     0.02      500  Object#fib_while (fib_benchmarks.rb:26}
 25.00      0.01     0.01     0.00     0.00    11000  Fixnum#&gt; (ruby_runtime:0}
 25.00      0.01     0.01     0.00     0.00    10500  Fixnum#+ (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00    10500  Fixnum#- (ruby_runtime:0}
  0.00      0.04     0.00     0.00     0.04        1  Integer#times (ruby_runtime:0}
  0.00      0.04     0.00     0.00     0.04        1  Object#profile (fib_benchmarks.rb:48}
  0.00      0.04     0.00     0.00     0.04      500  Proc#call (ruby_runtime:0}

inf memory:
Thread ID: 70118283774380
Total: 63.810000

 %self     total     self     wait    child    calls  name
  3.96      2.53     2.53     0.00     0.00   126500  LazyCons#initialize (./fib_inf_list.rb:18}
  1.13     42.51     0.72     0.00    41.79   220500  Proc#call-1 (ruby_runtime:0}
  0.66      3.16     0.42     0.00     2.74   115500  LazyCons#scanl (./fib_inf_list.rb:37}
  0.53      2.94     0.34     0.00     2.60   126500  Class#new (ruby_runtime:0}
  0.38     37.95     0.24     0.00    37.71   105000  LazyCons#rest-1 (./fib_inf_list.rb:24}
  0.16      0.10     0.10     0.00     0.00   105000  Fixnum#+ (ruby_runtime:0}
  0.13     63.81     0.08     0.00    63.73    10500  LazyCons#take-1 (./fib_inf_list.rb:41}
  0.11      0.07     0.07     0.00     0.00   126500  #allocate (ruby_runtime:0}
  0.08      0.25     0.05     0.00     0.20    11000  Object#fibs (./fib_inf_list.rb:56}
  0.03      0.02     0.02     0.00     0.00    10500  Array#+ (ruby_runtime:0}
  0.03      4.60     0.02     0.00     4.58      500  Proc#call (ruby_runtime:0}
  0.02      4.48     0.01     0.00     4.47    10500  LazyCons#rest (./fib_inf_list.rb:24}
  0.00      4.60     0.00     0.00     4.60        1  Integer#times (ruby_runtime:0}
  0.00      4.58     0.00     0.00     4.58      500  LazyCons#take (./fib_inf_list.rb:41}
  0.00      4.60     0.00     0.00     4.60        1  Object#profile (fib_benchmarks.rb:48}
  0.00      4.58     0.00     0.00     4.58      500  Object#fib_inf_list (./fib_inf_list.rb:52}
  0.00      0.00     0.00     0.00     0.00    10500  Fixnum#- (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00    11000  Fixnum#&lt; (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00    11000  Fixnum#zero? (ruby_runtime:0}
  0.00      0.00     0.00     0.00     0.00      500  Array#first (ruby_runtime:0}
</pre>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/60/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/60/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/60/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=60&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2009/06/06/an-infinite-list-of-fibonacci-numbers-in-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Powerset in Ruby Using the List Monad</title>
		<link>http://mikeburnscoder.wordpress.com/2009/05/30/powerset-in-ruby-using-the-list-monad/</link>
		<comments>http://mikeburnscoder.wordpress.com/2009/05/30/powerset-in-ruby-using-the-list-monad/#comments</comments>
		<pubDate>Sat, 30 May 2009 18:25:34 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[monads]]></category>
		<category><![CDATA[monkeypatch]]></category>
		<category><![CDATA[powerset]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/?p=54</guid>
		<description><![CDATA[While trying to think of good, quick interview questions I stumbled across power set (thanks to Mike DiStaula for suggesting it). After 10 minutes of hacking in Ruby I discovered that it&#8217;s not a reasonable replacement for our current starter question (it takes too long), but it&#8217;s also a fun problem to solve.
Then I wandered [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=54&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>While trying to think of good, quick interview questions I stumbled across <a href="http://en.wikipedia.org/wiki/Powerset">power set</a> (thanks to <a href="http://mikedistaula.com/">Mike DiStaula</a> for suggesting it). After 10 minutes of hacking in Ruby I discovered that it&#8217;s not a reasonable replacement for our current starter question (it takes too long), but it&#8217;s also a fun problem to solve.</p>
<p>Then I wandered across this definition of power set in Haskell:</p>
<pre>
powerset = filterM (const [True, False])
</pre>
<p>Well, that was easy. So I set out to write that in Ruby. That is, I wanted to write this:</p>
<pre class="brush: ruby;">
class Array
  def powerset
    self.filterM {|x| [true, false]}
  end
end
</pre>
<p>First thing I need is a list monad:</p>
<pre class="brush: ruby;">
class Array
  def self.unit(x)
    [x]
  end

  def bind(&amp;f)
    self.inject([]) do |acc, e|
      acc + f.call(e)
    end
  end
end
</pre>
<p>I quickly hit my weekly reminder that Ruby does not have <code>Array#rest</code>, so I added that:</p>
<pre class="brush: ruby;">
class Array
  def rest
    r = self[1..-1]
    r.nil? ? [] : r
  end
end
</pre>
<p>Whew; now things are easier. Next I needed <code>filterM</code>, so I added it to <code>Enumerable</code> as a faithful copy <a href="http://haskell.org/ghc/docs/latest/html/libraries/base/src/Control-Monad.html#filterM">from Haskell</a> (expanding the <code>do</code> notation into the <code>&gt;&gt;=</code> notation):</p>
<pre class="brush: ruby;">
module Enumerable
  def filterM(&amp;p)
    return self.class.unit([]) if self.empty?
    p.call(self.first).bind do |flg|
      self.rest.filterM(&amp;p).bind do |ys|
        self.class.unit(flg ? ([self.first] + ys) : ys)
      end
    end
  end
end
</pre>
<p>Now my original <code>Array#powerset</code> method works:</p>
<pre class="brush: ruby;">
irb(main):013:0&gt; [1,2,3].powerset
=&gt; [[1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], []]
</pre>
<p>I expect you to write that quickly in your next interview.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/54/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/54/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/54/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=54&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2009/05/30/powerset-in-ruby-using-the-list-monad/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Correctly Handle OpenID Updates</title>
		<link>http://mikeburnscoder.wordpress.com/2008/11/08/correctly-handle-openid-updates/</link>
		<comments>http://mikeburnscoder.wordpress.com/2008/11/08/correctly-handle-openid-updates/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 16:10:37 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[shoulda]]></category>
		<category><![CDATA[tests]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/?p=50</guid>
		<description><![CDATA[OpenID is pretty well established as a login infrastructure, but a topic often ignored is correctly letting the user change his saved OpenID. Don&#8217;t just save the text they enter! Verify that they&#8217;ve entered their valid OpenID.
The user model needs to pass this test:

should_have_db_column :new_openid_identity, :type =&#62; 'string'

The view on /account/edit needs to pass this [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=50&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://openid.net/">OpenID</a> is pretty well established as a login infrastructure, but a topic often ignored is correctly letting the user change his saved OpenID. Don&#8217;t just save the text they enter! <strong>Verify that they&#8217;ve entered their valid OpenID</strong>.</p>
<p>The user model needs to pass this test:</p>
<pre class="brush: ruby;">
should_have_db_column :new_openid_identity, :type =&gt; 'string'
</pre>
<p>The view on /account/edit needs to pass this test:</p>
<pre class="brush: ruby;">
context &quot;logged in&quot; do
  setup { session[:user_id] = Factory(:user).id }

  context &quot;GET to edit&quot; do
    setup { get :edit }

    should &quot;have a form for their OpenID info&quot; do
      assert_select 'form[action=?][method=post]', openid_path do
        assert_select 'input[type=hidden][name=_method][value=put]'
        assert_select 'input[type=text][name=?]',
                      'user[new_openid_identity]'
        assert_select 'input[type=submit]'
      end
    end
  end
end
</pre>
<p>And, most importantly, the OpenidsController needs to pass the test suite in <a href="http://gist.github.com/23084">gist 23084</a>.</p>
<p>(All these tests assume <a href="http://thoughtbot.com/projects/factory_girl">FactoryGirl</a> and <a href="http://thoughtbot.com/projects/shoulda">Shoulda</a>; re-write in <a href="http://rspec.info/">RSpec</a> or <a href="http://pyunit.sourceforge.net/">PyUnit</a> or whatever as you see fit.) </p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/50/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/50/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/50/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=50&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2008/11/08/correctly-handle-openid-updates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Save Those Receipts!</title>
		<link>http://mikeburnscoder.wordpress.com/2008/10/22/save-those-receipts/</link>
		<comments>http://mikeburnscoder.wordpress.com/2008/10/22/save-those-receipts/#comments</comments>
		<pubDate>Thu, 23 Oct 2008 00:54:17 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[moodswings]]></category>
		<category><![CDATA[railsrumble]]></category>
		<category><![CDATA[wheresthemilkat]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/?p=46</guid>
		<description><![CDATA[Over the weekend I was on a team of (potential) winners participating in the 2008 Rails Rumble. The application idea was something that I had prototyped for myself years ago and quickly lost, and it solves the problem I had at the time:
I was living near Fenway, and I suffered from too many choices of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=46&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Over the weekend I was on <a href="http://railsrumble.com/teams/giant-robots">a team of (potential) winners</a> participating in the 2008 <a href="http://railsrumble.com/">Rails Rumble</a>. The application idea was something that I had prototyped for myself years ago and quickly lost, and it solves the problem I had at the time:</p>
<p>I was living near Fenway, and I suffered from too many choices of where to purchase milk (and other groceries). The best solution, to me, was to track the price of milk at various shops so I could have an accurate measurement of which was cheapest, or if there were any correlations I could use to predict the price.</p>
<p>That&#8217;s it.</p>
<p><img src="http://www.milkyfan.com/images/adopt/milky.gif" alt="Milky" style="float:right;" /></p>
<p>So <a href="http://chadpytel.com/">Chad</a>, Joe, <a href="http://www.micahrich.com/">Micah</a>, and myself met the day before it started and mapped out a gameplan for <a href="http://wheresthemilkat.r08.railsrumble.com/">Where&#8217;s The Milk At</a>. We watched <a href="http://www.youtube.com/watch?v=kWUil383us4">Blur&#8217;s &#8220;Coffee &amp; TV&#8221;</a> for <a href="http://www.milkyfan.com/">visual inspiration</a>, drew mocks on paper, and discussed just how awesome we&#8217;re gonna rock.</p>
<p>Chad, Micah, and myself set to work at 8PM EDT on Friday (midnight GMT), lasting until 2:30AM. Fueled by <a href="http://www.theuppercrustpizzeria.com/">pizza</a>, we knocked out most of the server setup, sign up and sign up (both <a href="http://github.com/thoughtbot/clearance">password</a> and <a href="http://github.com/rails/open_id_authentication">OpenID</a>), page layout and design, and the logo.</p>
<p>The next day Joe joined in to hack from 9AM to 9PM (Chad stayed until midnight), fixing some bugs and propelling forward with some crazy JavaScript. More pizza was ordered, and Joe&#8217;s girlfriend stopped by with some delicious, large cookies.</p>
<p>I felt unrested and failed to pull my own weight on Saturday, but on Sunday we all worked full-steam toward the 8PM EDT deadline. We found browser incompatibilities with two hours to go, and two bugs in our code with an hour to go; we were down to the wire, but we got everything in with 30 minutes to spare. (Joe used those 30 minutes to improve the JavaScript.)</p>
<p>All of this was caught on video.</p>
<p>Inspired by this weekend of hacking for 32.5 hours, I&#8217;ve started work on another idea I suggested during the brainstorming (<a href="http://github.com/mike-burns/moodswings">word blogging</a>), with the intent of doing a 12-hour code sprint on Saturday with anyone who is willing to join. Find me on IRC to join in.</p>
  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/46/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/46/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/46/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=46&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2008/10/22/save-those-receipts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>

		<media:content url="http://www.milkyfan.com/images/adopt/milky.gif" medium="image">
			<media:title type="html">Milky</media:title>
		</media:content>
	</item>
		<item>
		<title>Uniquify an array of hashes in Ruby</title>
		<link>http://mikeburnscoder.wordpress.com/2008/01/18/uniquify-an-array-of-hashes-in-ruby/</link>
		<comments>http://mikeburnscoder.wordpress.com/2008/01/18/uniquify-an-array-of-hashes-in-ruby/#comments</comments>
		<pubDate>Sat, 19 Jan 2008 01:06:20 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[eigenclass]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[singleton]]></category>
		<category><![CDATA[uniq]]></category>
		<category><![CDATA[unique]]></category>
		<category><![CDATA[uniqueness]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/2008/01/18/uniquify-an-array-of-hashes-in-ruby/</guid>
		<description><![CDATA[Array#uniq is a handy Ruby method that produces an array of distinct elements. So, for example, [1,2,3,3,3].uniq produces [1,2,3].
However, this fails on an array of hashes. For example, [{}, {}].uniq actually produces [{},{}]. That&#8217;s not what I wanted, recently.
It turns out that #uniq uses the methods #hash and #eql? to determine uniqueness, and Hash#hash produces [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=44&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><code>Array#uniq</code> is a handy Ruby method that produces an array of distinct elements. So, for example, <code>[1,2,3,3,3].uniq</code> produces <code>[1,2,3]</code>.</p>
<p>However, this fails on an array of hashes. For example, <code>[{}, {}].uniq</code> actually produces <code>[{},{}]</code>. That&#8217;s not what I wanted, recently.</p>
<p>It turns out that <code>#uniq</code> uses the methods <code>#hash</code> and <code>#eql?</code> to determine uniqueness, and <code>Hash#hash</code> produces the <code>object_id</code>, and <code>{}.eql?({})</code> produces <code>false</code>.</p>
<p>To solve this, I redefined <code>#hash</code> and <code>#eql?</code> for the hash instances before I put them in the array:</p>
<pre class="brush: ruby;">
h = {}
class &lt;&lt;h
  def hash
    values.inject(0) { |acc,value| acc + value.hash }
  end

  def eql?(a_hash)
    self == a_hash
  end
end
</pre>
<p>It should be noted that calling <code>#dup</code> on this hash will then screw things up, but that&#8217;s common to all Ruby eigenclass fun.</p>
<p>However, you could just use a proper class instead of a hash, &#8217;cause this isn&#8217;t Perl.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mikeburnscoder.wordpress.com/44/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mikeburnscoder.wordpress.com/44/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/44/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/44/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/44/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=44&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2008/01/18/uniquify-an-array-of-hashes-in-ruby/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Spider bugfix</title>
		<link>http://mikeburnscoder.wordpress.com/2007/11/10/spider-bugfix/</link>
		<comments>http://mikeburnscoder.wordpress.com/2007/11/10/spider-bugfix/#comments</comments>
		<pubDate>Sat, 10 Nov 2007 05:35:27 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bugfix]]></category>
		<category><![CDATA[crawl]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[spider]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/2007/11/10/spider-bugfix/</guid>
		<description><![CDATA[There were two issues with version 0.4.0 of Spider, both caught by Henri Cook. These are now fixed in 0.4.1:

As documented, you use IncludedInMemcached like this: require 'spider/included_in_memcached' .
Sometimes HTTP redirects assume a base URL; this is now handled.

       <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=43&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>There were two issues with version 0.4.0 of Spider, both caught by Henri Cook. These are now fixed in 0.4.1:</p>
<ul>
<li>As documented, you use <code>IncludedInMemcached</code> like this: <code>require 'spider/included_in_memcached'</code> .</li>
<li>Sometimes HTTP redirects assume a base URL; this is now handled.</li>
</ul>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mikeburnscoder.wordpress.com/43/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mikeburnscoder.wordpress.com/43/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/43/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/43/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/43/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=43&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2007/11/10/spider-bugfix/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Spider with memcached</title>
		<link>http://mikeburnscoder.wordpress.com/2007/11/02/spider-with-memcached/</link>
		<comments>http://mikeburnscoder.wordpress.com/2007/11/02/spider-with-memcached/#comments</comments>
		<pubDate>Fri, 02 Nov 2007 22:14:25 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crawl]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[spider]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/2007/11/02/spider-with-memcached/</guid>
		<description><![CDATA[The problem with Spider has been that it can use all your memory. The reason is that the Web is a graph, and to avoid cycles Spider stores each URL it encounters. Since the Web is a really, really, really gigantic graph, you eventually run out of memory.
Now you can use memcached to use not [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=42&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>The problem with Spider has been that it can use all your memory. The reason is that the Web is a graph, and to avoid cycles Spider stores each URL it encounters. Since the Web is a really, really, really gigantic graph, you eventually run out of memory.</p>
<p>Now you can use <a href="http://www.danga.com/memcached/">memcached</a> to use not only all the memory on one computer, but all the memory on many computers!</p>
<pre class="brush: ruby;">
require 'spider'
require 'spider/included_in_memcached'
SERVERS = ['10.0.10.2:11211','10.0.10.3:11211','10.0.10.4:11211']
Spider.start_at('http://mike-burns.com/') do |s|
  s.check_already_seen_with IncludedInMemcached.new(SERVERS)
end
</pre>
<p>Also new in this version is a tutorial on <a href="http://spider.rubyforge.org/">the main Spider Web site</a>. Yeah!</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mikeburnscoder.wordpress.com/42/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mikeburnscoder.wordpress.com/42/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/42/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/42/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/42/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=42&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2007/11/02/spider-with-memcached/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Proxied Spider</title>
		<link>http://mikeburnscoder.wordpress.com/2007/11/01/proxied-spider/</link>
		<comments>http://mikeburnscoder.wordpress.com/2007/11/01/proxied-spider/#comments</comments>
		<pubDate>Thu, 01 Nov 2007 22:01:43 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crawl]]></category>
		<category><![CDATA[crawler]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[indexer]]></category>
		<category><![CDATA[net::http]]></category>
		<category><![CDATA[net::http::configuration]]></category>
		<category><![CDATA[proxy]]></category>
		<category><![CDATA[spider]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/2007/11/01/proxied-spider/</guid>
		<description><![CDATA[Aha: if you need to proxy your Spider calls, look no further than the HTTP Configuration gem.
I didn&#8217;t write this, and have yet to use it, but I think it goes like this:

http_conf = Net::HTTP::Configuration.new(:proxy_host =&#62; 'localhost', :proxy_port =&#62; 8881)
http_conf.apply do
  Spider.start_at('http://example.com/')
end

So next up will be a tutorial with stuff like this and other [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=41&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Aha: if you need to proxy your <a href="http://spider.rubyforge.net/">Spider</a> calls, look no further than the <a href="http://httpconfig.rubyforge.org/">HTTP Configuration</a> gem.</p>
<p>I didn&#8217;t write this, and have yet to use it, but I think it goes like this:</p>
<pre class="brush: ruby;">
http_conf = Net::HTTP::Configuration.new(:proxy_host =&gt; 'localhost', :proxy_port =&gt; 8881)
http_conf.apply do
  Spider.start_at('http://example.com/')
end
</pre>
<p>So next up will be a tutorial with stuff like this and other cool stuff, plus a way to use <a href="http://www.danga.com/memcached/">memcached</a> with Spider.</p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mikeburnscoder.wordpress.com/41/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mikeburnscoder.wordpress.com/41/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/41/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/41/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/41/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=41&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2007/11/01/proxied-spider/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Spider: API changes, setup and teardown, HTTP headers</title>
		<link>http://mikeburnscoder.wordpress.com/2007/11/01/spider-api-changes-setup-and-teardown-http-headers/</link>
		<comments>http://mikeburnscoder.wordpress.com/2007/11/01/spider-api-changes-setup-and-teardown-http-headers/#comments</comments>
		<pubDate>Thu, 01 Nov 2007 04:00:59 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[crawl]]></category>
		<category><![CDATA[crawler]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[indexer]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[spider]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/2007/11/01/spider-api-changes-setup-and-teardown-http-headers/</guid>
		<description><![CDATA[The newest version of Spider, 0.3.0, is hitting your gem tree Real Soon Now. This release features:

Set the headers to a HTTP request.
This can be used to set the cookies, user agent, and many other fine things.
setup and teardown handlers.
Seems like a good place to set the headers if the headers are conditional on the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=40&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>The newest version of Spider, 0.3.0, is hitting your gem tree Real Soon Now. This release features:</p>
<dl>
<dt>Set the headers to a HTTP request.</dt>
<dd>This can be used to set the cookies, user agent, and many other fine things.</dd>
<dt><code>setup</code> and <code>teardown</code> handlers.</dt>
<dd>Seems like a good place to set the headers if the headers are conditional on the URL.</dd>
<dt>Say <code>:every</code>, not <code>:any</code>.</dt>
<dd>Makes more sense this way, I claim.</dd>
<dt>All the handlers take the same three arguments.</dt>
<dd>The URL, the response, and&#8212;new&#8212;the calling URL.</dd>
</dl>
<p>Next on my list: proxies, a better way to store whether an URL has been seen, then a tutorial.</p>
<p>Get it the usual way: <code>gem install spider</code></p>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mikeburnscoder.wordpress.com/40/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mikeburnscoder.wordpress.com/40/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/40/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/40/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/40/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=40&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2007/11/01/spider-api-changes-setup-and-teardown-http-headers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
		<item>
		<title>Spider bug fix release</title>
		<link>http://mikeburnscoder.wordpress.com/2007/10/23/spider-bug-fix-release/</link>
		<comments>http://mikeburnscoder.wordpress.com/2007/10/23/spider-bug-fix-release/#comments</comments>
		<pubDate>Wed, 24 Oct 2007 03:34:30 +0000</pubDate>
		<dc:creator>Mike Burns</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[bugfix]]></category>
		<category><![CDATA[crawl]]></category>
		<category><![CDATA[crawler]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[indexer]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[spider]]></category>

		<guid isPermaLink="false">http://mikeburnscoder.wordpress.com/2007/10/23/spider-bug-fix-release/</guid>
		<description><![CDATA[John Nagro immediately reported errors with the Spider Ruby gem, so I&#8217;ve fixed them in 0.2.1. You should upgrade, especially if you want support for:

URLs without any path component (e.g. http://example.com?s=1).
HTTP redirects.
HTTPS.

John also had some good ideas, so here is what is in the works:

The ability to construct a complete graph of every node found.
Defeat [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=39&subd=mikeburnscoder&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><a href="http://northeastern.facebook.com/profile.php?id=1812620">John Nagro</a> immediately reported errors with the Spider Ruby gem, so I&#8217;ve fixed them in 0.2.1. You should upgrade, especially if you want support for:</p>
<ul>
<li>URLs without any path component (e.g. <code>http://example.com?s=1</code>).</li>
<li>HTTP redirects.</li>
<li>HTTPS.</li>
</ul>
<p>John also had some good ideas, so here is what is in the works:</p>
<ul>
<li>The ability to construct a complete graph of every node found.</li>
<li>Defeat cycles using <a href="http://www.danga.com/memcached/">memcached</a> instead of memory (closely related to the above bullet).</li>
<li>A <code>Net::HTTP</code> abstraction that makes it easier to e.g. use a proxy or replace HTTP.</li>
</ul>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/mikeburnscoder.wordpress.com/39/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/mikeburnscoder.wordpress.com/39/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/mikeburnscoder.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/mikeburnscoder.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/mikeburnscoder.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/mikeburnscoder.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/mikeburnscoder.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/mikeburnscoder.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/mikeburnscoder.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/mikeburnscoder.wordpress.com/39/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/mikeburnscoder.wordpress.com/39/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/mikeburnscoder.wordpress.com/39/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=mikeburnscoder.wordpress.com&blog=255131&post=39&subd=mikeburnscoder&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://mikeburnscoder.wordpress.com/2007/10/23/spider-bug-fix-release/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/01b9172e9f53e0955a1af7458752aa9b?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">mike-burns</media:title>
		</media:content>
	</item>
	</channel>
</rss>