mirror of
https://github.com/samsonjs/samhuri.net.git
synced 2026-03-25 09:05:47 +00:00
640 lines
31 KiB
HTML
640 lines
31 KiB
HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<title>sjs: Embrace the database</title>
|
|
|
|
<link rel="openid.server" href="http://www.myopenid.com/server" />
|
|
<link rel="openid.delegate" href="http://sami-samhuri.myopenid.com/" />
|
|
<meta http-equiv="X-XRDS-Location" content="http://sami-samhuri.myopenid.com/xrds" />
|
|
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
|
<link rel="alternate" type="application/rss+xml" title="RSS" href="http://feeds.feedburner.com/sjs" />
|
|
|
|
|
|
<script src="http://web.archive.org/web/20071202091244js_/http://sami.samhuri.net/javascripts/prototype.js" type="text/javascript"></script>
|
|
|
|
<link href="http://web.archive.org/web/20071202091244cs_/http://sami.samhuri.net/stylesheets/application.css" rel="stylesheet" type="text/css" />
|
|
</head>
|
|
<body>
|
|
<!-- BEGIN WAYBACK TOOLBAR INSERT -->
|
|
|
|
<script type="text/javascript" src="http://staticweb.archive.org/js/disclaim-element.js" ></script>
|
|
<script type="text/javascript" src="http://staticweb.archive.org/js/graph-calc.js" ></script>
|
|
<script type="text/javascript" src="http://staticweb.archive.org/jflot/jquery.min.js" ></script>
|
|
<script type="text/javascript">
|
|
//<![CDATA[
|
|
var firstDate = 820454400000;
|
|
var lastDate = 1325375999999;
|
|
var wbPrefix = "http://web.archive.org/web/";
|
|
var wbCurrentUrl = "http://sami.samhuri.net/2007/6/22/embrace-the-database";
|
|
|
|
var curYear = -1;
|
|
var curMonth = -1;
|
|
var yearCount = 16;
|
|
var firstYear = 1996;
|
|
var imgWidth=400;
|
|
var yearImgWidth = 25;
|
|
var monthImgWidth = 2;
|
|
var trackerVal = "none";
|
|
var displayDay = "2";
|
|
var displayMonth = "Dec";
|
|
var displayYear = "2007";
|
|
var prettyMonths = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
|
|
|
function showTrackers(val) {
|
|
if(val == trackerVal) {
|
|
return;
|
|
}
|
|
if(val == "inline") {
|
|
document.getElementById("displayYearEl").style.color = "#ec008c";
|
|
document.getElementById("displayMonthEl").style.color = "#ec008c";
|
|
document.getElementById("displayDayEl").style.color = "#ec008c";
|
|
} else {
|
|
document.getElementById("displayYearEl").innerHTML = displayYear;
|
|
document.getElementById("displayYearEl").style.color = "#ff0";
|
|
document.getElementById("displayMonthEl").innerHTML = displayMonth;
|
|
document.getElementById("displayMonthEl").style.color = "#ff0";
|
|
document.getElementById("displayDayEl").innerHTML = displayDay;
|
|
document.getElementById("displayDayEl").style.color = "#ff0";
|
|
}
|
|
document.getElementById("wbMouseTrackYearImg").style.display = val;
|
|
document.getElementById("wbMouseTrackMonthImg").style.display = val;
|
|
trackerVal = val;
|
|
}
|
|
function getElementX2(obj) {
|
|
var thing = jQuery(obj);
|
|
if((thing == undefined)
|
|
|| (typeof thing == "undefined")
|
|
|| (typeof thing.offset == "undefined")) {
|
|
return getElementX(obj);
|
|
}
|
|
return Math.round(thing.offset().left);
|
|
}
|
|
function trackMouseMove(event,element) {
|
|
|
|
var eventX = getEventX(event);
|
|
var elementX = getElementX2(element);
|
|
var xOff = eventX - elementX;
|
|
if(xOff < 0) {
|
|
xOff = 0;
|
|
} else if(xOff > imgWidth) {
|
|
xOff = imgWidth;
|
|
}
|
|
var monthOff = xOff % yearImgWidth;
|
|
|
|
var year = Math.floor(xOff / yearImgWidth);
|
|
var yearStart = year * yearImgWidth;
|
|
var monthOfYear = Math.floor(monthOff / monthImgWidth);
|
|
if(monthOfYear > 11) {
|
|
monthOfYear = 11;
|
|
}
|
|
// 1 extra border pixel at the left edge of the year:
|
|
var month = (year * 12) + monthOfYear;
|
|
var day = 1;
|
|
if(monthOff % 2 == 1) {
|
|
day = 15;
|
|
}
|
|
var dateString =
|
|
zeroPad(year + firstYear) +
|
|
zeroPad(monthOfYear+1,2) +
|
|
zeroPad(day,2) + "000000";
|
|
|
|
var monthString = prettyMonths[monthOfYear];
|
|
document.getElementById("displayYearEl").innerHTML = year + 1996;
|
|
document.getElementById("displayMonthEl").innerHTML = monthString;
|
|
// looks too jarring when it changes..
|
|
//document.getElementById("displayDayEl").innerHTML = zeroPad(day,2);
|
|
|
|
var url = wbPrefix + dateString + '/' + wbCurrentUrl;
|
|
document.getElementById('wm-graph-anchor').href = url;
|
|
|
|
//document.getElementById("wmtbURL").value="evX("+eventX+") elX("+elementX+") xO("+xOff+") y("+year+") m("+month+") monthOff("+monthOff+") DS("+dateString+") Moy("+monthOfYear+") ms("+monthString+")";
|
|
if(curYear != year) {
|
|
var yrOff = year * yearImgWidth;
|
|
document.getElementById("wbMouseTrackYearImg").style.left = yrOff + "px";
|
|
curYear = year;
|
|
}
|
|
if(curMonth != month) {
|
|
var mtOff = year + (month * monthImgWidth) + 1;
|
|
document.getElementById("wbMouseTrackMonthImg").style.left = mtOff + "px";
|
|
curMonth = month;
|
|
}
|
|
}
|
|
//]]>
|
|
</script>
|
|
|
|
<style type="text/css">body{margin-top:0!important;padding-top:0!important;min-width:800px!important;}#wm-ipp a:hover{text-decoration:underline!important;}</style>
|
|
<div id="wm-ipp" style="display:none; position:relative;padding:0 5px;min-height:70px;min-width:800px; z-index:9000;">
|
|
<div id="wm-ipp-inside" style="position:fixed;padding:0!important;margin:0!important;width:97%;min-width:780px;border:5px solid #000;border-top:none;background-image:url(http://staticweb.archive.org/images/toolbar/wm_tb_bk_trns.png);text-align:center;-moz-box-shadow:1px 1px 3px #333;-webkit-box-shadow:1px 1px 3px #333;box-shadow:1px 1px 3px #333;font-size:11px!important;font-family:'Lucida Grande','Arial',sans-serif!important;">
|
|
<table style="border-collapse:collapse;margin:0;padding:0;width:100%;"><tbody><tr>
|
|
<td style="padding:10px;vertical-align:top;min-width:110px;">
|
|
<a href="http://wayback.archive.org/web/" title="Wayback Machine home page" style="background-color:transparent;border:none;"><img src="http://staticweb.archive.org/images/toolbar/wayback-toolbar-logo.png" alt="Wayback Machine" width="110" height="39" border="0"/></a>
|
|
</td>
|
|
<td style="padding:0!important;text-align:center;vertical-align:top;width:100%;">
|
|
|
|
<table style="border-collapse:collapse;margin:0 auto;padding:0;width:570px;"><tbody><tr>
|
|
<td style="padding:3px 0;" colspan="2">
|
|
<form target="_top" method="get" action="http://wayback.archive.org/web/form-submit.jsp" name="wmtb" id="wmtb" style="margin:0!important;padding:0!important;"><input type="text" name="url" id="wmtbURL" value="http://sami.samhuri.net/2007/6/22/embrace-the-database" style="width:400px;font-size:11px;font-family:'Lucida Grande','Arial',sans-serif;" onfocus="javascript:this.focus();this.select();" /><input type="hidden" name="type" value="replay" /><input type="hidden" name="date" value="20071202091244" /><input type="submit" value="Go" style="font-size:11px;font-family:'Lucida Grande','Arial',sans-serif;margin-left:5px;" /><span id="wm_tb_options" style="display:block;"></span></form>
|
|
</td>
|
|
<td style="vertical-align:bottom;padding:5px 0 0 0!important;" rowspan="2">
|
|
<table style="border-collapse:collapse;width:110px;color:#99a;font-family:'Helvetica','Lucida Grande','Arial',sans-serif;"><tbody>
|
|
|
|
<!-- NEXT/PREV MONTH NAV AND MONTH INDICATOR -->
|
|
<tr style="width:110px;height:16px;font-size:10px!important;">
|
|
<td style="padding-right:9px;font-size:11px!important;font-weight:bold;text-transform:uppercase;text-align:right;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
|
|
|
Nov
|
|
|
|
</td>
|
|
<td id="displayMonthEl" style="background:#000;color:#ff0;font-size:11px!important;font-weight:bold;text-transform:uppercase;width:34px;height:15px;padding-top:1px;text-align:center;" title="You are here: 9:12:44 Dec 2, 2007">DEC</td>
|
|
<td style="padding-left:9px;font-size:11px!important;font-weight:bold;text-transform:uppercase;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
|
|
|
<a href="http://sami.samhuri.net/2007/6/22/embrace-the-database" style="text-decoration:none;color:#33f;font-weight:bold;background-color:transparent;border:none;" title="20 Aug 2008"><strong>AUG</strong></a>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- NEXT/PREV CAPTURE NAV AND DAY OF MONTH INDICATOR -->
|
|
<tr>
|
|
<td style="padding-right:9px;white-space:nowrap;overflow:visible;text-align:right!important;vertical-align:middle!important;" nowrap="nowrap">
|
|
|
|
<img src="http://staticweb.archive.org/images/toolbar/wm_tb_prv_off.png" alt="Previous capture" width="14" height="16" border="0" />
|
|
|
|
</td>
|
|
<td id="displayDayEl" style="background:#000;color:#ff0;width:34px;height:24px;padding:2px 0 0 0;text-align:center;font-size:24px;font-weight: bold;" title="You are here: 9:12:44 Dec 2, 2007">2</td>
|
|
<td style="padding-left:9px;white-space:nowrap;overflow:visible;text-align:left!important;vertical-align:middle!important;" nowrap="nowrap">
|
|
|
|
<a href="http://sami.samhuri.net/2007/6/22/embrace-the-database" title="11:44:10 Aug 20, 2008" style="background-color:transparent;border:none;"><img src="http://staticweb.archive.org/images/toolbar/wm_tb_nxt_on.png" alt="Next capture" width="14" height="16" border="0"/></a>
|
|
|
|
</td>
|
|
</tr>
|
|
|
|
<!-- NEXT/PREV YEAR NAV AND YEAR INDICATOR -->
|
|
<tr style="width:110px;height:13px;font-size:9px!important;">
|
|
<td style="padding-right:9px;font-size:11px!important;font-weight: bold;text-align:right;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
|
|
|
2006
|
|
|
|
</td>
|
|
<td id="displayYearEl" style="background:#000;color:#ff0;font-size:11px!important;font-weight: bold;padding-top:1px;width:34px;height:13px;text-align:center;" title="You are here: 9:12:44 Dec 2, 2007">2007</td>
|
|
<td style="padding-left:9px;font-size:11px!important;font-weight: bold;white-space:nowrap;overflow:visible;" nowrap="nowrap">
|
|
|
|
2008
|
|
|
|
</td>
|
|
</tr>
|
|
</tbody></table>
|
|
</td>
|
|
|
|
</tr>
|
|
<tr>
|
|
<td style="vertical-align:middle;padding:0!important;">
|
|
<a href="http://wayback.archive.org/web/20071202091244*/http://sami.samhuri.net/2007/6/22/embrace-the-database" style="color:#33f;font-size:11px;font-weight:bold;background-color:transparent;border:none;" title="See a list of every capture for this URL"><strong>2 captures</strong></a>
|
|
<div style="margin:0!important;padding:0!important;color:#666;font-size:9px;padding-top:2px!important;white-space:nowrap;" title="Timespan for captures of this URL">2 Dec 07 - 20 Aug 08</div>
|
|
</td>
|
|
<td style="padding:0!important;">
|
|
<a style="position:relative; white-space:nowrap; width:400px;height:27px;" href="" id="wm-graph-anchor">
|
|
<div id="wm-ipp-sparkline" style="position:relative; white-space:nowrap; width:400px;height:27px;background-color:#fff;cursor:pointer;border-right:1px solid #ccc;" title="Explore captures for this URL">
|
|
<img id="sparklineImgId" style="position:absolute; z-index:9012; top:0px; left:0px;"
|
|
onmouseover="showTrackers('inline');"
|
|
onmouseout="showTrackers('none');"
|
|
onmousemove="trackMouseMove(event,this)"
|
|
alt="sparklines"
|
|
width="400"
|
|
height="27"
|
|
border="0"
|
|
src="http://wayback.archive.org/jsp/graph.jsp?graphdata=400_27_1996:-1:000000000000_1997:-1:000000000000_1998:-1:000000000000_1999:-1:000000000000_2000:-1:000000000000_2001:-1:000000000000_2002:-1:000000000000_2003:-1:000000000000_2004:-1:000000000000_2005:-1:000000000000_2006:-1:000000000000_2007:11:000000000001_2008:-1:000000010000_2009:-1:000000000000_2010:-1:000000000000_2011:-1:000000000000"></img>
|
|
<img id="wbMouseTrackYearImg"
|
|
style="display:none; position:absolute; z-index:9010;"
|
|
width="25"
|
|
height="27"
|
|
border="0"
|
|
src="http://staticweb.archive.org/images/toolbar/transp-yellow-pixel.png"></img>
|
|
<img id="wbMouseTrackMonthImg"
|
|
style="display:none; position:absolute; z-index:9011; "
|
|
width="2"
|
|
height="27"
|
|
border="0"
|
|
src="http://staticweb.archive.org/images/toolbar/transp-red-pixel.png"></img>
|
|
</div>
|
|
</a>
|
|
|
|
</td>
|
|
</tr></tbody></table>
|
|
</td>
|
|
<td style="text-align:right;padding:5px;width:65px;font-size:11px!important;">
|
|
<a href="javascript:;" onclick="document.getElementById('wm-ipp').style.display='none';" style="display:block;padding-right:18px;background:url(http://staticweb.archive.org/images/toolbar/wm_tb_close.png) no-repeat 100% 0;color:#33f;font-family:'Lucida Grande','Arial',sans-serif;margin-bottom:23px;background-color:transparent;border:none;" title="Close the toolbar">Close</a>
|
|
<a href="http://faq.web.archive.org/" style="display:block;padding-right:18px;background:url(http://staticweb.archive.org/images/toolbar/wm_tb_help.png) no-repeat 100% 0;color:#33f;font-family:'Lucida Grande','Arial',sans-serif;background-color:transparent;border:none;" title="Get some help using the Wayback Machine">Help</a>
|
|
</td>
|
|
</tr></tbody></table>
|
|
|
|
</div>
|
|
</div>
|
|
<script type="text/javascript">
|
|
var wmDisclaimBanner = document.getElementById("wm-ipp");
|
|
if(wmDisclaimBanner != null) {
|
|
disclaimElement(wmDisclaimBanner);
|
|
}
|
|
</script>
|
|
<!-- END WAYBACK TOOLBAR INSERT -->
|
|
|
|
<div id="container">
|
|
<div id="header">
|
|
<h1><span><a href="http://sami.samhuri.net/">sjs</a></span></h1>
|
|
<h2>geeky ramblings</h2>
|
|
</div>
|
|
|
|
<div id="page">
|
|
<div id="content">
|
|
|
|
|
|
<!--
|
|
<rdf:RDF
|
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
|
<rdf:Description
|
|
rdf:about=""
|
|
trackback:ping=""
|
|
dc:title="Embrace the database"
|
|
dc:identifier="/2007/6/22/embrace-the-database"
|
|
dc:description="<p>If you drink the Rails koolaid you may have read the notorious <a href="http://www.loudthinking.com/arc/2005_09.html">single layer of cleverness</a> post by <a href="http://www.loudthinking.com">DHH</a>. <em>[5th post..."
|
|
dc:creator="sjs"
|
|
dc:date="June 22, 2007 10:14" />
|
|
</rdf:RDF>
|
|
-->
|
|
|
|
<div class="hentry" id="article-92">
|
|
<h2 class="entry-title">
|
|
<a href="http://sami.samhuri.net/2007/6/22/embrace-the-database">Embrace the database</a>
|
|
|
|
<span class="comment_count">0</span>
|
|
|
|
</h2>
|
|
<div class="vcard">
|
|
Posted by <span class="fn">sjs</span>
|
|
</div>
|
|
<abbr class="published" title="2007-06-22T10:14:00+00:00">on Friday, June 22</abbr>
|
|
<br class="clear" />
|
|
<div class="entry-content">
|
|
<p>If you drink the Rails koolaid you may have read the notorious <a href="http://www.loudthinking.com/arc/2005_09.html">single layer of cleverness</a> post by <a href="http://www.loudthinking.com/">DHH</a>. <em>[5th post on the archive page]</em> In a nutshell he states that it's better to have a single point of cleverness when it comes to business logic. The reasons for this include staying agile, staying in Ruby all the time, and being able to switch the back-end DB at any time. Put the logic in ActiveRecord and use the DB as a dumb data store, that is the Rails way. It's simple. It works. You don't need to be a DBA to be a Rails developer.</p>
|
|
|
|
|
|
<p><a href="http://www.stephenbartholomew.co.uk/">Stephen</a> created a Rails plugin called <a href="http://www.stephenbartholomew.co.uk/2007/6/22/dependent-raise">dependent-raise</a> which imitates a foreign key constraint inside of Rails. I want to try this out because I believe that data integrity is fairly important, but it's really starting to make me think about this single point of cleverness idea.</p>
|
|
|
|
|
|
<p>Are we not reinventing the wheel by employing methods such as this in our code? Capable DBs already do this sort of thing for us. I don't necessarily think it's bad to implement this sort of thing, but I think it's a symptom of NIH syndrome. Instead of reinventing this kind of thing why don't we embrace the DB as a semi-intelligent data store? The work has been done all we have to do is exploit it via Rails.</p>
|
|
|
|
|
|
<p>There are a few reasons that the Rails folks choose not to do so but perhaps some of them could be worked around. Adapting your solution as you progress and realise that things aren't exactly as you thought they were... I believe the word for that sort of thing is agility.</p>
|
|
|
|
|
|
<h3>Database agnosticism</h3>
|
|
|
|
|
|
<p>From SQLite to Oracle, just configure the connection, migrate, and run your app on any database. One of the biggest Rails myths that is backed by the Rails team themselves. It takes a fair amount of work to ensure that any significant app is fully agnostic. Sure you can develop on SQLite and deploy on MySQL without much trouble but there are significant diffirences between RDBMSs that will manifest themselves if you create an app that's more than a toy. Oh, you used finder_sql? Sorry but chances are your app is no longer DB agnostic. FAIL.</p>
|
|
|
|
|
|
<p><strong>Solution:</strong> Drop the lie. Tell people the truth. Theoretically, theory and practice are the same; in practice they are not. Be honest that it's <em>possible</em> to be DB-agnostic but can be a challenge. Under no circumstances should we shun something useful in the name of claiming to be DB-agnostic.</p>
|
|
|
|
|
|
<h3>Staying agile</h3>
|
|
|
|
|
|
<p>If we start making use of FK constraints then we'll have to make changes to both our DB and our code. This makes change more time-consuming and error-prone which means change is less likely to happen. This goes against the grain of an agile methodology. Or does it?</p>
|
|
|
|
|
|
<p><strong>Solution:</strong> Rails should use the features of the DB to keep data intact and fall back on an AR-only solution only if the DB doesn't support the operation. There doesn't need to be any duplication in logic rules either. If Rails could recognise a FK constraint that cascades on delete it could set up the <code>has_many :foos, :dependent => :destroy</code> relation for us. In fact I only see our code becoming DRYer (maybe even too DRY[1]).</p>
|
|
|
|
|
|
<h3>Staying in Ruby</h3>
|
|
|
|
|
|
<p>Using the DB from within Ruby is a solved problem. I don't see why this couldn't be extended to handle more of the DB as well. Use Ruby, but use it intelligently by embracing outside tools to get the job done.</p>
|
|
|
|
|
|
<p>Many relationships could be derived from constraints as people have pointed out before. There are benefits to using the features of a decent RDBMS, and in some cases I think that we might be losing by not making use of them. I am not saying we should move everything to the DB, I am saying that we should exploit the implemented and debugged capabilities of our RDBMSs the best we can while practicing the agile methods we know and love, all from within Ruby.</p>
|
|
|
|
|
|
<p>[1] I make liberal use of <a href="http://agilewebdevelopment.com/plugins/annotate_models">annotate_models</a> as it is.</p>
|
|
|
|
</div>
|
|
<ul class="meta">
|
|
|
|
|
|
<li>
|
|
Tags: <a href="http://sami.samhuri.net/tags/activerecord">activerecord</a> <a href="http://sami.samhuri.net/tags/rails">rails</a> <a href="http://sami.samhuri.net/tags/ruby">ruby</a>
|
|
</li>
|
|
|
|
<li>
|
|
Meta:
|
|
|
|
<a href="http://sami.samhuri.net/2007/6/22/embrace-the-database">0 comments</a>,
|
|
|
|
<a href="http://sami.samhuri.net/2007/6/22/embrace-the-database">permalink</a>
|
|
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<h5><a name="comments">Comments</a></h5>
|
|
<p><a href="http://sami.samhuri.net/2007/6/22/embrace-the-database#comment-form">Leave a response</a></p>
|
|
<div id="comments_div">
|
|
<ol id="comments" class="comments">
|
|
|
|
</ol>
|
|
</div>
|
|
|
|
<form id="comment-form" method="post" action="http://sami.samhuri.net/2007/6/22/embrace-the-database/comments#comment-form">
|
|
<fieldset>
|
|
<legend>Comment</legend>
|
|
<p>
|
|
<label class="text" for="comment_author">Name:</label><br/>
|
|
<input type="text" id="comment_author" name="comment[author]" value="" />
|
|
</p>
|
|
<p>
|
|
<label class="text" for="comment_author_email">Email Address:</label><br />
|
|
<input type="text" id="comment_author_email" name="comment[author_email]" value="" />
|
|
</p>
|
|
<p>
|
|
<label class="text" for="comment_author_url">Website:</label><br />
|
|
<input type="text" id="comment_author_url" name="comment[author_url]" value="" />
|
|
</p>
|
|
<p>
|
|
<label class="text" for="comment_body">Comment:</label><br />
|
|
<textarea id="comment_body" name="comment[body]"></textarea>
|
|
</p>
|
|
<div class="formactions">
|
|
<input type="submit" value="Post comment" class="submit" />
|
|
</div>
|
|
</fieldset>
|
|
</form>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<div id="sidebar">
|
|
|
|
<div class="sidebar-node">
|
|
<div id="search" class="search">
|
|
<form action="http://sami.samhuri.net/search" id="sform" method="get" name="sform">
|
|
<p><input type="text" id="q" name="q" value="" /></p>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="sidebar-node">
|
|
<h3>Sections</h3>
|
|
<ul>
|
|
|
|
<li><a href="http://sami.samhuri.net/">geeky ramblings</a> (15)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/emacs">Emacs</a> (3)</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="sidebar-node">
|
|
<h3>Tags</h3>
|
|
<ul>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/activerecord">activerecord</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/alsa">alsa</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/amusement">amusement</a> (6)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/apple">apple</a> (6)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/bdd">bdd</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/broken">broken</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/browsers">browsers</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/buffalo">buffalo</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/bundle">bundle</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/cheat">cheat</a> (3)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/coding">coding</a> (22)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/cool">cool</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/coverflow">coverflow</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/crazy">crazy</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/digg">digg</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/drm">drm</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/dtrace">dtrace</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/elschemo">elschemo</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/emacs">emacs</a> (11)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/english">english</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/extensions">extensions</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/firefox">firefox</a> (3)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/framework">framework</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/funny">funny</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/fuse">fuse</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/games">games</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/gentoo">gentoo</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/german">german</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/gtkpod">gtkpod</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/haskell">haskell</a> (7)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/humans">humans</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/injury">injury</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/inspirado">inspirado</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/iphone">iphone</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/itunes">itunes</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/i_laughed_i_cried">i_laughed_i_cried</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/keyboard">keyboard</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/keyboard%20shortcuts">keyboard shortcuts</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/lemmings">lemmings</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/life">life</a> (11)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/linux">linux</a> (7)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/lisp">lisp</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/mac%20os%20x">mac os x</a> (6)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/mediawiki">mediawiki</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/mephisto">mephisto</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/migrations">migrations</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/munich">munich</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/mysql">mysql</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/networking">networking</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/opera">opera</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/pedantry">pedantry</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/people">people</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/photo">photo</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/php">php</a> (4)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/propaganda">propaganda</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/python">python</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/quickcheck">quickcheck</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/rails">rails</a> (18)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/rails%20on%20rules">rails on rules</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/regex">regex</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/regular%20expressions">regular expressions</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/rest">rest</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/rtfm">rtfm</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/ruby">ruby</a> (14)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/rushcheck">rushcheck</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/sake">sake</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/scheme">scheme</a> (4)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/school">school</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/seaside">seaside</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/secure%20associations">secure associations</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/seekport">seekport</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/snippets">snippets</a> (3)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/tagify">tagify</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/technology">technology</a> (6)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/test/spec">test/spec</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/textmate">textmate</a> (7)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/tips">tips</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/typo">typo</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/ubuntu">ubuntu</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/usability">usability</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/userscript">userscript</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/vim">vim</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/volume">volume</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/web%20objects">web objects</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/wikipediafs">wikipediafs</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/windows">windows</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/work">work</a> (1)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/zend">zend</a> (2)</li>
|
|
|
|
<li><a href="http://sami.samhuri.net/tags/zsh">zsh</a> (1)</li>
|
|
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
<div class="sidebar-node">
|
|
<h3>Friends & cool blogs</h3>
|
|
<ul>
|
|
<li><a href="http://jim.roepcke.com/">have browser, will travel</a></li>
|
|
<li><a href="http://cassandrahill.blogspot.com/">cj's chatter</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="sidebar-node">
|
|
<p><a href="http://twitter.com/_sjs">
|
|
<img src="http://web.archive.org/web/20071202091244im_/http://sami.samhuri.net/assets/2007/6/26/icon_twitter.png" alt="[t]" /> twitter</a></p>
|
|
</div>
|
|
|
|
<div class="sidebar-node">
|
|
<p><a href="http://mephistoblog.com/" class="powered"><img alt="mephisto-badge-tiny" src="http://web.archive.org/web/20071202091244im_/http://sami.samhuri.net/images/mephisto-badge-tiny.png" /></a></p>
|
|
</div>
|
|
|
|
</div>
|
|
<br style="clear:both;" />
|
|
|
|
</div>
|
|
|
|
<div id="footer">
|
|
<hr />
|
|
<p><a href="http://sami.samhuri.net/">sjs</a></p>
|
|
<ul>
|
|
<li>powered by <a href="http://mephistoblog.com/">Mephisto</a> /
|
|
styled with <a href="http://quotedprintable.com/pages/scribbish">scribbish</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<script src="http://web.archive.org/web/20071202091244js_/http://www.google-analytics.com/urchin.js" type="text/javascript"> </script>
|
|
<script type="text/javascript"> _uacct = "UA-214054-3"; urchinTracker(); </script>
|
|
<script src="http://web.archive.org/web/20071202091244js_/http://feeds.feedburner.com/~s/sjs" type="text/javascript" charset="utf-8"></script>
|
|
|
|
</body>
|
|
</html>
|
|
|
|
|
|
|
|
|
|
|
|
<!--
|
|
FILE ARCHIVED ON 9:12:44 Dec 2, 2007 AND RETRIEVED FROM THE
|
|
INTERNET ARCHIVE ON 2:58:02 Aug 21, 2011.
|
|
JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
|
|
|
|
ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
|
|
SECTION 108(a)(3)).
|
|
-->
|