<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Ideas For Dozens</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/" />
    <link rel="self" type="application/atom+xml" href="http://www.urbanhonking.com/ideasfordozens/atom.xml" />
    <id>tag:www.urbanhonking.com,2008-04-13:/ideasfordozens//44</id>
    <updated>2008-04-30T17:45:24Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Publishing Platform 4.0</generator>

<entry>
    <title>Time to Organize Recording Artists: Why an Enforcement-based Strategy is a Mistake for the Music Industry</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/04/time-to-organize-recording-art.html" />
    <id>tag:www.urbanhonking.com,2008:/ideasfordozens//44.14146</id>

    <published>2008-04-29T21:41:47Z</published>
    <updated>2008-04-30T17:45:24Z</updated>

    <summary> Celia Hirschman from KCRW&apos;s On the Beat In the most recent On the Beat, Celia Hirschman advocates for the Musician&apos;s Union to take a more active stand for musicians&apos; rights online. In a world where only 42% of internet...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="business" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="grabbit" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="music" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p style="float:left; margin: 10px; margin-top:0; font-size: small">
	<img src="http://www.kcrw.com/etc/programs/ob/ob_335x120.jpg" title="Celia Hirschman from KCRW's On the Beat"/><br /><em>Celia Hirschman from KCRW's On the Beat</em>
</p>
<p>
	In <a href="http://www.kcrw.com/etc/programs/ob/ob080423time_to_organize_rec">the most recent On the Beat</a>, Celia Hirschman advocates for <a href="http://www.musiciansunion.org.uk/">the Musician's Union</a> to take a more active stand for musicians' rights online. In a world where <a href="http://bits.blogs.nytimes.com/2008/04/17/amazon-gains-share-of-shrinking-paid-music-market/?em&ex=1208664000&en=2e42c4bf40b0e867&ei=5087%0A&scp=2-b&sq=Amazon&st=nyt">only 42% of internet users say they pay for music</a>, she argues, the Union has a responsibility to advocate for musicians' "right to be paid for their efforts anytime their music is played". She notes the failure of legislative attempts to extract revenue for musicians from peer-to-peer file sharing, mp3 blogs, and CD burning and lays the blame at the feet of the Union as the primary organization that represents musicians.	
</p>

<p>
	I agree with half of this argument. The Musician's Union <em>has</em> been embarrassingly lax in fighting the real battles that matter for artists in the modern music distribution landscape. What has the Musician's Union done to stop the labels from <a href="http://www.techdirt.com/articles/20060428/036245.shtml">cheating artists out of revenue from iTunes downloads</a>? How about to stop them wasting their shrinking budgets on <a href="http://www.amazon.com/Rock-Office-Ballad-Dan-Kennedy/dp/1565125096/grabbit-20">glamorous perks and inflated short-run corporate profits</a> rather than developing new artists with the possibility of long and successful careers? Or what about to force them to <a href="http://nymag.com/daily/entertainment/2008/03/why_wont_the_music_business_hire.html">hire people who can figure out new business models that fit the new technology</a>?
</p>

<p>None of these battles receive the slightest mention in Hirscman's critique of the Union. She ignores the losses artists have suffered by being forced into vastly inequitable relationships with labels and instead highlights the ways in which the industry has failed to fully extract revenue from new forms of music consumption and fandom.</p>

<p>This wrong-headed focus on enforcement over transformation is symptomatic of the problems plaguing the record industry as a whole. Hirschman's catalogue of Union failings closely resembles a punchlist of <a href="http://www.riaa.com/physicalpiracy.php">RIAA complaints and talking points</a>. Focusing on missed revenue from new forms of fandom while the music industry's entire distribution and profit model sinks into irrelevance is like getting upset over a spilled glass of champagne on the deck of the Titanic.
	</p>

<p>This mistake derives directly from the principle that Hirschman articulates in the piece: that artists "have the right to be paid for their efforts anytime their music is played." This same idea was proposed recently by Peter Kirn at <a href="http://createdigitalmusic.com/2008/03/26/tech-blogger-michael-arrington-thinks-you-musicians-owe-the-web-money/">Create Digital Music</a>:
	<blockquote cite="http://createdigitalmusic.com/2008/03/26/tech-blogger-michael-arrington-thinks-you-musicians-owe-the-web-money/"> 
Recorded music has value to consumers. And, in business, if something has value somewhere, it's a business.
</blockquote>
	</p>
<p>
	This is a core principle of the industry's thinking right now and it is obviously, palpably false. In middle school, when a friend played me <a href="http://grabb.it/artists/b689fe3119f4">Sebadoh</a> off of a walkman that he'd smuggled to school, transforming me in a single moment into a lifelong fan of indie rock, was that "theft"? Should Sebadoh have gotten paid? 
	
	When I worked at <a href="http://www.pixpatisserie.com/">a local patisserie</a> I used to play my favorite CDs throughout my shifts and would often write the band names and album titles down for intrigued customers. Should the shop have had to track and regulate everything we played so they could pay royalties to the artists?
</p>

<p>This last is something of a trick question since enforcement of this kind of public performance royalty is something for which Hirschman specifically lauds rights-enforcers like <a href="http://ascap.org/">ASCAP</a>:
	<blockquote cite="http://www.kcrw.com/etc/programs/ob/ob080423time_to_organize_rec">
		If you walk into a restaurant, nightclub or boutique and hear music playing, chances are very good a performance-rights organization have demanded compensation. These rights societies literally go door-to-door to insure their members get paid for music
	</blockquote>
	</p>
<p>
	Hirschman could not have this issue more wrong. ASCAP contacted the patisserie while I worked there saying they'd observed us playing music controlled by their members and we had to either cut  it out, sign up for a very expensive pay service they were offering, or face a lawsuit. The business owners felt like they'd been shaken down by the mafia. Their response was to stop playing ASCAP music altogether and instead to put together a library of local music which we had explicit permission from the artists to play <em>without royalties</em>. Maintaining this library was a lot of work and we rapidly fell back into the old system of playing whatever we wanted, including ASCAP music, without permission, but now in an environment of greater fear and resentment. I would bet that a similar story holds for most places you actually visit beyond corporate chains: if you walk in and hear good music playing it is either local or in explicit defiance of an ASCAP threat.</p>

<p>And this story is a parable of what's wrong with focusing on enforcement. Enforcement alienates consumers and tastemakers. It tarnishes the reputations of artists and the organizations that should represent them. It forces natural music consumption and sharing patterns underground. Possibly worst, enforcement distracts artists and the industry itself from solving the huge existential issues that they face.</p>

<p>
	There is one piece of information from Hirschman's piece, however, that does hold out hope for the music industry if they do ever overcome these distractions and decide to face the real challenge of transformation: 42% of internet users pay for music. That's an enormous number. How many internet users pay for news? Or search? Or social networks? I don't hear anyone in these businesses complaining that their industry is in decline. That's an enormous number and it reflects the incredible amount of passion that exists for music online. If the industry can't find a way to transform that passion into a functional profitable business, it won't be because because the users outfoxed their enforcements efforts. They'll have only themselves to blame.
</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/music" rel="tag">music</a>, <a href="http://www.technorati.com/tags/industry" rel="tag">industry</a>, <a href="http://www.technorati.com/tags/on+the+beat" rel="tag">on the beat</a>, <a href="http://www.technorati.com/tags/Celia+Hirschman" rel="tag">Celia Hirschman</a>, <a href="http://www.technorati.com/tags/kcrw" rel="tag">kcrw</a>, <a href="http://www.technorati.com/tags/enforcement" rel="tag">enforcement</a>, <a href="http://www.technorati.com/tags/piracy" rel="tag">piracy</a>, <a href="http://www.technorati.com/tags/riaa" rel="tag">riaa</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>RAD 0.2.2 Released: Arduino 0011 Support</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/04/rad-022-released-arduino-0011.html" />
    <id>tag:www.urbanhonking.com,2008:/ideasfordozens//44.14145</id>

    <published>2008-04-29T20:15:41Z</published>
    <updated>2008-04-29T22:28:25Z</updated>

    <summary>On sunday night, I released version 0.2.2 of the Ruby Arduino Development gem. The main focus of this update is compatibility with version 0011 of the Arduino software tools (follow that link for the release notes). While 0010 may still...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="RAD" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>On sunday night, I released version 0.2.2 of the <a href="http://rad.rubyforge.org">Ruby Arduino Development gem<a/>. The main focus of this update is compatibility with <a href="http://www.arduino.cc/en/Main/ReleaseNotes">version 0011 of the Arduino software tools</a> (follow that link for the release notes). While 0010 may still work with this new version of RAD, 0011 is now the default and upgrading is highly encourages. Download it here: <a href="http://www.arduino.cc/en/Main/Software">Arduino 0011</a></p>.
	
<p>
	This release also includes a patch to fix a problem with type-compatibility between RAD's var system and some Arduino function return values courtesy of <a href="http://blog.unnature.net/">David Michael</a>. David also gave what looks like a great talk about RAD at <a href="http://nycruby.org/wiki/">NYC.rb</a>: <a href="http://blog.unnature.net/post/31202116">Ruby Meets Worlds</a>, which includes a really nice example of using the observer pattern to communicate with an Arduino over a serial port that portends really well for one of the exciting things we've been talking about on the RAD Google Group: <a href="http://groups.google.com/group/ruby-arduino-development/browse_thread/thread/3997e7c3e91ccfd6">an interactive serial console</a>.
</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/ruby" rel="tag">ruby</a>, <a href="http://www.technorati.com/tags/arduino" rel="tag">arduino</a>, <a href="http://www.technorati.com/tags/rad" rel="tag">rad</a>, <a href="http://www.technorati.com/tags/0011" rel="tag">0011</a>, <a href="http://www.technorati.com/tags/computerkraft" rel="tag">computerkraft</a>, <a href="http://www.technorati.com/tags/console" rel="tag">console</a>, <a href="http://www.technorati.com/tags/serial" rel="tag">serial</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>On Politics: How Proprietary vs. Open Source is like Obama vs. Clinton and why we need to get over it and get on with the work</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/04/on-politics-how-obama-vs-clint.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.14125</id>

    <published>2008-04-25T05:29:11Z</published>
    <updated>2008-04-25T06:42:00Z</updated>

    <summary><![CDATA[ "The enemy isn't Microsoft. The enemy is non-use" &mdash; Matt Asay, The Ten Commandments of Open Source For the past month, watching Hillary Clinton and Barack Obama &mdash; two relatively noble politicians who largely want the same good things...]]></summary>
    <author>
        <name></name>
        
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p><blockquote cite="http://itc.conversationsnetwork.org/shows/detail3522.html">
"The enemy isn't Microsoft. The enemy is non-use" 
</blockquote>
&mdash; <a href="http://asay.blogspot.com/">Matt Asay</a>, <a href="http://itc.conversationsnetwork.org/shows/detail3522.html">The Ten Commandments of Open Source</a>
</p>

<p>
For the past month, watching Hillary Clinton and Barack Obama &mdash; two relatively noble politicians who largely want the same good things for this country &mdash; say and do silly things to each other over the most superficial of disagreements in an atmosphere of ever-increasing animosity, I've been experiencing a disgust that was strangely familiar. All month I struggled to place where I'd felt this particular variety of nausea before, what other phenomenon oozes this same poison. And then I figured it out: it's the old Open Source vs. Evil Corporation flamewar. It's Slashdot all over again.
</p>

