<?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/"
	>

<channel>
	<title>Netphase &#187; scottned</title>
	<atom:link href="http://blog.netphase.com/author/scottned/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.netphase.com</link>
	<description>for a connected world</description>
	<lastBuildDate>Mon, 14 Dec 2009 21:40:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Ruby on Rails with Spring, Hibernate and JPA</title>
		<link>http://blog.netphase.com/2009/01/23/ruby-on-rails-with-spring-hibernate-and-jpa/</link>
		<comments>http://blog.netphase.com/2009/01/23/ruby-on-rails-with-spring-hibernate-and-jpa/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 18:56:42 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.netphase.com/?p=248</guid>
		<description><![CDATA[Scott led a session at Bar Camp extolling the virtues of running your Ruby on Rails app in a pure Java environment, accessing the same resources as your programming brethren.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m leading a discussion on this topic at the <a href="http://barcampcharlotte.com/">Charlotte BarCamp</a> tomorrow.</p>
<p>Many companies who have invested a lot of time and money in Java technology could still benefit greatly from Ruby on Rails by using it to build new sites that make use of their backend Java based services.</p>
<p>Here&#8217;s an example of an <a href="http://rspec.info/">RSpec</a> test that uses a Java DAO, provided by <a href="http://www.springsource.org">Spring</a> to access a database with <a href="http://java.sun.com/javaee/technologies/persistence.jsp">JPA</a> / <a href="http://www.hibernate.org/">Hibernate</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">it <span style="color:#996600;">&quot;should retrieve an Account by ID&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  load_data <span style="color:#996600;">&quot;dao/accounts.xml&quot;</span>
  dao = spring.<span style="color:#9900CC;">getBean</span> <span style="color:#996600;">'accountDao'</span>
  acct = dao.<span style="color:#9900CC;">find</span> <span style="color:#996600;">&quot;5000&quot;</span>
  acct.<span style="color:#9900CC;">should_not</span> be_nil
  acct.<span style="color:#9900CC;">getName</span>.<span style="color:#9900CC;">should</span> == <span style="color:#996600;">&quot;Alpha&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>It&#8217;s surprisingly easy to use a Spring context here by adding the following method to my spec_helper:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">import <span style="color:#996600;">'org.springframework.context.support.ClassPathXmlApplicationContext'</span>
import <span style="color:#996600;">'org.springframework.core.io.ClassPathResource'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> spring<span style="color:#006600; font-weight:bold;">&#40;</span>context_file=<span style="color:#996600;">&quot;beans.xml&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  java.<span style="color:#9900CC;">lang</span>.<span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">current_thread</span>.<span style="color:#9900CC;">context_class_loader</span> =
      JRuby.<span style="color:#9900CC;">runtime</span>.<span style="color:#9900CC;">getJRubyClassLoader</span>
  <span style="color:#0066ff; font-weight:bold;">@ctx</span> <span style="color:#006600; font-weight:bold;">||</span>= ClassPathXmlApplicationContext.<span style="color:#9900CC;">new</span> context_file
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Using that helper I am able to access any component managed by Spring.  As designed, Spring will wire up any required dependencies, provide a pooled database connection, and handle any other configuration necessary so that the bean returned is ready to use.</p>
<p>My test also uses <a href="http://www.dbunit.org/">DBUnit</a> to load an XML fixture.  It can do that by adding this method to spec_helper:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">import <span style="color:#996600;">'org.dbunit.database.DatabaseConnection'</span>
import <span style="color:#996600;">'org.dbunit.dataset.xml.FlatXmlDataSet'</span>
import <span style="color:#996600;">'org.dbunit.operation.DatabaseOperation'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> load_data<span style="color:#006600; font-weight:bold;">&#40;</span>data_file<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">begin</span>
    <span style="color:#0066ff; font-weight:bold;">@dataSource</span> <span style="color:#006600; font-weight:bold;">||</span>= spring.<span style="color:#9900CC;">getBean</span> <span style="color:#996600;">'dataSource'</span>
    <span style="color:#0066ff; font-weight:bold;">@conn</span> <span style="color:#006600; font-weight:bold;">||</span>= DatabaseConnection.<span style="color:#9900CC;">new</span> <span style="color:#0066ff; font-weight:bold;">@dataSource</span>.<span style="color:#9900CC;">getConnection</span>
    <span style="color:#0066ff; font-weight:bold;">@dataset</span> <span style="color:#006600; font-weight:bold;">||</span>=
        FlatXmlDataSet.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>ClassPathResource.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>data_file<span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">getInputStream</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#6666ff; font-weight:bold;">DatabaseOperation::CLEAN_INSERT</span>.<span style="color:#9900CC;">execute</span><span style="color:#006600; font-weight:bold;">&#40;</span>@conn, <span style="color:#0066ff; font-weight:bold;">@dataset</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span>
    <span style="color:#CC0066; font-weight:bold;">print</span> <span style="color:#996600;">&quot;load_data error: &quot;</span>, $!, <span style="color:#996600;">&quot;<span style="color:#000099;">\n</span>&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>DBUnit provides a useful way to load data fixtures into a test database.  The reason I&#8217;m using DBUnit instead of the more common YAML format used in Rails apps, is so that I can make use of the fixtures already available in the Java project.</p>
<p>Here&#8217;s what my DBUnit fixture looks like:</p>
<p>This combination of technologies seems like a pretty powerful combination to me, especially for those companies who are entrenched in Java and are looking for a way to improve their productivity.</p>
<p>I&#8217;m interested to know who else is using this type of setup.  Leave a comment and describe your experience.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2009/01/23/ruby-on-rails-with-spring-hibernate-and-jpa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>nested error_messages_for</title>
		<link>http://blog.netphase.com/2008/03/06/nested-error_messages_for/</link>
		<comments>http://blog.netphase.com/2008/03/06/nested-error_messages_for/#comments</comments>
		<pubDate>Thu, 06 Mar 2008 03:20:55 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2008/03/06/nested-error_messages_for/</guid>
		<description><![CDATA[I think lots of folks have run into this problem of using error_messages_for to display errors of nested or subordinate objects.  The current Rails method doesn&#8217;t handle it well.  In addition, there&#8217;s the problem of not being able to specify the full message.  So&#8230; I tackled this problem today and came up [...]]]></description>
			<content:encoded><![CDATA[<p>I think lots of folks have run into this problem of using error_messages_for to display errors of nested or subordinate objects.  The current Rails method doesn&#8217;t handle it well.  In addition, there&#8217;s the problem of not being able to specify the full message.  So&#8230; I tackled this problem today and came up with a pretty good solution using recursion.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> nested_error_messages_for<span style="color:#006600; font-weight:bold;">&#40;</span>object<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#CC00FF; font-weight:bold;">Symbol</span>, <span style="color:#CC0066; font-weight:bold;">String</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">member</span>? object.<span style="color:#9966CC; font-weight:bold;">class</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    object = instance_variable_get<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;@#{object}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">unless</span> object.<span style="color:#0000FF; font-weight:bold;">nil</span>? <span style="color:#006600; font-weight:bold;">||</span> object.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">count</span>.<span style="color:#9900CC;">zero</span>?
    error_messages = object.<span style="color:#9900CC;">errors</span>.<span style="color:#9900CC;">to_a</span>.<span style="color:#9900CC;">uniq</span>.<span style="color:#9900CC;">map</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>key, value<span style="color:#006600; font-weight:bold;">|</span>
      object2 = object.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>key<span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">if</span> object2.<span style="color:#9900CC;">is_a</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#CC0066; font-weight:bold;">Array</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        object2.<span style="color:#9900CC;">collect</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>obj<span style="color:#006600; font-weight:bold;">|</span> 
          content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:li</span>, nested_error_messages_for<span style="color:#006600; font-weight:bold;">&#40;</span>obj<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span> 
        <span style="color:#006600; font-weight:bold;">&#125;</span>
      <span style="color:#9966CC; font-weight:bold;">elsif</span> object2.<span style="color:#9900CC;">is_a</span>?<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:li</span>, nested_error_messages_for<span style="color:#006600; font-weight:bold;">&#40;</span>object2<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">elsif</span> value.<span style="color:#9900CC;">match</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>^\^<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#41;</span>
        content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:li</span>, value<span style="color:#006600; font-weight:bold;">&#91;</span>1..<span style="color:#9900CC;">value</span>.<span style="color:#9900CC;">length</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">else</span>
        content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:li</span>, 
           <span style="color:#996600;">&quot;#{key.underscore.split('_').join(' ').humanize} #{value}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>,
      content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:div</span>, 
        <span style="color:#996600;">&quot;#{object.class} has errors&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'error_field'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">+</span>
      content_tag<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:ul</span>, error_messages<span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#ff3333; font-weight:bold;">:class</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'error_block'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#996600;">''</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>To use it, just replace your current call to error_messages_for with nested_error_messages_for.  There&#8217;s nothing extra that needs to be done in the controller as with some recipes.  You&#8217;ll also want to make it look good with some CSS.</p>
<p>I&#8217;m pretty sure there&#8217;s more that could be done with this, but thought I&#8217;d present it here first and try to get some feedback before turning it into a gem.  Let me know how it works for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2008/03/06/nested-error_messages_for/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Extending ActiveRecord with count_since</title>
		<link>http://blog.netphase.com/2008/02/23/extending-activerecord-with-count_since/</link>
		<comments>http://blog.netphase.com/2008/02/23/extending-activerecord-with-count_since/#comments</comments>
		<pubDate>Sat, 23 Feb 2008 02:29:15 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2008/02/23/extending-activerecord-with-count_since/</guid>
		<description><![CDATA[I just implemented a statistics page for an application and found that I was using this pattern over and over again:

User.count&#40;:conditions =&#62; &#91;'created_at &#62; ?', 30.days.ago&#93;&#41;

Here&#8217;s a simple extension I made to ActiveRecord to DRY it up:

module ActiveRecord
  class Base
      def self.count_since&#40;time_ago&#41;
        [...]]]></description>
			<content:encoded><![CDATA[<p>I just implemented a statistics page for an application and found that I was using this pattern over and over again:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">count</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'created_at &gt; ?'</span>, 30.<span style="color:#9900CC;">days</span>.<span style="color:#9900CC;">ago</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Here&#8217;s a simple extension I made to ActiveRecord to <abbr title="Don't Repeat Yourself">DRY</abbr> it up:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> ActiveRecord
  <span style="color:#9966CC; font-weight:bold;">class</span> Base
      <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">count_since</span><span style="color:#006600; font-weight:bold;">&#40;</span>time_ago<span style="color:#006600; font-weight:bold;">&#41;</span>
        count<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:conditions</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'created_at &gt; ?'</span>, time_ago<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Put that snippet in a file in your lib directory.  I called mine rails_extensions.rb.  Then add <em>require &#8216;rails_extensions&#8217;</em> to the bottom of your environment.rb file.</p>
<p>Now you can just do:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">count_since</span><span style="color:#006600; font-weight:bold;">&#40;</span>30.<span style="color:#9900CC;">days</span>.<span style="color:#9900CC;">ago</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>That&#8217;s a little cleaner, don&#8217;t you think?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2008/02/23/extending-activerecord-with-count_since/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uninstall Apache</title>
		<link>http://blog.netphase.com/2008/01/30/uninstall-apache/</link>
		<comments>http://blog.netphase.com/2008/01/30/uninstall-apache/#comments</comments>
		<pubDate>Wed, 30 Jan 2008 18:21:35 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2008/01/30/uninstall-apache/</guid>
		<description><![CDATA[So, I&#8217;m sure many others have made the same mistake.  You downloaded the latest Apache, did the 3 step: 

configure &#8211;prefix=/usr/local &#8211;enable-mods-shared=all &#8211;enable-ssl &#8211;enable-proxy
make
sudo make install

Doh! That&#8217;s probably not what you wanted.  Now you have stuff like

/usr/local/build
/usr/local/icons

You&#8217;d have been better off going with Apache 2&#8217;s default prefix which is /usr/local/apache2.  The problem [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;m sure many others have made the same mistake.  You downloaded the latest Apache, did the 3 step: </p>
<ol>
<li>configure &#8211;prefix=/usr/local &#8211;enable-mods-shared=all &#8211;enable-ssl &#8211;enable-proxy</li>
<li>make</li>
<li>sudo make install</li>
</ol>
<p>Doh! That&#8217;s probably not what you wanted.  Now you have stuff like</p>
<ul>
<li>/usr/local/build</li>
<li>/usr/local/icons</li>
</ul>
<p>You&#8217;d have been better off going with Apache 2&#8217;s default prefix which is /usr/local/apache2.  The problem is there&#8217;s no uninstall!  If that&#8217;s happened to you and you just made the mistake a short time ago, try this:</p>
<ol>
<li>Make sure you have enough free space for a backup of /usr/local
<p>$ sudo du -sh /usr/local<br />
2.2G    /usr/local</p>
<p>$ df -h
</li>
<li>Back it up
<p>$ tar cvf /tmp/usr_local.tar /usr/local
</li>
<li>Find out which files you just installed
<p>$ sudo find . -type f -newerct &#8216;60 minutes ago&#8217; > /tmp/uninstall_files.txt</p>
<p>$ sudo find . -type d -newerct &#8216;60 minutes ago&#8217; > /tmp/uninstall_dirs.txt
</li>
<li>Inspect the file you just created and remove things that don&#8217;t belong (e.g. mysql)</li>
<li>Remove the files (don&#8217;t get creative and add -r to rm &#8212; <b>you did backup, right?</b>)
<p>$ cat uninstall_files.txt | sudo xargs rm</p>
<p>$ cat uninstall_dirs.txt | sudo xargs rmdir
</li>
</ol>
<p>Now, take off that prefix and try the 3-step again.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2008/01/30/uninstall-apache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autotest CPU Fix</title>
		<link>http://blog.netphase.com/2008/01/05/autotest-cpu-fix/</link>
		<comments>http://blog.netphase.com/2008/01/05/autotest-cpu-fix/#comments</comments>
		<pubDate>Sat, 05 Jan 2008 22:17:57 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2008/01/05/autotest-cpu-fix/</guid>
		<description><![CDATA[
Update 1/15/2008
Autotest and rspec both posted updates today.  Now, the way to fix this issue is slightly different:

Autotest.add_hook :run do &#124;autotest&#124;
  autotest.add_exception(/^\.\/vendor/)
  autotest.add_exception(/\.svn/)
end

Thanks Ryan and David for the updates!

I&#8217;ve been noticing in my current project that running autotest was constantly consuming about 25-30% of my cpu and causing my macbook pro to [...]]]></description>
			<content:encoded><![CDATA[<div style="background:#eee">
<b>Update 1/15/2008</b><br />
Autotest and rspec both posted updates today.  Now, the way to fix this issue is slightly different:</p>
<pre>
Autotest.add_hook :run do |autotest|
  autotest.add_exception(/^\.\/vendor/)
  autotest.add_exception(/\.svn/)
end
</pre>
<p>Thanks <a href="http://blog.zenspider.com/">Ryan</a> and <a href="http://blog.davidchelimsky.net/">David<a/> for <a href="http://blog.davidchelimsky.net/articles/2008/01/15/rspec-1-1-2-and-zentest-3-8-0">the updates</a>!
</div>
<p>I&#8217;ve been noticing in my current project that running autotest was constantly consuming about 25-30% of my cpu and causing my macbook pro to run really hot.  I did a little googling and found <a href="http://rails.aizatto.com/2007/11/28/taming-the-autotest-beast-with-fsevents/">this discussion</a> on the topic.</p>
<p>For me, my problem was definitely the vendor directory (~3500 files in 4 plugins: rspec, rspec_on_rails, restful_open_id_authentication and active_merchant).  I tried excluding the entire directory by adding this to my ~/.autotest file:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:initialize</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>autotest<span style="color:#006600; font-weight:bold;">|</span>
  autotest.<span style="color:#9900CC;">exceptions</span> <span style="color:#006600; font-weight:bold;">&lt;&lt;</span>
   <span style="color:#006600; font-weight:bold;">%</span>r<span style="color:#006600; font-weight:bold;">%</span>^\.<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>?:db<span style="color:#006600; font-weight:bold;">|</span>doc<span style="color:#006600; font-weight:bold;">|</span>log<span style="color:#006600; font-weight:bold;">|</span>public<span style="color:#006600; font-weight:bold;">|</span>script<span style="color:#006600; font-weight:bold;">|</span>vendor<span style="color:#006600; font-weight:bold;">|</span>previous_failures.<span style="color:#9900CC;">txt</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">%</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>However, that didn&#8217;t work.  After some investigation, I found out that the rspec_on_rails plugin in my vendor directory was subclassing Autotest::Rspec and setting it&#8217;s own exceptions string like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> initialize
  <span style="color:#9966CC; font-weight:bold;">super</span>
  <span style="color:#0066ff; font-weight:bold;">@exceptions</span> = 
   <span style="color:#006600; font-weight:bold;">%</span>r<span style="color:#006600; font-weight:bold;">%</span>^\.<span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>?:db<span style="color:#006600; font-weight:bold;">|</span>doc<span style="color:#006600; font-weight:bold;">|</span>log<span style="color:#006600; font-weight:bold;">|</span>public<span style="color:#006600; font-weight:bold;">|</span>script<span style="color:#006600; font-weight:bold;">|</span>vendor\<span style="color:#006600; font-weight:bold;">/</span>rails<span style="color:#006600; font-weight:bold;">|</span>previous_failures.<span style="color:#9900CC;">txt</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">%</span>
...</pre></div></div>

<p>See the problem?  It dutifully calls super so AutoTest:initialize can do it&#8217;s stuff (including calling my hook) and then wipes out the exception string with it&#8217;s own.</p>
<p>So, I browsed the lib/autotest.rb code and found another hook.  Adding this to my ~/.autotest now lowers the cpu usage to about 5%.  Huzzah!</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Autotest.<span style="color:#9900CC;">add_hook</span> <span style="color:#ff3333; font-weight:bold;">:run</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>autotest<span style="color:#006600; font-weight:bold;">|</span>
  autotest.<span style="color:#9900CC;">exceptions</span> = <span style="color:#CC00FF; font-weight:bold;">Regexp</span>.<span style="color:#9900CC;">union</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">/</span>^\.\<span style="color:#006600; font-weight:bold;">/</span>vendor<span style="color:#006600; font-weight:bold;">/</span>, autotest.<span style="color:#9900CC;">exceptions</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2008/01/05/autotest-cpu-fix/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Drudge afraid of Forbes?  Not!</title>
		<link>http://blog.netphase.com/2007/11/08/drudge-afraid-of-forbes-not/</link>
		<comments>http://blog.netphase.com/2007/11/08/drudge-afraid-of-forbes-not/#comments</comments>
		<pubDate>Thu, 08 Nov 2007 15:36:51 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[Facebook]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2007/11/08/drudge-afraid-of-forbes-not/</guid>
		<description><![CDATA[On Tuesday, Forbes posted a bizarre article, Fear Among Facebook Developers, that seems to suggest if you&#8217;re not a big brand on the Internet then you should just pack your bags and go home.
The issue is that Facebook is going to start putting more of its own ads throughout the site.  Big surprise.  [...]]]></description>
			<content:encoded><![CDATA[<p>On Tuesday, Forbes posted a bizarre article, <a href="http://www.forbes.com/2007/11/06/facebook-small-developers-tech-internet-cx_rr_1106techfacebook_print.html">Fear Among Facebook Developers</a>, that seems to suggest if you&#8217;re not a big brand on the Internet then you should just pack your bags and go home.</p>
<p>The issue is that Facebook is going to start putting more of its own ads throughout the site.  Big surprise.  However, Facebook also allows apps to generally put whatever they want in the application canvas, including ads.  If Facebook advertises something else outside the canvas then it&#8217;s not that big a deal to me.  As a developer, I don&#8217;t really need them to provide me an &#8220;ad widget&#8221; as the author suggests; I can use <a href="http://www.google.com/adsense">Google Ads</a>, <a href="http://www.coudal.com/deck/">The Deck</a> or whatever.</p>
<blockquote><p>
If a small application developer is under the illusion that he can win a fight with a big-brand widget, that’s a bad plan, says Gerd Leonhard, chief executive of Sonific, which recently launched a music widget on Facebook.
</p></blockquote>
<p>Strange comment.  &#8220;Sonific&#8221; doesn&#8217;t sound like a big brand to me, and yet they just launched a music widget?  Good for them.  However, it seems to me like they&#8217;re trying to scare off competition.  Also, the net is the quintessential mechanism for some little guy knocking over &#8220;big brands&#8221;.  In fact, that&#8217;s what Facebook is!</p>
<p><a href="http://apps.facebook.com/netphase-madlibs/"><img src="http://blog.netphase.com/wp-content/uploads/2007/11/madlibs-car-logo.png" alt="madlibs_car_logo.png" border="0" width="75" height="72" align="right" style="margin: 0 1em 2em" /></a></p>
<p>A couple months ago, we launched our first Facebook app for <a href="http://imin.com">I&#8217;m&nbsp;In</a>.  Within a week about 1000 people had installed it to check it out.  That&#8217;s pretty cool, considering all we had to do was get it added to the Facebook directory.  So, over the long run will it generate more transactions for I&#8217;m In?  I think so, but time will tell.  For a site like that, it wouldn&#8217;t take too many added sales to cover the cost of building an app like <a href="http://apps.facebook.com/netphase-madlibs/">Mad&nbsp;Libs™</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2007/11/08/drudge-afraid-of-forbes-not/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>acts_as_amazon_product</title>
		<link>http://blog.netphase.com/2007/09/26/acts_as_amazon_product/</link>
		<comments>http://blog.netphase.com/2007/09/26/acts_as_amazon_product/#comments</comments>
		<pubDate>Wed, 26 Sep 2007 20:31:58 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[Acts As Amazon Product]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2007/09/26/acts_as_amazon_product/</guid>
		<description><![CDATA[Today we released a new Ruby Gem that makes integrating with Amazon E-Commerce Service (ECS) a snap.  It&#8217;s called acts_as_amazon_product and you can find it on RubyForge.
All that&#8217;s necessary to integrate any of your existing models with Amazon is to add a require line to the top of your model file and then an [...]]]></description>
			<content:encoded><![CDATA[<p>Today we released a new Ruby Gem that makes integrating with Amazon E-Commerce Service (ECS) a snap.  It&#8217;s called acts_as_amazon_product and you can <a href="http://rubyforge.org/projects/aaap/">find it on RubyForge</a>.</p>
<p>All that&#8217;s necessary to integrate any of your existing models with Amazon is to add a <em>require</em> line to the top of your model file and then an acts_as_amazon_product line just inside your class definition.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'acts_as_amazon_product'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> Book <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  acts_as_amazon_product<span style="color:#006600; font-weight:bold;">&#40;</span>
      <span style="color:#ff3333; font-weight:bold;">:asin</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'isbn'</span>, <span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'title'</span>, 
      <span style="color:#ff3333; font-weight:bold;">:access_key</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'0123456'</span>, 
      <span style="color:#ff3333; font-weight:bold;">:associate_tag</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'assoc-20'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>After this, you can access Amazon data in your controllers or views like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#0066ff; font-weight:bold;">@book</span> = Book.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'Getting Things Done'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">amazon</span>.<span style="color:#9900CC;">isbn</span>
<span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">amazon</span>.<span style="color:#9900CC;">title</span>
<span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">amazon</span>.<span style="color:#9900CC;">author</span>
<span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">amazon</span>.<span style="color:#9900CC;">small_image_url</span>
&nbsp;
<span style="color:#0066ff; font-weight:bold;">@book</span>.<span style="color:#9900CC;">amazon</span>.<span style="color:#9900CC;">get</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'itemattributes/foobar'</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>The code does not require changing any current database tables.  It only requires adding one migration for a single new table used to cache responses from Amazon:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>.<span style="color:#9900CC;">connection</span>.<span style="color:#9900CC;">create_table</span> <span style="color:#ff3333; font-weight:bold;">:amazon_products</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
  t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:asin</span>, <span style="color:#ff3333; font-weight:bold;">:string</span>
  t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:xml</span>, <span style="color:#ff3333; font-weight:bold;">:text</span>
  t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:created_at</span>, <span style="color:#ff3333; font-weight:bold;">:datetime</span>
  t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:amazonable_id</span>, <span style="color:#ff3333; font-weight:bold;">:integer</span>
  t.<span style="color:#9900CC;">column</span> <span style="color:#ff3333; font-weight:bold;">:amazonable_type</span>, <span style="color:#ff3333; font-weight:bold;">:string</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2007/09/26/acts_as_amazon_product/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Session Patent Awarded</title>
		<link>http://blog.netphase.com/2007/06/03/web-session-patent-awarded/</link>
		<comments>http://blog.netphase.com/2007/06/03/web-session-patent-awarded/#comments</comments>
		<pubDate>Sun, 03 Jun 2007 22:48:03 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2007/06/03/web-session-patent-awarded/</guid>
		<description><![CDATA[I just found out that the U.S. Patent office issued patent number 7,188,176 naming me as primary inventor for an &#8220;Apparatus, system, and method for maintaining a persistent data state on a communications network&#8221;.  I&#8217;m pretty stunned.  I did the work for this back in 1998 for Priceline and they filed for the [...]]]></description>
			<content:encoded><![CDATA[<p>I just found out that the U.S. Patent office issued <a href="http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&#038;Sect2=HITOFF&#038;d=PALL&#038;p=1&#038;u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&#038;r=1&#038;f=G&#038;l=50&#038;s1=7188176.PN.&#038;OS=PN/7188176&#038;RS=PN/7188176">patent number 7,188,176</a> naming me as primary inventor for an &#8220;Apparatus, system, and method for maintaining a persistent data state on a communications network&#8221;.  I&#8217;m pretty stunned.  I did the work for this back in 1998 for <a href="http://priceline.com">Priceline</a> and they filed for the patent in 2000.  So, I guess I&#8217;m now &#8220;officially&#8221; an Inventor.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2007/06/03/web-session-patent-awarded/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Apache Log Quick Summary</title>
		<link>http://blog.netphase.com/2007/05/10/apache-log-quick-summary/</link>
		<comments>http://blog.netphase.com/2007/05/10/apache-log-quick-summary/#comments</comments>
		<pubDate>Thu, 10 May 2007 19:46:23 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2007/05/10/apache-log-quick-summary/</guid>
		<description><![CDATA[Sometimes I set up a quick site for a client and want to summarize hits without setting up awstats.  So, I wrote a quick and dirty script to sum up the hits per day in Apache&#8217;s access_log file.
Example:

$ cklog access_log

04-15-2007: 21
04-16-2007: 2134
04-17-2007: 304
04-18-2007: 6960
04-19-2007: 951
04-20-2007: 412

Here&#8217;s the script:

require 'date'
&#160;
daily = Hash.new
File.open&#40;ARGV&#91;0&#93; &#124;&#124; &#34;access_log&#34;, &#34;r&#34;&#41; [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes I set up a quick site for a client and want to summarize hits without setting up awstats.  So, I wrote a quick and dirty script to sum up the hits per day in Apache&#8217;s access_log file.</p>
<p>Example:</p>
<pre>
$ cklog access_log

04-15-2007: 21
04-16-2007: 2134
04-17-2007: 304
04-18-2007: 6960
04-19-2007: 951
04-20-2007: 412
</pre>
<p>Here&#8217;s the script:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'date'</span>
&nbsp;
daily = <span style="color:#CC00FF; font-weight:bold;">Hash</span>.<span style="color:#9900CC;">new</span>
<span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#CC0066; font-weight:bold;">open</span><span style="color:#006600; font-weight:bold;">&#40;</span>ARGV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">||</span> <span style="color:#996600;">&quot;access_log&quot;</span>, <span style="color:#996600;">&quot;r&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>file<span style="color:#006600; font-weight:bold;">|</span>
  <span style="color:#9966CC; font-weight:bold;">while</span> line = file.<span style="color:#CC0066; font-weight:bold;">gets</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> line =~ <span style="color:#006600; font-weight:bold;">/</span><span style="color:#006600; font-weight:bold;">&#40;</span>\d<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006666;">2</span><span style="color:#006600; font-weight:bold;">&#125;</span>\<span style="color:#006600; font-weight:bold;">/</span>\w<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006666;">3</span><span style="color:#006600; font-weight:bold;">&#125;</span>\<span style="color:#006600; font-weight:bold;">/</span>\d<span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006666;">4</span><span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#006600; font-weight:bold;">*</span>GET\s<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&#91;</span>^\?\s<span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">+</span><span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">/</span>
      date = <span style="color:#CC00FF; font-weight:bold;">Date</span>.<span style="color:#9900CC;">strptime</span> $<span style="color:#006666;">1</span>, <span style="color:#996600;">'%d/%b/%Y'</span>
      daily<span style="color:#006600; font-weight:bold;">&#91;</span>date<span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#006666;">0</span> <span style="color:#9966CC; font-weight:bold;">if</span> daily<span style="color:#006600; font-weight:bold;">&#91;</span>date<span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#0000FF; font-weight:bold;">nil</span>?
      daily<span style="color:#006600; font-weight:bold;">&#91;</span>date<span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">+</span> <span style="color:#006666;">1</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
daily.<span style="color:#9900CC;">sort</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>d, f<span style="color:#006600; font-weight:bold;">|</span> 
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;#{d.strftime '%m-%d-%Y'}: #{f}&quot;</span>
<span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2007/05/10/apache-log-quick-summary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby Web Crawler</title>
		<link>http://blog.netphase.com/2007/04/19/ruby-web-crawler/</link>
		<comments>http://blog.netphase.com/2007/04/19/ruby-web-crawler/#comments</comments>
		<pubDate>Thu, 19 Apr 2007 21:26:43 +0000</pubDate>
		<dc:creator>scottned</dc:creator>
				<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.netphase.com/2007/04/19/ruby-web-crawler/</guid>
		<description><![CDATA[Here&#8217;s a web crawler I wrote awhile back.  It&#8217;s pretty simple, but does the job.  If you need something more, you might try rdig or Nutch.
You can run this as a stand-alone script and just pass in the URL to crawl as an argument.
[ruby]
require &#8216;net/http&#8217;
require &#8216;uri&#8217;
class SiteCrawler
  def initialize(url)
    [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a web crawler I wrote awhile back.  It&#8217;s pretty simple, but does the job.  If you need something more, you might try <a href="http://rdig.rubyforge.org/">rdig</a> or <a href="http://lucene.apache.org/nutch/">Nutch</a>.</p>
<p>You can run this as a stand-alone script and just pass in the URL to crawl as an argument.</p>
<p>[ruby]<br />
require &#8216;net/http&#8217;<br />
require &#8216;uri&#8217;</p>
<p>class SiteCrawler<br />
  def initialize(url)<br />
    @site_uri = URI.parse(url)<br />
    @site_uri.path = &#8220;/&#8221; if @site_uri.path == &#8220;&#8221;<br />
    @visited = Hash.new<br />
    @queue = Array.new<br />
    addPath(@site_uri.path)<br />
    puts &#8220;Initialized site crawl for #{@site_uri}&#8221;<br />
  end</p>
<p>  def addPath(path)<br />
    @queue.push path<br />
    @visited[path] = false<br />
  end</p>
<p>  def getPage(path)<br />
    begin<br />
      uri = @site_uri.clone<br />
      uri.path = uri.path + path if path != &#8220;/&#8221;<br />
      puts &#8220;getting #{uri}&#8221;<br />
      response = Net::HTTP.get_response(uri)<br />
    rescue Exception<br />
      puts &#8220;Error: #{$!}&#8221;<br />
      return &#8220;&#8221;<br />
    end<br />
    return response.body<br />
  end</p>
<p>  def queueLocalLinks(html)<br />
    html.scan(/<a href\s*=\s*["']([^"]+)"/i) {|w|<br />
      uri = URI.parse("#{w}")<br />
      if !@visited.has_key?(uri.path) and<br />
         (uri.relative? or uri.host == @site_uri.host)<br />
        addPath(uri.path)<br />
      end<br />
    }<br />
  end</p>
<p>  def crawlSite()<br />
    while (!@queue.empty?)<br />
      uri = @queue.shift<br />
      page = getPage(uri)<br />
      yield uri, page<br />
      queueLocalLinks(page)<br />
      @visited[uri] = true<br />
    end<br />
  end<br />
end</p>
<p>sc = SiteCrawler.new(ARGV[0])<br />
@pages = Array.new<br />
sc.crawlSite { |url, page_text|<br />
  @pages << url<br />
  # SITE_INDEX << { :url => url, :context => page_text }<br />
}<br />
[/ruby]</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.netphase.com/2007/04/19/ruby-web-crawler/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