<p>
	I won't alienate <a href="http://www.realclearpolitics.com/epolls/2008/president/us/democratic_presidential_nomination-191.html">40.4 percent of you</a> by telling you which side I think is which since the key point is this: when two groups with basically the same objectives spend their best energy beating on each other those objectives are guaranteed to stay largely unaccomplished.
</p>
<p>
And just like every day that Obama and Clinton spend attacking each other leaves less hope for those good goals the two candidates share, every flamewar, every easy attack on Microsoft, every knee jerk reaction against a company that charges for its software leaves less attention available to solve the problems we all share of data interoperability, scaling, user friendliness, etc. 
<p>
	It's a fine thing to stand up for important values like openness and freedom, and, gosh knows, we have real disagreements on some topics that deserve to be debated vigorously, but the constant mutual harassment and posturing actually make these debates harder to resolve. 
	</p>
	<p>Both sides are guilty of this and we pay a measurable cost for it.</p>
	<p>On the Open Source side, we tend to rule out technologies that reek of big corporate support even when they might be the best choice for the job and on the corporate side they tend to be too cautious, holding off on new ideas until they're blessed by the vendor of choice.</p>
	<p>For example, I recently had a good old fashioned geek out with <a href="http://www.neopoleon.com">Rory Blyth</a>, a college friend who went on to work at Microsoft. We spent a few hours having two of the oldest, least productive, and most fun coding conversations around: static vs. dynamic typing and SOAP vs. REST, as well as one new one that's shaping up to acquire a similar status: relational vs. document databases. While we seem to have an unbridgeable spiritual divide on the first topic, we each managed to convince each other, at least a little bit, on the last two. Rory did a strong job arguing in favor of the value of SOAP APIs for client implementors because of the strong level of automation and framework/IDE support that they enable and convincing me that at least some of my RESTful bias is inherited unquestioned from my community. Likewise, I managed to overcome Rory's profound SQL Server loyalty to convince him that relational databases, which were designed to perform original relational algebra in order to resolve a query with an unknown answer, are a bad architectural fit for most web applications which simply use them for object persistence. He left eager to check out <a href="http://incubator.apache.org/couchdb/">CouchDB</a> and I left resolved to explore <a href="http://www.zorched.net/2006/02/09/ruby-soap4r-for-web-services/"> Ruby's SOAP options</a>.
</p> 

<p>This is exactly the kind of outcome that gets crowded out of most online discourse by the flamewars and name calling. The animosity and ugliness pushes us deeper into our own camps, just as moderate politicians tend to head to the extremes of their own party during a hard fought primary.  
	</p>


<p>Well, the primary's over. I hereby declare it to be the general election. There's a world out there with real problems. From <a href="http://www.amazon.com/Worldchanging-Users-Guide-21st-Century/dp/0810930951/grabbit-20">global warming</a> to <a href="http://www.bloomberg.com/apps/news?pid=20601086&sid=aMvxEl_rz3Yk&refer=latin_america">the growing international food crisis</a> to <a href="http://www.riaa.com/whatwedo.php?content_selector=whatwedo_fbi_seal">the war on free speech</a>, the world faces serious challenges that can only be overcome by radically great technology, the license it's released under be damned.
</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/microsoft" rel="tag">microsoft</a>, <a href="http://www.technorati.com/tags/open" rel="tag">open</a>, <a href="http://www.technorati.com/tags/source" rel="tag">source</a>, <a href="http://www.technorati.com/tags/politics" rel="tag">politics</a>, <a href="http://www.technorati.com/tags/rory+blyth" rel="tag">rory blyth</a>, <a href="http://www.technorati.com/tags/soap" rel="tag">soap</a>, <a href="http://www.technorati.com/tags/rest" rel="tag">rest</a>, <a href="http://www.technorati.com/tags/couchdb" rel="tag">couchdb</a>, <a href="http://www.technorati.com/tags/flamewar" rel="tag">flamewar</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>RAD 0.2.1 Announcement and Dorkbotpdx 0x01 demo</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/04/rad-021-announcement-and-dorkb.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9108</id>

    <published>2008-04-07T20:33:00Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary> It&apos;s been an active few weeks in the world of RAD! First off, RAD 0.2.1 was released last week which includes a bunch of small features and bug-fixes: added first significant documentation fixed require &apos;yaml&apos; bug in makefile.rb added...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="RAD" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>
It's been an active few weeks in the world of <a href="http://rad.rubyforge.org">RAD</a>! First off, RAD 0.2.1 was released last week which includes a bunch of small features and bug-fixes:

<ul>                                                                 
<li>added <a href="http://rad.rubyforge.org/rdoc/">first significant documentation</a>                            </li>
<li>fixed require 'yaml' bug in makefile.rb                          </li>
<li>added <a href="http://rad.rubyforge.org/examples">examples directory</a> to the website</li>
<li>applied <a href="http://www.wulfden.org/TheShoppe.shtml">Brian Riley</a>'s SWSerLCDpa patch                           </li>
<li>experimental libraries system in vendor/libraries                </li>
<li>enhancements to the rad command: can set project config.         </li>
</ul>

The documentation and examples should be lots of help for those of you are just getting started. If you've got successful sketches, send them to me and I'll add them!
</p>
<p>I setup a <a href="http://groups.google.com/group/ruby-arduino-development">Ruby Arduino Development Google Group</a> for discussion amongst the growing group of contributors and users of the project. We've already got some fun stuff brewing there including someone working on a serial console, so drop by if you've got questions or want to participate.</p>
<p>
	Also, big thanks to <a href="http://www.wulfden.org/TheShoppe.shtml">Brian Riley of Really Bare Bones Arduino supplier Wulfden.org</a>. His patch here for SWSerLCDpa support hopefully marks the start of a great collaboration to get a bunch of important Arduino libraries ported to RAD including OneWire and I2C. Plus, he sent me a totally awesome data logging kit to play with!   
<a href="http://www.flickr.com/photos/unavoidablegrain/2385314571/" title="Wulfden Arduino Kit Unboxing: data logging kit by atduskgreg, on Flickr"><img src="http://farm4.static.flickr.com/3003/2385314571_6339690272.jpg" width="400"  alt="Wulfden Arduino Kit Unboxing: data logging kit" /></a>
</p>


<p>
	Last, but definitely not least, I presented about RAD at <a href="http://dorkbotpdx.org/wiki/dorkbotpdx_0x01">Dorkbotpdx 0x01</a> last week. I was fortunate enough to be in the good company of Ward Cunningham (who gave an amazing talk about his biologically-inspired <a href="http://c2.com/cybords/">Cybords</a> project) and many others. Jared from Dorkbotpdx shot video of the event which is now online. I did two demos, the basic blinky-LED hello world and a more advanced assembler sketch that drove a 7-segment LED and serial output (my segment starts at about 4:46):

<object type="application/x-shockwave-flash" width="400" height="225" data="http://www.vimeo.com/moogaloop.swf?clip_id=858480&amp;server=www.vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=">	<param name="quality" value="best" />	<param name="allowfullscreen" value="true" />	<param name="scale" value="showAll" />	<param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=858480&amp;server=www.vimeo.com&amp;fullscreen=1&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=" /></object>
</p>
<p>
	Watch the rest of the videos from the event here: <a href="http://www.vimeo.com/album/10961">Dorkbotpdx 0x01 on Vimeo</a>.
</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/arduino" rel="tag">arduino</a>, <a href="http://www.technorati.com/tags/ruby" rel="tag">ruby</a>, <a href="http://www.technorati.com/tags/rad" rel="tag">rad</a>, <a href="http://www.technorati.com/tags/dorkbotpdx" rel="tag">dorkbotpdx</a>, <a href="http://www.technorati.com/tags/wulfden" rel="tag">wulfden</a>, <a href="http://www.technorati.com/tags/electronics" rel="tag">electronics</a>, <a href="http://www.technorati.com/tags/physical" rel="tag">physical</a>, <a href="http://www.technorati.com/tags/computing" rel="tag">computing</a>, <a href="http://www.technorati.com/tags/portland" rel="tag">portland</a>, <a href="http://www.technorati.com/tags/oregon" rel="tag">oregon</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Guide to Getting Started with Merb and ActiveRecord</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/04/guide-to-getting-started-with.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9107</id>

    <published>2008-04-04T04:35:15Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary> Spent a while today getting up and running with Merb, the minimalist modular alternative Ruby framework from Ezra and the good people at Engine Yard. Merb has been in a bit of chaos these recent months as it&apos;s gone...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="learns_to" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p><img src="http://www.merbivore.com/img/header_logo.png" style="float:left; margin: 10px"/></p>
<p>Spent a while today getting up and running with <a href="http://www.merbivore.com/">Merb</a>, the minimalist modular alternative Ruby framework from Ezra and the good people at <a href="http://www.engineyard.com/">Engine Yard</a>. Merb has been in a bit of chaos these recent months as it's gone through a major reworking to acheive a whole new level of performance as well as honest-to-goodness modularity, including choosing your own ORM and templating system. I've been watching Merb's development for some time waiting for it to get to a level of stability that looked safe enough to dive in; their most recent release, 0.9.2, combined with pressing needs in a few exciting new <a href="http://grabb.it">Grabb.it</a> features, made today the day.</p>

<p>
My first day with Merb has been mostly great, but the one thing I found really sorely missing was a tutorial on how to get started. In all fairness, the Merb team promises left and right that copious documentation will be coming as they settle down to 1.0. In the meantime, I thought I'd pitch in for any brave early adopters out there with this Guide to Installing Merb and ActiveRecord.  
</p>

<h4>Acquire and Install the Source</h4>

<p>
 So, my goal here was to get from 0 (no Merb on my machine whatsoever), to running a hello world for accessing the database from an existing Rails project using ActiveRecord from within Merb. The first step was to acquire the source. One of the downsides to Merb's modular architecture is the complexity involved with installing it (again, all relevant disclaimers here about how the merb team will, I'm sure, be working to simplify and improve the process as they reach 1.0). At least for now, you actually have to get your hands on three different packages: merb-core (the base of the framework, a requirement), merb-more (has more advanced features like the command for actually creating a new app), and merb-plugins (this is where things like ORMs and templating systems live). Let's do that:

<code>
$ git clone git://github.com/wycats/merb-core.git
$ git clone git://github.com/wycats/merb-more.git
$ git clone git://github.com/wycats/merb-plugins.git
</code>

That'll get us the bleeding edge trunk version (about which more <a href="http://www.merbivore.com/get_merb.html#trunk
">here</a>).
</p>

<p>
Now that we've got the pieces, we need to install them, thusly:
<code>
$ cd merb-core ; rake install ; cd ..
$ cd merb-more ; rake install ; cd ..
$ cd merb-plugins/merb_activerecord; rake install; cd ..
</code>
</p>

<h4>Create a New Project and Configure it for Active Record</h4>

<p>We've got all the pieces; it's time to create our project and get it setup to use ActiveRecord. Go to the place you want to create your app and do this:
<code>
$ merb-gen app my_app
</code>

This is equivalent to the 'rails' command and will create your project directoy with <em>most</em> of what you need. But since a basic project in Merb is assumed to be simpler than a basic project in Rails, you'll quickly notice that you don't have a models directory. Since we're actually going to need a model if we want to connect up to a database with ActiveRecord, go ahead and create that directory and create a file inside if for your model just as you would in Rails, for example my_resourece.rb, which could look like this:
<code lang="ruby">
class MyResource &lt; ActiveRecord::Base
end
</code> 
</p>
<p>We'll probably want a controller as well, so create a new file: controllers/my_resources.rb:
<code lang="ruby">
class MyResources &lt; Application
  def show
    r = MyResource.find :first
    render r.some_method
  end
end
</code>
Notice that all Merb controllers inherit from Application just like Rails controllers inherit from Application::Controller. The naming choice there is kind of interesting because it reveals Merb's controller-centric history and philosophy (remember that the framework doesn't assume that we need models by default; it turns out there's a lot you can do with just controllers).
</p>
</p>
<p>
	Since we're using ActiveRecord, we'll obviously need to tell Merb that we want it to go ahead and actually load AR as our ORM. Go into config/init.rb in your project and uncomment the line that says "use_orm :activerecord".
</p>
<p>We're almost there! These last few steps will feel familiar from setting up a Rails app: letting the framework know about our route and database configuration. To set up your route, open up config/router.rb and, inside the 'prepare' block, add a line like this:
	
<code>
r.resources :my_resources
</code>
	
Merb's routes work pretty much like Rails's, but with a few more advanced features some of which are explained in the comments at the top of that file. If you need something other than standard RESTful routing, read those.	
</p>
<p>Finally, all we've got to do is configure database access and we'll be ready to roll. In Merb this looks exactly like Rails, in fact, I simply copied the database.yml file over from the Rails project that usually manages the db I wanted to access, dropped it in config/databse.yml and it worked straight out of the box.</p>

<p>Ok! If you've made it this far, then you're probably more than ready for the big reveal. In you project directory do this:
	
<code>
$ merb
</code>

The server will start and you'll get a few log messages in your terminal that look like this:
<code>
$ merb
 ~ Loaded DEVELOPMENT Environment...
 ~ loading gem 'merb_activerecord' from  ...
 ~ loading gem 'activerecord' from  ...
 ~ Connecting to database...
 ~ Compiling routes...
 ~ Using 'share-nothing' cookie sessions (4kb limit per client)
 ~ Using Mongrel adapter
</code>	

Once that settles down, browse to <a href="http://localhost:4000">http://localhost:4000</a> and you should see the Merb welcome screen. Go to your expected url to see the result of your handiwork: i.e. http://localhost:4000/my_resources/7
</p>
<p>If this works, you're officially up and running with Merb and ActiveRecord. If not, you'll see one of Merb's very stylish error screens and it'll be time to go to #merb on irc.freenode.net where all the friendly merbfolk hang out and are more than willing to help.</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/merb" rel="tag">merb</a>, <a href="http://www.technorati.com/tags/ruby" rel="tag">ruby</a>, <a href="http://www.technorati.com/tags/web" rel="tag">web</a>, <a href="http://www.technorati.com/tags/framework" rel="tag">framework</a>, <a href="http://www.technorati.com/tags/install" rel="tag">install</a>, <a href="http://www.technorati.com/tags/0.9.2" rel="tag">0.9.2</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Announcing RAD 0.2: Software Serial Support, Inline Assembler, and More!</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/03/announcing-rad-02-software-ser.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9106</id>

    <published>2008-03-16T22:51:10Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary> I&apos;m proud to announce a new release of the Ruby Arduino Development gem (RAD)! This release brings two major new features (software serial serial support and inline assembler), a major revamping of the hardware serial library, and a raft...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="RAD" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>
	I'm proud to announce a new release of the <a href="http://rad.rubyforge.org">Ruby Arduino Development gem (RAD)</a>! This release brings two major new features (software serial serial support and inline assembler), a major revamping of the hardware serial library, and a raft of other small features and bug fixes. I've got lots of details below, but first I wanted to thank Scott Windsor who contributed the software serial support as well as all the other people who wrote in with bug reports, ideas, and comments, and of course <a href="http://blog.bleything.net/">all the members of the RAD core team</a>. It's exciting to see RAD starting to support physical computing scenarios I've never had the hardware to work with myself.
</p>  

<h4>Inline Assembler</h4>

<p>
	I'm starting with this new feature not because it's necessarily the most import or most broadly useful, but just because I think it's the sexiest (which probably says something sick about me, but there you go)! RAD now offers a class method to all sub-classes of ArduinoSketch for writing routines in assembly language. You give the method three arguments: the name of the routine, its signature, and the assembly code you'd like to consitute its body. Here's an example script showing the method in action:
	
<code lang="ruby">
class AssemblerTest &lt; ArduinoSketch
  serial_begin
  
  def loop
    serial_println product(10,4)
  end
  
  assembler( :product, &quot;int product(int a, int b);&quot;,
    &lt;&lt;-CODE
    product:
      	mov  r18,r24	; move a to another register
      	ldi  r24,0		; clear running sum, used to coalesce product
      	ldi  r25,0		; sum = 0
      
      .loop:
      	tst  r18		  ; is a = 0? if so, we&#x27;re done
      	breq .end
      
      	mov  r19,r18	; copy a
      	andi r19,1		; is a % 2 == 0
      	breq .skip		
      
      	add  r24,r22	; add b to sum
      	adc  r25,r23
      
      .skip:
      	lsr  r18		  ; divide a by 2
      
      	clc			
      	rol  r22		  ; multiply b by 2
      	rol  r23
      	rjmp .loop
      
      .end:
      	ret
      	.size product, .-product
    CODE
  )
end

</code>

As you can see, the body of the assembly code is simply passed as a string to the 'assembler' method. In this case, all I'm doing is implementing multiplication of two integers. RAD takes your assembly code, adds some architecture-specific headers and other boilerplate, writes it to a source file, and makes sure that the compiler knows to compile it into object code and link it into your project during the build process. 
</p>
<p>I'm an asm newbie and I found that the hardest part of getting started learning the stuff was bootstrapping an environment where you could actually run your code and see the results. Hopefully this addition to RAD will smooth that process for people in a similar situation. Now all you've got to do is put your assembly code in an ArduinoSketch model like the one above, upload it to your Arduino, and read the board's serial output (for example by attaching to it with <a href="http://en.wikipedia.org/wiki/GNU_Screen">screen</a>). You can be writing (and debugging) your first assembler routines in seconds.</p>
	
<p>
	<em>It's worth noting that this feature wouldn't have been possible without <a href="http://people.reed.edu/~jimfix/">Reed College math professor Jim Fix</a> teaching me the basics of AVR assembler and the avr-gcc build process. Thanks, Jim!</em>
</p>

<h4>Software Serial Support</h4>
	<p>This feature came in as a patch from Scott Windsor. Scott was working on hooking up his <a href="http://www.ladyada.net/make/boarduino/">Boarduino</a> (an Arduino-compatible clone from <a href="http://www.ladyada.net">Lady Ada</a>) to a GPS module and a Serial LCD both of which require serial connections. Thankfully, Arduino provides a <a href="http://www.arduino.cc/en/Tutorial/SoftwareSerial">SoftwareSerial library</a> for doing serial connection on any of the board's digital i/o pins. Scott's patch gives you really convenient access to this functionality, thusly:

<code lang="ruby">
class MySketch &lt; ArduinoSketch
  output_pin 13, :as =&gt; :led
  software_serial 6, 7, :as =&gt; :gps
  serial_begin

  def loop
    digitalWrite(led, true)
    serial_print(gps.read)
  end
end
</code>
	As you can see, he configures ports 6 and 7 as a software seria connetion called "gps" and then he simply says "gps.read" to read the data his device is sending over that connection. Scott also implemented "print" and "println" methods for outputting to serial-connected devices such as his LCD, which work in the same way.
			</p>
			<p>
				I was especially psyched to see this patch since I haven't gotten to work with any devices that communicate over software serial yet, which had meant that I couldn't really test and add this functionality myself. I'm planning to get my hands on some of that soon and so I'm excited to play with the clean simple API Scott's provided here.
			</p>
<h4>Fixed Hardware Serial Support</h4>
		
		<p>In previous releases of RAD, hardware serial support had been, uh, perfunctory. The trouble stemmed from the wide variety of functionality hidden behind Arduino's elegant serial API. Serial.read(), Serial.print(), and their brethren do subtle things to act correctly when called with different arguments, from integers to individual characters to full strings (or arrays of characters, as C would have it). The result was that RAD's versions of these methods would sometimes do strange things like returning ASCII-value integers when sent characters. That should no longer be happening. For example if your run the following sketch:

<code lang="ruby">
class SlowTypewriter &lt; ArduinoSketch
	serial_begin
	
	def loop
		serial_print serial_read
	end
end
</code>

and attach to the serial output with screen, you'll see the characters you type successfully roundtripping to the Arduino and coming back with their encoding preserved. It's the world's slowest typewriter!
	</p>
		
<h4>A Panoply of Small Features, Tweaks and Bug Fixes</h4>
<p>
	Including, but not limited to:
	<ul>
		<li>Made 'rake make:upload' default to skipping the prompt for reseting the board. The older NG boards that require the reset are getting rare and I recently <a href="http://flickr.com/photos/unavoidablegrain/2310821792/">modded mine to no longer require it</a>. The reset is still available as an option by editing the "physical_reset" option in config/hardware.yml.</li>
		<li>Added support for HIGH/LOW and ON/OFF constants. This is a nice feature of the Arduino API that I hadn't been able to sneak throug the RubyToC translation stage until now.</li>
		<li>Support for variables that are not local to the loop method. It's a common desire to be able to initialize variables outside of the loop method of a sketch so that they will not be constantly re-initialized with each run, for example to define environmental constants or initialize counters. Since RAD replaces the Arduino setup functions and global declarations with ArduinoSketch class methods (such as output_pin), this wasn't previously possible. As of this release, you can use the 'vars' method to initialize variables in this scope thusly:
<code lang="ruby">
class VarTest &lt; ArduinoSketch
	vars :a =&gt; :int, :b =&gt; 7, :c =&gt; &quot;hello&quot;
	
	def loop
		a = 1
		serial_print a
		serial_print b
		serial_println c
	end
end	
</code>
	This will produce output like:
<pre>
17hello
17hello
17hello
17hello
[...]
</pre>
 As you can see, the vars method takes a hash where each key is the name of the variable you'd like to initialize and the value and be either a type (rendered as a symbol, i.e. ":int"), or an actual value if you want the var to be initialized to something (i.e. "hello").
			</li>
			<li>Changed default Arduino location to be /Applications/arduino-00010, which seems to be where most people (now including me) have it.</li>
			<li>Plus too many small bug fixes to list here!</li>
	</ul>
</p>	

<h4>What's Next?</h4>
<p>
	There's all kinds of things big and small on the immediate roadmap for RAD. There's the administrative: putting the RAD source on <a href="http://github.com">Git Hub</a>, adding sorely needed documentation to the core ArduinoSketch methods, organizing an email list for the growing group of people wanting to be kept up-to-date on the project, etc. There's the lofty: I've got the beginnings of a plan for putting building a testing and simulation framework on top of RAD that would let you run your sketch against a software version of the Arduino hardware while developing (with a visualization/interactive app built on <a href="http://code.whytheluckystiff.net/shoes/">Shoes</a>!), etc.
</p>
<p>And then there's your contribution: send me your patches and RAD can become whatever your want it to! As always, if you've got any questions, ideas for contributions, or run into any troubles running RAD, feel free to email me: greg [dot] borenstein [at] gmail [dot] com or comment here; I'd especially love to see/hear what projects people are building with RAD. Happy hacking!</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/rad" rel="tag">rad</a>, <a href="http://www.technorati.com/tags/ruby" rel="tag">ruby</a>, <a href="http://www.technorati.com/tags/arduino" rel="tag">arduino</a>, <a href="http://www.technorati.com/tags/c" rel="tag">c</a>, <a href="http://www.technorati.com/tags/assembly" rel="tag">assembly</a>, <a href="http://www.technorati.com/tags/reed" rel="tag">reed</a>, <a href="http://www.technorati.com/tags/gem" rel="tag">gem</a>, <a href="http://www.technorati.com/tags/release" rel="tag">release</a>, <a href="http://www.technorati.com/tags/physical+computing" rel="tag">physical computing</a>, <a href="http://www.technorati.com/tags/framework" rel="tag">framework</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Automating Firefox for Web Application Integration</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/03/automating-firefox-for-web-app.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9105</id>

    <published>2008-03-07T18:54:34Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary>This post explains how to control Firefox from the command line with Telnet and Ruby. After presenting some context to explain why I think this hack represents an important area of concern in contemporary web application development, I&apos;ll show how...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="learns_to" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p><em>This post explains how to control Firefox from the command line with Telnet and Ruby. After presenting some context to explain why I think this hack represents an important area of concern in contemporary web application development, I'll show how to execute it with actual install directions and code samples.</em></p>

<p>
	Ok, I'll say it: I think JavaScript is cool. One of my favorite effects of the move to the modern AJAX-oriented web application architecture has been the opportunity to move ever more functionality into the client. At <a href="http://grabb.it">Grabb.it</a>, we like to say, "Anything you can implement in JavaScript is free." Instead of running on our servers, the JavaScript portion of our app runs on a distributed grid of thousands of machines maintained for us by our users. Also, despite the reputation given it by the Browser Wars, JavaSript is incredibly fun to develop in: it's lightweight and extremely flexible in a unique way that somehow forces you to constantly keep your code very closely tied to the data it's manipulating. 
</p>
<p>
	The one big downside to JavaScript is its runtime environment. Not only does code running in the browser confront a Gordian Knot of browser compatibility problems, but it's also irretreviably isolated from interoperating with other application code. While javascript libraries (like the inestimable <a href="http://docs.jquery.com/Main_Page">jQuery</a>) are increasingly proving the <a href="http://en.wikipedia.org/wiki/Gordian_Knot#Legend">Alexander's sword</a> of the browser compatibility Knot, the issue of lack of application interoperability is only just beginning to get serious. As JavaScript's innate advantages lure more and more application code into the browser, the question will be unavoidable: How do you get modules implemented in JavaScript to interact with those built in other languages that live in more traditional environments? How do you avoid duplicating all functionality that you put into the JavaScript portion of the application so that you can call it from outside the browser?
</p>
<p>
	This week, trying to solve exactly these types of problems, I discovered a tantalizing avenue towards addressing some of these questions: browser automation from the command line and from scripting languages. Here was my situation.
	</p>
	<p>
	As part of <a href="http://go.grabb.it">an upcoming Grabbit project</a>, I've built a <a href="http://go.grabb.it/demo">a highly interactive data browser</a> for our customers. The JavaScript running on that page makes a series of JSON GET requests to gather all of the necessary information to compose its display and it makes a few AJAX POST requests to report back to the server on certain bits of status. But now, I wanted to trigger those POSTs programatically on a schedule rather than waiting for customers to trigger them. The dilemma is that I'd already written this relatively sophisticated JavaScript application that makes all the necessary requests, implements the business logic, and knows how to POST in the data. I had two options: redo all of that work again in my server-side application (ick!) or figure out a way to trigger this JavaScript code by automating its runtime enviornment (the browser).
</p>

<p>
		After a half day's research, here's what I discovered: there's a Firefox extension that allows other applications to <a href="http://www.croczilla.com/jssh">establish JavaScript shell connections to a running Mozilla process via TCP/IP</a>. It's called JSSH. Once you've got JSSH installed and running in Firefox, you can open a telnet connection to the browser that allows you to automate it using JavaScript commands to do things like load new pages or even manipulate the DOM on pages you've loaded. You can then automate this interaction using any scripting language with a telnet library. For the remainder of this post, I'll provide step-by-step instructions for running JSSH and for automating it with Ruby.
		</p>
		<h4>Install JSSH</h4>
		<p>
		The easiest way to install JSSH is to download the <a href="http://alephzarro.com/files/jssh-20070312-linux.xpi">JSSH.xpi</a> and open it with Firefox which will offer to install the extension (if you're interested in compiling Firefox with it from scratch or installing an existing binary, you should read <a href="http://crasch.livejournal.com/550521.html">these instructions</a>).
		</p>
		<h4>Start Firefox with JSSH</h4>
		<p>
			 Once you've got a copy of Firefox with JSSH installed, you'll need to run it. You can do this by providing the correct options when launching Firefox from the command line. On Mac OS X, that looks like this:
			<code>
/Applications/Firefox.app/Contents/MacOS/firefox -jssh &
			</code>
			The "&" at the end of that line will background your command so it doesn't take over your terminal session.
		</p>
		<h4>Telnet into the JavaScript Shell</h4>
		<p>
			Once Firefox is running, we can use telnet to log into JSSH like so:
<code>
$ telnet localhost 9997
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to the Mozilla JavaScript Shell!

&gt;
</code>
	</p>

	<h4>Load a URL from JSSH</h4>
	<p>
		Now that we're in, we can tell Firefox to load pages for us, thusly:
<code>
var w0 = getWindows()[0]
var browser = w0.getBrowser()
browser.loadURI("http://www.urbanhonking.com/ideasfordozens")	
</code>

	And that's it! If the JavaScript application I wanted to run lived at "http://urbanhonking.com/ideasfordozens", we'd be done. That command would load the page and Firefox would interpret and run the JavaScript it found there.
	</p>
	<p>
	Now, all we've got left to do is make it so that we can trigger this process from our application code. So, we'll...
	</p>
	<p>
		<h4>Automate the Process with Ruby</h4>
			<p>
				Like any good scripting language, <a href="http://www.ruby-doc.org/stdlib/libdoc/net/telnet/rdoc/index.html">Ruby has a telnet library</a>, which means that once we've got an instance of Firefox running with JSSH enabled, we can talk to it from Ruby whenever we want. Here's an example script that logs into the telnet shell and loads a series of URLs one at a time:
<code lang="ruby">
require 'net/telnet'
my_urls = ["http://urbanhonking.com/ideasfordozens", "http://atduskmusic.com", "http://grabb.it", "http://pdxpopnow.com"]

# start telnet session with the Firefox javascript shell and setup browser object
puts "starting telnet session"
firefox = Net::Telnet::new("Host" => "localhost", "Port" => 9997)
firefox.cmd "var w0 = getWindows()[0]"
firefox.cmd "var browser = w0.getBrowser()"

# load each page
my_urls.each do |url|
  puts "loading...#{url}"
  firefox.cmd "browser.loadURI('#{url}')"
  sleep 10 # so that the browser has time to load even if the page is slow
end

firefox.close
</code>
			</p>
			<h4>Further Research: Screen Scraping JavaScript Heavy Sites</h4>
			<p>
				What else might this rickety bridge we've built to the JavaSript runtime environment be good for? One thing that immediately occurs to me is: screen scraping for sites with a lot of JavaScript. Another side effect of the rise of rich JavaScript applications has been to create intractable problems for people trying to do screen scraping. If the data you want is not in the page's HTML when you request it in the first place but is only written in later when the page's JavaScript runs then traditional spidering and screen scraping techiques will fail to find it. <a href="http://www.freebase.com/">Freebase</a>, the open database application built by Danny Hillis and his team, for example, uses a highly dynamic interface for presenting its data that is almost entirely based in JavaScript. Or, on the low-brow side, <a href="http://myspace.com">MySpace</a> uses JavaScript throughout the forms in its interface to help with date picking and such. If you wanted to scrape or automate interaction with either of these sites, you'd need access to a runtime environment that could execute JavaScript.
			</p>
			<p>
				I haven't really tackled this problem with JSSH, but I do have some leads. For example, here's how you get the html of the document:
<code>
&gt; browser.contentDocument
[object XPCNativeWrapper [object HTMLDocument]]
&gt; domDumpFull(domNode(browser.contentDocument))
&lt;HTML&gt;&lt;HEAD&gt;&lt;META content=&quot;text/html...
</code>

If you want to explore this avenue further, one of the best places to look is <a href="http://code.google.com/p/firewatir/">Firewatir</a>, a project to add Firefox support to the <a href="http://www.openqa.org/watir/">WATIR browser testing framework</a>. They do lots of click-by-click automation and checking for results, so I'm sure they've figured out approaches for a lot of what you'd confront when screen scraping. <a href="http://www.croczilla.com/jssh">The JSSH documentation</a> itself is useful and clear but not the most in depth. 
				</p>
				<p>
					Happy automating! Let me know what you discover...
				</p>
				<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/ruby" rel="tag">ruby</a>, <a href="http://www.technorati.com/tags/firefox" rel="tag">firefox</a>, <a href="http://www.technorati.com/tags/jssh" rel="tag">jssh</a>, <a href="http://www.technorati.com/tags/javascript" rel="tag">javascript</a>, <a href="http://www.technorati.com/tags/automation" rel="tag">automation</a>, <a href="http://www.technorati.com/tags/browser" rel="tag">browser</a>, <a href="http://www.technorati.com/tags/ajax" rel="tag">ajax</a>, <a href="http://www.technorati.com/tags/json" rel="tag">json</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Developing Single Serving Sites using Ruby CGI scripts on Dreamhost</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/03/developing-single-serving-site.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9104</id>

    <published>2008-03-02T03:27:22Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary> There&apos;s been a lot of hullabaloo lately about Single Serving Sites. Stimulated by the inexplicable runaway success of Barack Obama is Your New Bicylce, these simple sites that provide a small dollop of amusement (isitchristmas.com) or utility (istwitterdown.com) have...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="learns_to" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>
	There's been a lot of hullabaloo lately about <a href="http://www.kottke.org/08/02/single-serving-sites">Single Serving Sites</a>. Stimulated by the inexplicable runaway success of <a href="http://barackobamaisyournewbicycle.com/">Barack Obama is Your New Bicylce</a>, these simple sites that provide a small dollop of amusement (<a href="http://www.isitchristmas.com/">isitchristmas.com</a>) or utility (<a href="http://istwitterdown.com">istwitterdown.com</a>) have become all the rage.
</p>
<p>Of course, I've been making them for awhile now, e.g. <a href="http://largeheartedgoat.com">Largehearted Goat</a> and <a href="http://thenytimesexplainstheratings.com">The NY Times Explains the Ratings</a>. At first, creating a new SSS is a satisfying experience. You have a whacky idea and withing a few hours, you've registered a domain, written some simple code, and put something up. But, over time, each one gets to be more and more of a burden. My ideas, at least, have involved sites that need to be constantly updated with new information over time. Since I've always implemented these sites with simple ruby scripts that run on my local machine and then upload the static finished versions of the sites, this has meant keeping an eye on unreliable cron jobs and, sometimes, hand maintenance. And, over the years, I've wondered if there was a better solution.
	</p>
<p>
	Today, I took the first steps towards finding one. It turns out that <a href="http://en.wikipedia.org/wiki/Common_Gateway_Interface">good-ole CGI scripts</a> &mdash; so foreign to those of us who's main experience has taken place in the age of sophisticated web frameworks like Rails &mdash; make a great basis for SSS development. What follows is a basic introduction to writing and running CGI scripts with Ruby. I'll focus on Dreamhost as a deployment target since it's the service I have access to for this kind of thing and also the issues that arise there are probably not that dissimilar from what comes up with the other shared hosting services that are the natural habitat of SSSes.
</p>

<h4>Step One: Get Ruby and Rubygems up and running</h4>

<p>If you plan on keeping your SSSes extremely spartan simple, you might be able to skip this step. Dreamhost accounts come with an old version of Ruby already installed. If you don't need to install any custom gems for your scripts or control anything else about your ruby environment, you can skip straight down to the step two. However, if you plan on doing anything the least bit more sophisticated &mdash; from installing one individual gem all the way up to using Rails itself &mdash; you've got a bit of work to do beforey you can get started on the fun part.</p>

<p>
	Being far from an expert on unix build process and dependencies, I followed <a href="http://nateclark.com/articles/2006/10/20/dreamhost-your-own-packages-and-gems">Nate Clark's excellent instructions for building Ruby and Rubygems on Dreamhost</a> with just a few discrepancies. My biggest note is that the version of the Ruby source to which he links is out-of-date. I changed his line for download the Ruby source to:
	<code>
$ wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz
	</code>
	But, don't trust me! The most recent version of Ruby changes all the time and you can always find <a href="http://www.ruby-lang.org/downloads">the most recent version of Ruby at ruby-lang.org</a>. The one other thing worth noting that I discovered was that in any of the compilations make may die by timeout (Dreamhost kills processes that last longer than a given interval, a major pain point we'll be returning to in a moment when we try to install individual gems). It won't always be clear that a timeout was at fault so if you see a 'configure', 'make', or 'make install' command die mysteriously, just go ahead and try again. 
</p>

<h4>Step Two: CGI Hello World with Ruby</h4>

<p>
	Now that we've got Ruby and Rubygems installed, the first thing we want to do is to just run a basic 'hello world' CGI script to make sure that we've got things configured correctly. Here are the steps:
	<ol>
		<li>Log into dreamhost over ssh.</li>
		<li>Navigate to the desired directory within your web space.</li>
		<li>Create a new file, e.g. test.cgi.</li>
		<li>Fill it with the following content (if you skipped Step One and are using the build-in DH Ruby, the first 'shebang' line should read: "#!/usr/bin/ruby" instead of what is shown):
			<code>
#!/usr/bin/env ruby
require "cgi"
cgi = CGI.new("html3")
cgi.out("text/plain"){
  "Hello World #{Time.now}"
}
			</code>
			</li>
			<li>Change the permissions of that file by running:
			<code>
$ chmod 775 test.cgi
			</code>
			</li>
	</ol>
	That should do it. Navigate to that path in your browser and you should see output that looks something like this:
<code>
Hello World Sat Mar 01 19:04:53 -0800 2008
</code>
</p>

<h4>Step Three: Install Gems by Hand</h4>

<p>Now, if you plan on doing anything more interesting than displaying the date, the odds are you're going to want to take advantage of Ruby's great and growing weatlh of libraries made available as Gems. Unfortunately, the RubyGems server system running at <a href="http://rubyforge.org">RubyForge</a> has lately become incredibly slow. In order to find packages and detect dependecies, the default 'gem install' command has to communicate with that server and so becomes subject to the ruthless Dreamhost killing of long-running processes. In my experience, trying to install gems on Dreamhost will universally end in frustration:

<code>
$ gem install feedalizer
Bulk updating Gem source index for: http://gems.rubyforge.org
Killed
</code>
What to do?
</p>
<p>Fortunately, in addition to using the RubyForge server to search for gems, it's possible to install them directly from .gem files if you can find them for your desired packages. For example, when building a recent SSS I wanted to use <a href="http://termos.vemod.net/feedalizer">Feedalizer</a> &mdash; a great library that scrapes web pages and automatically creates RSS feeds from the resulting content &mdash; so I hunted down the .gem file via the <a href="http://rubyforge.org">RubyForge website</a>, downloaded it, attempted local installation, and then (when that failed) chased down the sources for the dependencies (in this case just <a href="http://code.whytheluckystiff.net/hpricot/">Hpricot</a>) to follow the same process. To give you a taste of things here were the gory details:</p>

<p>Installing Feedalizer:
<code>
$ wget http://rubyforge.org/frs/download.php/13797/feedalizer-0.1.0.gem
$ gem install feedalizer-0.1.0.gem
</code>
which threw an error complaining about the need for the Hpricot dependency, so:
<code>
$ wget http://code.whytheluckystiff.net/dist/hpricot-0.5.140.tgz
$ tar xzf hpricot-0.5.140.tgz 
$ cd hpricot-0.5.140
$ rake gem
$ gem install pkg/hpricot-0.5.gem
</code> 
The 'rake gem' step there is necessary because _why only makes the source directory available for direct download rather than an explicit .gem file. After this completes successefully, return to the 'gem install' step for Feedalizer above (be sure to the return to the directory into which you dowmloaded the Feedalizer .gem before running it).
</p>
<p>
	Much bumpier than the smooth ride normally provided by 'gem install', but it'll get the job done. You could clamber your way down similar rutted paths for most any other gem you needed for you script.
</p>

<p>And that should be more than enough to get you started. If you run into any troubles, dive into the comments here and on the other blog posts linked for help. Also, if anyone has any experience using lightweight persistence strategies in this context, I'd love to hear about them, espcially if they're file-system only; a lot of my scripts requiring saving records and I tend to use a rickety YAML-based system for them that could stand improving.</p>

<p><em>Note: Thanks to <a href"http://henrik.nyh.se/2007/12/dilbert-blog-rss-with-full-entries">The Pug Automatic</a> for inspiring me to start down this path in the first place.</em></p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/ruby" rel="tag">ruby</a>, <a href="http://www.technorati.com/tags/cgi" rel="tag">cgi</a>, <a href="http://www.technorati.com/tags/dreamhost" rel="tag">dreamhost</a>, <a href="http://www.technorati.com/tags/rubygems" rel="tag">rubygems</a>, <a href="http://www.technorati.com/tags/sss" rel="tag">sss</a>, <a href="http://www.technorati.com/tags/single+serving+sites" rel="tag">single+serving+sites</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Using Sandy with Web Snippets</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/02/using-sandy-with-web-snippets.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9103</id>

    <published>2008-02-12T02:40:46Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary> Welcome to the third in my series of tutorials on getting the most out of I Want Sandy, the &quot;virtual personal assitant&quot; from Portland company Values of N. In the last two installments, I covered how to communicate with...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="useful web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>
	Welcome to the third in my series of tutorials on getting the most out of <a href="http://iwantsandy.com">I Want Sandy</a>, the "virtual personal assitant" from Portland company Values of N. In the last two installments, I covered <a href="http://www.urbanhonking.com/ideasfordozens/archives/2008/01/i_want_sandy_wi.html">how to communicate with Sandy on the go using SMS and Twitter</a> and outlined <a href="http://www.urbanhonking.com/ideasfordozens/archives/2008/02/an_iwantsandy_p.html">a Sandy-specific version of the Quicksilver append trick</a>. This time, I'm going to show you how I use Safari's new 'web snippets' feature so that I always have quick access to all the stuff I've stored with Sandy.</p>
	<p>I know what you're saying: 'Web snippets? Isn't that a Dashboard feature? Personally, I'd be perfectly happy if Dashboard never launched again!' I know, I know; before figuring out this little trick I felt similarly. But, believe it or not the combination of Sandy and web snippets has actually made Dashboard useful to me for the first time since its inception. So put your well-deserved Dashboard skepticism aside for a moment and listen up.</p>
	<p>
		Now that you've been using my first two tips for awhile, Sandy's starting to know about a lot of your appointments and all your other little tidbits, but what's the best way for her to give you easy access to them? Sure, you can query Sandy for individual bits of information when you're on the go, but there are some things &mdash; like your calendar and TODO list &mdash; that you've just got to have close at hand in full. Creating web snippets out of Sandy's monthly and tag views is the best way I've found to accomplish this.
	</p>
	<p><a href="http://img.skitch.com/20080212-kqtdnsfb19usc53nyxfu44q43u.jpg"><img src="http://img.skitch.com/20080212-kqtdnsfb19usc53nyxfu44q43u.preview.jpg" alt="Skitch.com > atduskgreg" /></a></p>
	<p>
		A 'web snippet' is simply a chunk of a web page that you select from Safari. Safari then creates a Dashboard widget that will be constantly kept up to date with the current content of that little bit of the web. What we want to do is to create web snippets out of the pages on Sandy that have our most relevant information. For my part, I've settled on the Monthly view and the view for my @computer tag (more about that in a minute). Here's how I got those created:
	</p>
	<ol>
		<li>Login to <a href="http://iwantsandy.com/home">IWantSandy.com/home</a>.</li>
		<li>Click on Daily Digest &gt; This Month (the 'This Month' link under the Daily Digest drop down).</li>
		<li>Click the web snippet icon as shown above.</li>
		<li>Drag the highlight box around the yellow pad part of the screen containing your reminders. Sometimes, the box will lock onto individual sub-portions of the page making selection easier, but you can also drag its corners around as well.</li>
		<li>Click the "Add" button in the top right.</li>
		<li>Dashboard will launch. You're done.</li>
	</ol>
	<p>Now, you'll have a custom-made widget with all of your reminders for the month available anytime you invoke Dashboard.</p>
	<p>So, how do I use this? And what's so great about it? Couldn't I just visit Sandy's perfectly nice website anytime I wanted to view my stuff?</p>
	<p>I've made two Sandy-related widgets: one for my appointments for the month and one for my items tagged @computer. I use the @computer tag in a GTD-ish manner to specify TODO items that I can accomplish at my computer (click on the image below to see a larger version):</p>
	<p><a href="http://img.skitch.com/20080212-p3euj7y996d4u5uu525ahpissy.jpg"><img src="http://img.skitch.com/20080212-p3euj7y996d4u5uu525ahpissy.jpg.preview.jpg" title="sandy in web snippets" width="400px"/></a></p>
	<p>Each of these uses demonstrates a different big advantage of accessing Sandy from Dashboard. The key is: <em>the AJAX bits of Sandy's interface still work here</em>, so I can edit items and mark them as done <em>directly from these widgets</em>.</p>
	<p>For example, when I complete an item from my @computer TODO list, I simply click the 'x' next to its entry in the relevant widget and the item gracefully fades away never to return:</p>
	<p>
	<a href="http://img.skitch.com/20080212-d377maifw882y3bex97b8pcrj6.jpg"><img src="http://img.skitch.com/20080212-d377maifw882y3bex97b8pcrj6.preview.jpg" title="marking an item as complete from Dashboard" /></a>
	</p>
	<p>Similarly, I can edit details of appointments if they change, simply by clicking on an item from my monthly calendar. The first click pops up a box with some more details:</p>
		<p><a href="http://img.skitch.com/20080212-rhbghsephmfwtm1h93w7r7fu1p.jpg"><img src="http://img.skitch.com/20080212-rhbghsephmfwtm1h93w7r7fu1p.jpg.preview.jpg" title="click an item to view or edit details" width="400px"/></a></p>
		<p>Clicking 'Edit' brings up a form where you can change everything from the date to the description to when you want Sandy to send your reminder:</p>
	<p><a href="http://img.skitch.com/20080212-1rsbhfff599q9eac7k8eid9xhs.jpg"><img src="http://img.skitch.com/20080212-1rsbhfff599q9eac7k8eid9xhs.jpg.preview.jpg" title="editing details on an item from web snippets" width="400px"/></a></p>
	<p>
		Each of these web snippets really starts to feel like a tiny little custom desktop client for a single specific bit of Sandy's functionality.	
		</p>
		<p>
		One of the big lessons I've learned from my attempts at doing GTD has been the importance of putting your inboxes and other TODOs directly in your path, someplace you'll stumble over them in the course of your normal daily operations. And these little applications are a really lightweight way to do just that, eliminating nearly all the friction involved in maintaining and making reference to my lists and reducing the opportunity for fiddling to a minimum.
	</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/sandy" rel="tag">sandy</a>, <a href="http://www.technorati.com/tags/gtd" rel="tag">gtd</a>, <a href="http://www.technorati.com/tags/safari" rel="tag">safari</a>, <a href="http://www.technorati.com/tags/web+snippets" rel="tag">web+snippets</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>Ideas for Dozens&apos; Third Annivesary</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/02/ideas-for-dozens-third-annives.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9102</id>

    <published>2008-02-10T00:54:49Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary>Today I&apos;m proud to celebrate the third anniversary of Ideas for Dozens. In the the three years of this blog&apos;s existence, I&apos;ve written 197 entries (or about 1 post every 5 and a half days) using three different blog engines...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="meta" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>Today I'm proud to celebrate the third anniversary of Ideas for Dozens. In the the three years of this blog's existence, I've written 197 entries (or about 1 post every 5 and a half days) using three different blog engines (after a brief flirtation with Blogger I moved to a <a href="http://www.blosxom.com/">Blosxom</a> install for more control before joining <a href="http://urbanhonking.com">Urban Honking</a> and learning about the many mysteries of Moveable Type).</p>

<p>In that time, I've covered topics from <a href="http://www.urbanhonking.com/ideasfordozens/archives/learns_to/">art</a> to <a href="http://www.urbanhonking.com/ideasfordozens/archives/learns_to/">Ruby on Rails</a> to a <a href="http://www.urbanhonking.com/ideasfordozens/archives/2006/10/largehearted_go.html">series</a> of <a href="http://www.urbanhonking.com/ideasfordozens/archives/tshirtaday/">eccentric</a> <a href="http://www.urbanhonking.com/ideasfordozens/archives/2007/02/the_ny_times_ex.html">projects</a>. And you all have responded, writting 286 comments for an average 1.45 comments per entry. My posts have been picked up by <a href="http://www.boingboing.net/2005/08/12/theres-no-place-like.html">BoingBoing</a>, <a href="http://www.43folders.com/2005/05/27/guest-check-pda">43 Folders</a>, and many others.</p>

<p>
	Anyway, I've got lots of exciting stuff in the works including a series on the basics of microcontroller architecture and assembler programming, a few ideas for  phsycial/ubiquitous computing projects, and a few other non-tech projects starting up as well. 
</p>

<p>So stay tuned and keep those comments coming&hellip;</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/idfdz" rel="tag">idfdz</a>, <a href="http://www.technorati.com/tags/meta" rel="tag">meta</a>, <a href="http://www.technorati.com/tags/thrid" rel="tag">thrid</a>, <a href="http://www.technorati.com/tags/anniversary" rel="tag">anniversary</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>An iwantsandy Port of the Quicksilver Append Trick</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/02/an-iwantsandy-port-of-the-quic.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9101</id>

    <published>2008-02-09T02:14:41Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary> As a follow up to my last post on mobile communication with Sandy, here&apos;s a trick I use to communicate with her when I&apos;m sitting in front of my computer. My favorite super-fast way to tell Sandy about new...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="useful web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<img alt="append_to_sandy.jpg" src="http://www.urbanhonking.com/ideasfordozens/append_to_sandy.jpg" width="400" />

<p>As a follow up to my last post on <a href="http://www.urbanhonking.com/ideasfordozens/archives/2008/01/i_want_sandy_wi.html">mobile communication with Sandy</a>, here's a trick I use to communicate with her when I'm sitting in front of my computer.</p>

<p>My favorite super-fast way to tell Sandy about new reminders is nearly identitcal to <a href="http://www.43folders.com/2004/09/04/quicksilver-append-to-a-text-file-from-anywhere" title="Quicksilver: Append to a text file from _anywhere_ | 43 Folders">the famous Quicksilver append trick</a>. In that legendary tip, Merlin Mann advised combining Quicksilver's raw text entry option with it's ability to append information to existing text files in order to quickly add items to lists for tracking everything from TODOs to groceries. My Quicksilver-Sandy technique is almost exactly the same, but here, instead of popping our text on the end of an existing file, we're going to have Quicksilver stick it in an email and send it off to our favroite fictional personal assistant.</p>

<p>If you're experienced with Quicksilver, you can probably figure this out for yourself, but for the rest of you here are the gritty details:</p>

<ol>
	<li>Invoke quicksilver.</li>
	<li>Hit period so the first pane goes into text mode.</li>
	<li>Type your message to Sandy (i.e. "reminder thrusday meeting with mikey").</li>
	<li>Hit tab to bring up the second pane for selecting an action.</li>
	<li>Type "e", "m" (enough for Quicksilver to pick "Email To...(Send)" as the action). <em>Caveat: Make sure you have the "Email To...(Send)" option checked in Quicksilver's Actions preference pane or it won't be available.</em></li>
	<li>Hit tab to move to the third, "indirect object", pane.</li>
	<li>Type "s", "a" (enough for Quicksilver to select Sandy from your contacts (obviously, this presupposes that Sandy is amongst your contacts &mdash; which happened for me simply from emailing her a lot; I don't use Address Book).</li>
	<li>When all three panes look right, hit enter.</li>
	<li>There is no step 9.</li>
</ol>

<p>That's it. Just like the tips for mobile Sandy communication, I really like this way of telling Sandy about my stuff because it reduces for adding new information so much that it makes it easy for me to actually achieve the "ubiquitous capture" the GTD geeks are always talking about.</p>

<p>Next time, to complete my trifecta of Sandy-related posts, I'll talk about how I access the info that Sandy's storing for me using the new Dashboard "web snippets" feature so that it's always easily available to me.</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/iwantsandy" rel="tag">iwantsandy</a>, <a href="http://www.technorati.com/tags/quicksilver" rel="tag">quicksilver</a>, <a href="http://www.technorati.com/tags/append" rel="tag">append</a>, <a href="http://www.technorati.com/tags/43folders" rel="tag">43folders</a>, <a href="http://www.technorati.com/tags/email" rel="tag">email</a>, <a href="http://www.technorati.com/tags/gtd" rel="tag">gtd</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>I Want Sandy with SMS and Twitter</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/01/i-want-sandy-with-sms-and-twit.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9100</id>

    <published>2008-01-22T01:48:45Z</published>
    <updated>2008-04-14T00:52:24Z</updated>

    <summary> I&apos;ve been happily using I Want Sandy, the virtual email-based personal assistant from Portland-based Values of N for some time now. (Disclaimer: Sandy is the brainchild of Rael Dornfest who I&apos;m proud to count a friend.) The service&apos;s friendly...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="useful web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>
	<img src="http://img.skitch.com/20080122-x9xnc5xbnytif6cabt38igtsbq.jpg" alt="sandy" style="float:left; margin: 10px; margin-top:0; margin-bottom: 0"/>
	I've been happily using <a href="http://iwantsandy.com/">I Want Sandy</a>, the virtual email-based personal assistant from Portland-based <a href="http://valuesofn.com/" title="values of n">Values of N</a> for some time now. <em>(Disclaimer: Sandy is the brainchild of Rael Dornfest who I'm proud to count a friend.)</em> The service's friendly avatar-driven interface masks a powerful task and event storage and reminder system that actually feels surprisingly similar to the Ruby Golbergian contraption of <a href="http://rake.rubyforge.org/" title="ruby make">Rake tasks</a>, <a href="http://www.43folders.com/taxonomy/term/3560?page=2" title="Mac OS X | 43 Folders">Remind</a>, and <a href="http://www.versiontracker.com/dyn/moreinfo/macosx/17621">Geek Tool</a> that I'd previously hand-rolled for myself.</p>

<p>
	Until recently, the one part of my interaction with Sandy that hadn't left me totally satisfied was the ability to add tasks and reminders from my phone. Since I've been a straggler in the iPhone stampede, the main interface I use to get data to and from my phone is SMS. It was a synch to teach Sandy to send reminders via SMS, but I had never been able to close the loop on sending new information <em>to</em> Sandy via text. 
</p>
<p>It turns out the problem was mostly me. There are actually two different ways to get setup to send your reminders to Sandy from SMS: via the secondary email address and via Twitter. Both of these are relatively easy to setup and have different uses depending on the context. Here's what I did to get them working:</p>

<h5>Setting Sandy up with SMS</h5>

<ol>
	<li>
		<a href="http://www.iwantsandy.com/login">Login to iwantsandy.com</a>
	</li>
	<li>
		Navigate to <a href="http://www.iwantsandy.com/settings">the settings page</a>.
	</li>
	<li>
		Under the heading "Secondary email address", enter the email address that your carrier redirects to your phone via SMS. For Verizon users this will take the form &lt;YOUR PHONE NUMBER&gt;@vtext.com and other carriers have similar services. If you don't know what yours is, try sending a text message to your own email address and seeing what the from address turns out to be.
		</li>
		<li>
			Once you save your settings with your phone's email address, Sandy will send you a message with a link to confirm the address. When the message arrives in your phone &mdash; it will be in the form: iwantsandy.com/confirm/&lt;SHORT CODE&gt; &mdash; visit the url in the browser.
		</li>
		<li>
			That's it, you're ready to go! Add Sandy as a contact on your phone (enter the address listed as "Sandy's Email Address" as her email address) and you can send her info in just a few clicks any time.
		</li>
</ol>

<h5>Setting Sandy up with Twitter</h5>

<ol>
	<li>Go to <a href="http://twitter.com/s">Sandy's Twitter page</a> and click the button to follow her.</li>
	<li>Go to <a href="http://www.iwantsandy.com/settings/twitter">your Twitter settings page on Sandy</a>.</li>
	<li>Tell Sandy your Twitter account name.</li>
	<li>She'll send you a direct message on Twitter with a confirmation code.</li>
	<li>When that message arrives, return to <a href="http://www.iwantsandy.com/settings/twitter">your Twitter settings page on Sandy</a> and enter the code in the box.</li>
	<li>That's it. You're ready to go! You can now send Sandy a Twitter message in the form of "d s remember that I left my cell phone at the bar" from anywhere you can send Twitter messages: <a href="http://iconfactory.com/software/twitterrific" title="Iconfactory : Software : Twitterrific">Twitterriffic</a>, the web, IM, by texting to 40404, through the Twitter API, etc. Note: they use "s" as Sandy's Twitter name because it's fewer characters to type on a phone.</li>
	<li>Sandy will respond to your Twitter message telling you what she gleaned from it.</li>
</ol>
<p>
	While both of these processes are somewhat lengthy to describe, they each only take a minute to actually execute. And the result of doing so, at least for me, was a major imrpovement in not forgetting things. Instead of writing things down and then sending them to Sandy later when I return to my computer, I just tell her about them immediately when they come up. Plus, now I can access all the stuff I have Sandy store from anywhere. If I want to know what errands I'm supposed to do while I'm out doing them, I just text/twitter "lookup @errands" and Sandy replies with everything I've tagged as an errand.
</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/sandy" rel="tag">sandy</a>, <a href="http://www.technorati.com/tags/twitter" rel="tag">twitter</a>, <a href="http://www.technorati.com/tags/sms" rel="tag">sms</a>, <a href="http://www.technorati.com/tags/reminder" rel="tag">reminder</a>, <a href="http://www.technorati.com/tags/email" rel="tag">email</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>A Brief History of the Music Industry over the Last 10 Years</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2008/01/a-brief-history-of-the-music-i.html" />
    <id>tag:www2.urbanhonking.com,2008:/ideasfordozens//44.9099</id>

    <published>2008-01-13T03:40:55Z</published>
    <updated>2008-04-14T00:52:23Z</updated>

    <summary>Recently, my college music professor, David Schiff, came to me to get my perspective on the subject of a class he&apos;s putting together for this coming semester covering music from 1968 to the present. After thinking about the topic for...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="music" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p><em>Recently, my college music professor, <a href="http://www.davidschiffmusic.com/" title="David Schiff: Composer, Author, Teacher">David Schiff</a>, came to me to get my perspective on the subject of a class he's putting together for this coming semester covering music from 1968 to the present. After thinking about the topic for a little while I had an amazing realization: the kids taking the class were all under 12 in 1998 when Napster hit. All of the events of the Online Music Wars we take for granted as universal knowledge and the latest news are, to some extent, ancient history for them. So, amongst other pieces of advice, I wrote him a a high level overview of the technological and cultural changes undegone by the music industry over the last ten years. Following <a href="http://steve.yegge.googlepages.com/you-should-write-blogs">an old piece of advice from Steve Yegge</a>, I'm posting the main body of what I wrote here in the hopes that it may be helpful to others.
</a</em></p>

<p>The two biggest changes in music in the last ten years are the rise of digital distribution and the rise of digital production. In 1998 most records with any cultural impact (pop, jazz, classical, experimental, whatever) were recorded in professional recording studios and distributed on CD by record labels. Now, most music is recorded at home on computers at equal or better than 1998 studio quality and distributed through some form of the internet. Here are the stories:</p>

<h4>Digital Distribution</h4>

<p>
In 1998, <a href="http://en.wikipedia.org/wiki/Napster">Napster</a>, the first peer-to-peer file trading system to really take hold was just becoming popular on the college campuses. Using Napster entailed making a certain portion of your digital music library available for anyone to download and, in exchange, receiving free access to download everything anyone else had made available. The result was that all of a sudden an enormous library of music of all kinds &mdash; orders of magnitude larger than what you'd find in any real world record store &mdash; was made available for free with no effort to every college student. The major labels, and some bands (most notably Metallica), freaked out and sued the company out of existence (it has since turned out that the labels gave some consideration to making a licensing deal with Napster, which had planned all along to monetize their service, but they decided against it &mdash; a move that turned out to be a monumental mistake, as we'll soon see). Unlike the peer-to-peer technologies that succeeded it, Napster was centralized: each user's computer talked to one of Napster's servers to find out what was available. Napster's destruction made that technological model impossible and forced the users, who'd gotten a taste for free access to an infinite library of music, onto services with distributed architectures (Gnutella, Grokster, and, eventually, BitTorrent) which pretty much permanently eliminated the chance for a centrally-managed mandatorily-licensed service that would generally allow them to maintain their existing business model.</p>

<p>Enter Apple. In 2001, Apple introduced the iPod and iTunes. The original slogan for iTunes was "Rip. Mix. Burn." The idea was that the combination of iTunes and the iPod allowed you to transfer all of the digital music on CDs you'd purchased (mostly from the major labels, of course) and transfer them to be listened to on your computer, on burned copies for your friends, and, most importantly, on your iPod which you could take with you anywhere. One of the big effects of the iPod and iTunes (and, to a certain extent Napster, before them) was to accentuate the importance of the single over the album. In the world of digital music, the unit of currency is the individual file which corresponds to a song. And one of the most marketed ways to listen to an iPod was through its shuffle mode (allowing you a randomly programmed radio consisting only of your own favorite tracks).</p>

<p>In 2003, Apple released the iTunes Music store. You could now buy individual songs and full albums of major label music directly inside of iTunes, which more and more people were using to manage their music collections (mostly driven by the amazing strength of iPod sales). The catalog available on iTunes came from the major labels who, at first, didn't consider iTunes to be a serious business (Apple didn't consider it one either &mdash; the service was designed as a loss-leader for selling iPods). Apple sold all songs for the same price ($0.99) and included "Digital Rights Management" with each file &mdash;  software designed to limit the user's ability to make an unlimited number of copies of the file and to use them on unapproved devices, such as iPod competitors. Much to Apple and the labels' surprise, the iTunes Music Store has turned out to be a runaway hit with 3 billion songs sold so far; Apple is the third biggest music retailer in America after Wal-Mart and Best Buy. As a result, the labels have become terrified of Apple's power and have started trying to create competitors so that they might get a better deal in the process (for example, they'd like to have variable pricing which would allow them to charge more for current popular singles and less for undesirable catalog and genre material, something Apple refuses) &mdash; thus the launch of the new Amazon MP3 store and a series of others. It's worth noting here that very little of the money paid for digital downloads makes it to the artists. The labels get about 70 percent of the purchase price and artists less than a penny (and that's a best case for major artists with the clout to audit their labels to ensure they're paid at all).</p>

<p><em>(One other major change to iTunes in the last few years has come from Portland business CD Baby. They are an enormously large online distributor for self-released CDs (they are the second biggest online retailer of CDs after Amazon). They managed to make a deal with Apple to license their entire catalog for inclusion in the iTunes store. So, now, an independent artist who wants to make their music available through iTunes can do so by submitting it to CD Baby. Other services, like Amazon's new MP3 store, have licensed the catalog as well.)</em></p>

<p>In the meantime, a series of increasingly popular social networks arose starting with Friendster and culminating with MySpace. These started out as basically dating sites but gradually became teen and twenty-something hangouts. MySpace, based in LA, was especially successful in luring small local and independent bands. Despite the site's terrible technical flaws (and the fact that it is now owned by Rupert Murdoch's News Corp.) it made it relatively easy for the technically un-savvy to get their music online in a form where other people could easily listen to it, engage them in conversation, and find out when their live shows were taking place. MySpace now hosts more than 3 million artists and has started a record label that draws from that pool. It is the coin of the realm of local music scenes around the country &mdash; club booking agents, local music press, other bands, all expect artists to have a MySpace page where their music can be heard. In the last few years, major label acts have started creating MySpace pages as well, which is a little like watching your parents sing along to Hip-Hop.</p>

<p>In the last few years, a new phenomenon has arisen: music blogs, as we discussed. They've managed to replace the print music press as the taste-makers and trend-setters for the most influential demographic: college students and music enthusiasts. The most recent news here is that the industry has begun figuring out how to market to these online music writers by leaking advanced songs off of upcoming records and otherwise flattering them with free stuff and attention. In fact, they've become so important to the labels promotion wings that the labels can't crush them for freely distributing their music (no matter how much they'd like to) for fear of a backlash.</p>

<p>The main upshot of these changes has been an ever increasing ability for independent artists to distribute and promote their music without the help of a major label (one side story I'm not going into here is the death of mainstream print journalism, MTV, and locally programmed pop radio, the main venues the major labels have traditionally used to make their acts popular); and for music fans to get access to major artists' work without needing to go through the labels. The labels have so far responded by trying to lock down their music with more and more restrictive DRM (and harsher deals with their online vendors), suing individual customers for downloading, and trying to re-negotiate their relationships with their artists so they get an ever greater chunk of the non-record sales parts of the business: concert tickets, publishing, and merchandise. The result has been a 30% drop in CD sales in the last year and an ever-growing flight of major artists away from labels towards alternative distribution mechanisms (like starting their own labels or working with major retailers (like Starbucks and Wal-Mart) directly). Though with the recent news of both <a href="http://yro.slashdot.org/article.pl?sid=08/01/11/0630245">Sony</a> and <a href="http://www.macworld.com/article/131305/2007/12/amazonmp3.html?t=201">Warner Music Group</a> signing on to the Amazon MP3 store things may finally be starting to change both in terms of iTunes' dominance and the attitude of major labels towards DRM.
</p>
<h4>Digital Production</h4>
<p>Since the introduction of ProTools in the early 90s, the ability to record, mix, and master music at a professional caliber has become ever more affordable, making its way from big expensive professional institutions to home hobbyist studios and finally to every laptop made today. With a normal consumer laptop, a couple of hundred dollars in microphones and conversion gear and/or software (depending if you're making music that requires outside-of-the-computer instruments or not), a talented recording artist can make recordings that are perfectly competitive with richly budgeted major studios (though not necessarily in the same style). This has lead to a number of new musical aesthetics arising from intimate <a href="http://www.urbanhonking.com/ideasfordozens/archives/2005/03/the_new_digital.html">parlour music</a> (see also the work of <a href="http://grabb.it/search?q=juana%20molina">Juana Molina</a> to the pastiche of sampling (see <a href="http://en.wikipedia.org/wiki/Gray_Album">The Gray Album</a> by DJ Dangermouse &mdash; a mashup of the Beatles' White Album with Jay-Z's the Black Album is a paradigmatic example here and the first argument of most defenders of 'remix culture'). The prevalence of loop-based composition on the computer has also done a lot to spread the influence of dance music and hip-hop into all other genres (this year, in indie rock, nearly all of the big successful records are loop-based: Animal Collective's Strawberry Jam, Battles' Mirrored, Menomena's Friend and Foe, Bjork's Volta, Radiohead's In Rainbows, Girl Talk, etc. etc.).</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/music" rel="tag">music</a>, <a href="http://www.technorati.com/tags/history" rel="tag">history</a>, <a href="http://www.technorati.com/tags/internet" rel="tag">internet</a>, <a href="http://www.technorati.com/tags/napster" rel="tag">napster</a>, <a href="http://www.technorati.com/tags/itunes" rel="tag">itunes</a>, <a href="http://www.technorati.com/tags/drm" rel="tag">drm</a>, <a href="http://www.technorati.com/tags/amazon" rel="tag">amazon</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>50 Blog Posts I&apos;d Like to See in 2008</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2007/12/50-blog-posts-id-like-to-see-i.html" />
    <id>tag:www2.urbanhonking.com,2007:/ideasfordozens//44.9098</id>

    <published>2007-12-26T21:18:41Z</published>
    <updated>2008-04-14T00:52:23Z</updated>

    <summary> A while back, noted social media commentator Chris Brogan published a list of 100 blog posts he&apos;d like to see other people write. The list was meant as a spur in the backside of readers who suffer from Blogger&apos;s...</summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="learns_to" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>
	A while back, noted social media commentator Chris Brogan published a list of <a href="http://chrisbrogan.com/100-blog-topics-i-hope-you-write/">100 blog posts he'd like to see other people write</a>. The list was meant as a spur in the backside of readers who suffer from Blogger's Block, a final blow to the excuse that they can't think of anything to write about.  While Brogan's actual topics were too focused on the incestuously insider world of social media for my taste ("44. The Difference Between Fark and Truemors"), the format was inspiring; I immediately started putting together my own list of posts I'd like to see.
</p>
<p>
	Inevitably, my list reflects my interests and bias just as Brogan's does his. The posts I'd like to see are largely aimed at people like me: people who picked up Ruby in the last couple of years because of Rails and have got the language and framework pretty handily under control but lack the deep rooting in technical fundamentals and culture that comes from having gone to school for this stuff or having had a long career in it.
</p>
<p>
	The theme is: "I know Ruby. Now what?" 
</p>
<p>
	 Like Brogan, I'll ask that if you write on one of these topics link back here or come back to comment so I can find your post and gradually turn this list into something of a directory of this kind of info. Now, without further ado, here's my list:
</p>

<ol>
	<li>My First C Extension</li>
	<li>A Set Theory Primer for Relational Database Users</li>
	<li>What I Get Out of My Local Ruby Users' Group</li>
	<li>All About Postgres Indexes</li>
	<li>Ruby Was My First Language, Here's My Second</li>
	<li>The Five Most Useful Things I Learned in Computer Science</li>
	<li>My First Contribution to an Open Source Project</li>
	<li>Participating Actively on Mailing Lists</li>
	<li>Participating Actively on IRC</li>
	<li>Understanding and Using Threads</li>
	<li>Keeping Up to Date with New Developments to the Libraries You Care About</li>
	<li>How to Write Good API Documentation</li>
	<li>An Intro to Code Research, Or: Is There A Library for That?</li>
	<li>An Intro to Queues, Pools, Runners, and Inter-Process Communication</li>
	<li>Unicode Once and for All</li>
	<li>Timezones Once and for All</li>
	<li>How Do Migrations Actually Work?</li>
	<li>Basic System Administration for Developers</li>
	<li>Domain-based Programming in Javascript</li>
	<li>Instrumenting My Rails App</li>
	<li>Approaches to Processing Large Data Sets</li>
	<li>A Developer's Guide to Deployment</li>
	<li>Bootstrapping Rails Development for the Absolute Beginner</li>
	<li>Hey Look, I Did Something Useful with LISP!</li>
	<li>Approaching Your Idols: How to Start Conversations with Gray Beards and Gurus</li>
	<li>My Painless Gem Integration System</li>
	<li>Using Your Own Documentation</li>
	<li>Building a Rails App from Someone Else's Excel Spreadsheet</li>
	<li>Useful Ruby Outside of Rails</li>
	<li>Ruby as PHP Replacement</li>
	<li>Writing Simple CGI Scripts with Ruby</li>
	<li>Finding and Fixing Memory Leaks in Rails, Or: Why Are My Mongrels So Big?</li>
	<li>Writing and Managing Long-Running Processes</li>
	<li>SMS Integration in Rails</li>
	<li>What I Learned from Working with Statically Typed Languages</li>
	<li>My First Profiling Session</li>
	<li>Big Team Tools and Small Teams, Or: Why Is My Trac Empty?</li>
	<li>Rules of Thumb for Performant Ruby Code</li>
	<li>A Survey of Persistence Strategies Beyond Relational Databases</li>
	<li>Living with a Large Schema</li>
	<li>My First Cocoa Program</li>
	<li>Writing and Distributing Rails Apps for Desktop Installation</li>
	<li>Domain Registration and Hosting for Rails Apps</li>
	<li>Setting Up Subdomains and Pointing Them at Rails Apps</li>
	<li>My First Apache Configuration</li>
	<li>My First Nginx Configuration</li>
	<li>Is It Worth Releasing?: When to Open Source Your Work</li>
	<li>An Introduction to GUI Programming</li>
	<li>Lessons from Java for Someone Who's Never Written Any</li>
	<li>Practical Tips for Learning Protocols and Reading Specs</li>
</ol>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/ruby" rel="tag">ruby</a>, <a href="http://www.technorati.com/tags/programming" rel="tag">programming</a>, <a href="http://www.technorati.com/tags/blog" rel="tag">blog</a>, <a href="http://www.technorati.com/tags/list" rel="tag">list</a>, <a href="http://www.technorati.com/tags/education" rel="tag">education</a>, <a href="http://www.technorati.com/tags/brogan" rel="tag">brogan</a></span>]]>
        
    </content>
</entry>

<entry>
    <title>What Happens When Web-Scale Computing Becomes a Commodity?</title>
    <link rel="alternate" type="text/html" href="http://www.urbanhonking.com/ideasfordozens/2007/12/what-happens-when-webscale-com.html" />
    <id>tag:www2.urbanhonking.com,2007:/ideasfordozens//44.9097</id>

    <published>2007-12-18T04:08:07Z</published>
    <updated>2008-04-14T00:52:23Z</updated>

    <summary><![CDATA[With the announcement of Amazon's much-anticipated SimpleDB service this week, we now officially live in a world where the kind of enormous systems run by Google, Yahoo, Ebay, et al &mdash; systems that power huge portions of the web (where...]]></summary>
    <author>
        <name></name>
        
    </author>
    
        <category term="useful web" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.urbanhonking.com/ideasfordozens/">
        <![CDATA[<p>With the announcement of Amazon's much-anticipated <a href="http://www.amazon.com/b?ie=UTF8&amp;node=342335011">SimpleDB</a> service this week, we now officially live in a world where the kind of enormous systems run by Google, Yahoo, Ebay, et al &mdash; systems that power huge portions of the web (where 500+ million users is totally mundane) &mdash; are available on demand in small doses and at reasonable prices to anyone who needs them. Amazon Web Services now provides all the necessary infrastructure to run applications that host millions of files for download, persist hundreds of millions of database records, and run thousands of processes, all without building or maintaining any physical infrastructure.</p>
	
</p>On this infrastructure, the only real difference between running a small application (a custom CMS for a medium-sized non-profit, for example) and a large one (say, <a href="http://digg.com">Digg</a>) is the size of your monthly bill. And as other companies besides Amazon enter this market as a relatively simple way to monetize their huge existing infrastructure costs the size of that bill will fall as well.</p>

<p>So, what are we talking about here? Within a few years, a scale of computation that is currently only available to a handful of multi-billion dollar companies will be available to any pair of dorm room-bound hacker kids with $30/mo. and a pair of MacBooks. 
	
<p>Just as the rise of commodity server hardware and open source software revolutionized the web over the last ten years, it would be reasonable to expect changes of similarly breathtaking scope as we undergo the commoditization of web-scale computing over the next ten.</p>

<p>For a few clues as to what happens when the current, if obscure, state of the art becomes an industry-standard lowest common denominator, it helps to look at some history. This has happened at least twice in the last thirty years: once when industry standardization around x86 hardware lead to the collapse in prices for DOS- and then Windows-compatible PCs that made them ubiquitous around the world; and again when these same PCs reached a level of power and the open source software written to run on them reached a level of affordability and reliability that, together, they displaced the expensive and proprietary server systems and radically lowered the barrier to entry for web-development leading, <a href="http://www.oreillynet.com/pub/a/oreilly/tim/news/2005/09/30/what-is-web-20.html" title="">as Tim O'Reilly has clearly outlined</a>, to Web 2.0.</p>

<p>Each of these transitions had the same two high level effects: they made it cheaper to produce professional caliber work and they increased the value of openness.</p>

<p>The rise of the ubiquitous, cheap, and powerful PC has created near-universal access to the best digital tools available. Professional accountants, graphic designers, record producers, photographers, and countless others do their work on exactly the same relatively cheap hardware available to the average consumer playing games and writing email.</p>
<p>Similarly, the precipitous pricing drop in web application development and deployment environments caused by the birth of the LAMP stack and the commodity servers on which it runs made it possible for startups like <a href="http://del.icio.us">del.icio.us</a> and <a href="http://flickr.com">Flickr</a> without first raising millions of dollars in venture funding to buy Sun Workstations. (And this doesn't even take into account the second order revolution in the content industry caused by the cheap-to-free hosting publishing tools created by these very startups and run on commodity web hosting.)</p>

<p>The openness story is, if anything, even more shocking. Like fruit flies spontaneously generating out of garbage, Linux grew out of the universally available commodity PCs with their high levels of hardware compatibility. The same process that filled the PC landscape with identical gray boxes running Windows made it possible for a few OS geeks from obscure countries to build, in their spare time, an operating system that could feasibly run, for free, on all of them.</p>

<p>Similarly, the commoditization provided by the triumph of the LAMP stack made it possible for a handful of people to build non-profit web applications like Wikipedia and Craig's List whose only mission is to make useful information universally available to anyone who wants it.</p>

<p>Now. What form will these two kinds of changes take with the use of web-scale computing?</p>

<p>Let's start out with the ability to produce professional caliber work more cheaply. Currently now, it was only feasibly to build web-scale applications if the market for them was also web-scale. That is, you only got to use resource intensive technologies like full web spidering or massive file caching if you were building a mainstream service with a potential audience of 500+ million daily users. This meant the basics: search, ads, maybe games.</p>

<p>But, when doing these things only costs a couple hundred bucks a month, a great many smaller markets suddenly become lucrative. Could you build value on top of a dynamically updated list of every mention made of every stock ticker symbol anywhere on the web? How about every mention of every trademark? Or <a href="http://grabb.it">every mention of every mp3</a>? Since the overhead for extracting that value no longer includes building and maintaining enormous data centers it might actually become feasible to build service with such requirements.</p>

<p>(As a side note, it's worth noting that one of the corollary effects of such a change is that it's no longer necessary to take tens of millions of dollars in venture funding in order to run a business that requires web-scale computing. This means even more leverage for startups when negotiating for what little funding they do need and even shakier times ahead for the VCs out there looking to invest their billions in only a small handful of huge deals.)</p>

<p>And what about openness? What new prospects for collaborative networked volunteer-driven world-improving projects might we see?</p>

<p>How about a Web OS that runs on top of a peer-to-peer network of commodity machines that's available to anyone who contributes some spare cycles to the cause &mdash; like a Google-scale Linux install running on top of SETI-at-home? Or what about a world-wide effort to federate the tracking of all manufactured objects via their RFID tags in order to maximize the efficiency of their recycling, discover any of their toxic effects, and rollback global warming?</p>

<p>These ideas may seem silly or grandiose, but so did Google when Larry and Sergei were still students or Linux when it was just an excuse for mailing list flame wars. This is one of those times. A lot of new things just became possible.</p>

<span class='technoratitag'>Tagged: <a href="http://www.technorati.com/tags/simpledb" rel="tag">simpledb</a>, <a href="http://www.technorati.com/tags/amazon" rel="tag">amazon</a>, <a href="http://www.technorati.com/tags/google" rel="tag">google</a>, <a href="http://www.technorati.com/tags/web-scale" rel="tag">web-scale</a>, <a href="http://www.technorati.com/tags/computing" rel="tag">computing</a>, <a href="http://www.technorati.com/tags/linux" rel="tag">linux</a></span>]]>
        
    </content>
</entry>

</feed>
