<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Directed Edge News</title>
	
	<link>http://blog.directededge.com</link>
	<description />
	<lastBuildDate>Tue, 15 Mar 2011 18:43:55 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/directededge" /><feedburner:info uri="directededge" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>The easiest way to add recommendations to your Rails app, announcing acts_as_edgy</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/m2WtXcg0uPw/</link>
		<comments>http://blog.directededge.com/2011/03/15/the-easiest-way-to-add-recommendations-to-your-rails-app-announcing-acts_as_edgy/#comments</comments>
		<pubDate>Tue, 15 Mar 2011 18:17:44 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=702</guid>
		<description><![CDATA[
So, there are two things I want to talk about.  The first is how our new beta hotness, acts_as_edgy, just made it super easy to add Directed Edge recommendations to Rails 2 apps.  How easy?  One line easy.
Recommendations the Easy Way
Let&#8217;s suppose for example that you&#8217;ve got a model called User and [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.directededge.com/wp-content/uploads/2011/03/rails-plus-directededge.png" alt="" title="Rails plus Directed Edge" width="250" height="111"/></p>
<p>So, there are two things I want to talk about.  The first is how our new beta hotness, <tt>acts_as_edgy</tt>, just made it super easy to add Directed Edge recommendations to Rails 2 apps.  How easy?  One line easy.</p>
<h3 style="margin-bottom: 1em">Recommendations the Easy Way</h3>
<p>Let&#8217;s suppose for example that you&#8217;ve got a model called User and another called Product.  And let&#8217;s also suppose that you support &#8220;likes&#8221; in your app, so you&#8217;ve got a model called Like too that just maps from a user ID to a product ID.  Now, you want to show people personalized recommendations when they log in and related products when they&#8217;re viewing product pages.  Nothing too exotic there.</p>
<p>So, here&#8217;s what you add to your app in that case:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  acts_as_edgy<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:like</span>, Like, Product<span style="color:#006600; font-weight:bold;">&#41;</span>
  ...
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The <tt>acts_as_edgy</tt> line is the whole shebang.  That&#8217;s it.  After that&#8217;s in there you&#8217;ve got rake tasks that let you do <tt>rake edgy:export</tt> and it&#8217;ll push your data over to our servers.  You can also have it automatically update your data with our web service on saves to your model.  Did I mention it&#8217;s easy?</p>
<p>Okay, okay.  So, yeah, I skipped the part about where you actually do something with the recommendations.  But that&#8217;s not rocket surgery either.  Now that you&#8217;ve got that in your model you can do:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">User.<span style="color:#9900CC;">first</span>.<span style="color:#9900CC;">edgy_recommended</span> <span style="color:#008000; font-style:italic;"># returns a list of recommended products based on likes</span>
Product.<span style="color:#9900CC;">first</span>.<span style="color:#9900CC;">edgy_related</span>  <span style="color:#008000; font-style:italic;"># returns a list of related products based on likes</span></pre></div></div>

<p>You can do much more complicated stuff too.  Our Black Magic figures out the route between models that you provide a list of.  One of the apps that we&#8217;ve been testing with is Spree.  Let&#8217;s say that we want to do product recommendations based on sales.  In Spree that means that we have to map a User to a Product, but there are a bunch of intermediaries:  Orders belong to a User, LineItems belong to an Order, LineItems also belong to a Variant and Variants belong to a Product.  Whew.  What&#8217;s that look like in <tt>acts_as_edgy</tt> nomenclature?</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> User <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
  acts_as_edgy<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:purchase</span>, Order, LineItem, Variant, Product<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#008000; font-style:italic;"># ...</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>You just list the models that it has to pass through on its way to its target and it figures out (or, well, tries to, this assumes you&#8217;ve used nice consistent column names, which you of course did, didn&#8217;t you?) how to get there.</p>
<p>And then, once again, we can just query for related and recommended stuff like it&#8217;s nobody&#8217;s business.</p>
<p>You also have access to the regular stuff that our API supports.  So if you had both likes and purchases in the same application, that&#8217;s where that handle sitting up there right at the front of the <tt>acts_as_edgy</tt> line comes in handy.  You can chose how you want to weight those, e.g.:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Product.<span style="color:#9900CC;">first</span>.<span style="color:#9900CC;">edgy_related</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:like_weight</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0.1</span>, <span style="color:#ff3333; font-weight:bold;">:purchase_weight</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">0.9</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>And there you&#8217;ve got recommendations based on some mix and match weights that seem appropriate to you.</p>
<p>I wanted to get the cool stuff out first, but there are naturally a couple of set up steps that have to happen beforehand:</p>
<p><strong>THIS IS THE PART YOU ACTUALLY HAVE TO READ</strong></p>
<ol>
<li><strong><a href="http://www.directededge.com/signup.html">Sign up for a Directed Edge account</a></strong></li>
<li>Install the <tt><a href="http://rubygems.org/gems/directed-edge">directed-edge</a></tt> and <tt><a href="http://rubygems.org/gems/will_paginate">will_paginate</a></tt> gems</li>
<li>Install the <a href="https://github.com/directededge/acts_as_edgy">plugin</a></li>
<li>Run <tt>rake edgy:configure</tt> to enter your login info</li>
</ol>
<p>There&#8217;s more on the nuts and bolts of that over on the <a href="https://github.com/directededge/acts_as_edgy">Github page</a>, and just let us know if you get stuck.  But here&#8217;s a real world example.  Wait.  I&#8217;ve just realized I lied to you.  There are <em>three</em> things I want to tell you about.</p>
<p><img src="http://blog.directededge.com/wp-content/uploads/2011/03/spree.png" alt="" title="Spree Logo" width="176" height="82" class="alignright size-full wp-image-719" /><br />
<h3 style="margin-bottom: 1em">We have a Spree plugin.</h3>
<p>Yes, yes, we do.  Hell, we even have a full <em><a href="http://developer.directededge.com/article/Getting_started_with_Spree">tutorial</a></em> on working with Directed Edge and Spree!  It only works with Spree 0.11 at present since we haven&#8217;t ported this baby to Rails 3 yet.  Mostly we needed something real to test this thing on, and Spree seemed like a nice way to test with data models that weren&#8217;t tied to our own assumptions.</p>
<p>You can get at <a href="https://github.com/directededge/acts_as_edgy_spree">the full plugin on Github</a>.</p>
<p>And here are the guts &#8212; the example I mentioned above:</p>
<ol>
<li>An <a href="https://github.com/directededge/acts_as_edgy_spree/blob/master/config/initializers/edgy_spree.rb">initializer</a> to add the line above to the User model</li>
<li>A <a href="https://github.com/directededge/acts_as_edgy_spree/blob/master/app/helpers/edgy_helper.rb">helper</a> to figure out if we&#8217;re doing personalized recommendations, related products or basket recommendations</li>
<li>A <a href="https://github.com/directededge/acts_as_edgy_spree/blob/master/app/views/shared/_edgy_related_table.html.erb">partial template</a> to handle showing the results</li>
</ol>
<p>That&#8217;s pretty lean for all of the glue and display code for adding recommendations (and instant updating) to a full-blown e-commerce thingereedoo.</p>
<h3 style="margin-bottom: 1em">The nerdy bits.</h3>
<p>There are a few neat technical things that are happening behind the scenes to make all of this stuff easy from a user&#8217;s perspective.</p>
<p><strong>SQL Generator</strong></p>
<p>One of them is a fancy custom SQL generator that builds optimal queries for all of this stuff.  Entire Rails models get exported with one query.  The generated SQL can get hella ugly, but it offloads most of the dirty work to the database rather than having to do it all in Ruby code.</p>
<p>The above Spree example (the User to Product mapping) generates this SQL monstrosity:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> users<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AS</span> from_id<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'user'</span> <span style="color: #993333; font-weight: bold;">AS</span> from_type<span style="color: #66cc66;">,</span> variants<span style="color: #66cc66;">.</span>product_id <span style="color: #993333; font-weight: bold;">AS</span> to_id<span style="color: #66cc66;">,</span>
case when variants<span style="color: #66cc66;">.</span>product_id <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> then <span style="color: #ff0000;">'product'</span> end <span style="color: #993333; font-weight: bold;">AS</span> to_type<span style="color: #66cc66;">,</span>
case when variants<span style="color: #66cc66;">.</span>product_id <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> then <span style="color: #ff0000;">'purchase'</span> end <span style="color: #993333; font-weight: bold;">AS</span> link_type <span style="color: #993333; font-weight: bold;">FROM</span> users
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">OUTER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> orders <span style="color: #993333; font-weight: bold;">ON</span> users<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> orders<span style="color: #66cc66;">.</span>user_id
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">OUTER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> line_items <span style="color: #993333; font-weight: bold;">ON</span> orders<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> line_items<span style="color: #66cc66;">.</span>order_id
<span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">OUTER</span> <span style="color: #993333; font-weight: bold;">JOIN</span> variants <span style="color: #993333; font-weight: bold;">ON</span> line_items<span style="color: #66cc66;">.</span>variant_id <span style="color: #66cc66;">=</span> variants<span style="color: #66cc66;">.</span>id
<span style="color: #993333; font-weight: bold;">WHERE</span> users<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">IS</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> from_id;</pre></div></div>

<p>We build up a thing we call a &#8220;connection&#8221; which is a number of &#8220;bridges&#8221;.  A bridge is just a route between two models, including the foreign keys and so a connection is a full path from one model to another one via a chain of foreign keys.  In the simple case this is detected based on the model&#8217;s name and built in ActiveRecord methods for reporting foreign keys, but you can also specify a bridge manually for foreign keys that are created that don&#8217;t match the typical nomenclature.  That isn&#8217;t documented at the moment, but shout if that&#8217;s something that you need.</p>
<p><strong>Triggers</strong></p>
<p>Another neat thing is the automatic installation of model triggers.  So when it&#8217;s building that connection mentioned before, our system knows which models trigger updates which need to be sent over to Directed Edge to keep your data in sync.</p>
<p>So if <tt>acts_as_edgy</tt> is set up to automagically send updates (a config parameter that can be called in the config blog that gets written when you call rake edgy:configure) then as soon as a model changes anywhere along that path, we get the goods.  And this triggers a different code path that leads to our SQL generator just pulling out the stuff that needs to be updated in a single query.</p>
<p><b>Future:  Asynchronous Web-service Calls</b></p>
<p>And since those updates are hitting a remote web service, it&#8217;s ideal if they&#8217;re not blocking execution.  We make liberal use of a class we call Future (conceptually borrowed from <a href="http://doc.qt.nokia.com/4.7-snapshot/qfuture.html">QFuture</a> from Qt) which executes a block of code in a background thread and only forces synchronization when its data is accessed.  Here&#8217;s what it looks like:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Future
  <span style="color:#9966CC; font-weight:bold;">def</span> initialize<span style="color:#006600; font-weight:bold;">&#40;</span>postprocessor = <span style="color:#0000FF; font-weight:bold;">nil</span>, <span style="color:#006600; font-weight:bold;">&amp;</span>finalize<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'EDGY_SYNCHRONOUS'</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@data</span> = postprocessor ? postprocessor.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>finalize.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#41;</span> : finalize.<span style="color:#9900CC;">call</span>
      <span style="color:#0000FF; font-weight:bold;">return</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#0066ff; font-weight:bold;">@postprocessor</span> = postprocessor
    <span style="color:#0066ff; font-weight:bold;">@future</span> = <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      <span style="color:#9966CC; font-weight:bold;">begin</span>
        finalize.<span style="color:#9900CC;">call</span>
      <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> ex
        warn <span style="color:#996600;">&quot;Exception in background thread: #{ex}&quot;</span>
      <span style="color:#9966CC; font-weight:bold;">end</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>method, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
    data.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>method, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>block<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> to_s
    data.<span style="color:#9900CC;">to_s</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> data
    <span style="color:#0066ff; font-weight:bold;">@data</span> <span style="color:#006600; font-weight:bold;">||</span>= <span style="color:#0066ff; font-weight:bold;">@postprocessor</span> ? <span style="color:#0066ff; font-weight:bold;">@postprocessor</span>.<span style="color:#9900CC;">call</span><span style="color:#006600; font-weight:bold;">&#40;</span>@future.<span style="color:#9900CC;">value</span><span style="color:#006600; font-weight:bold;">&#41;</span> : <span style="color:#0066ff; font-weight:bold;">@future</span>.<span style="color:#9900CC;">value</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Since we implement <tt>method_missing</tt> on the Future class to first block and then forward the call on, you can use it just like a normal value, e.g.:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">foo = Future.<span style="color:#9900CC;">new</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#CC0066; font-weight:bold;">sleep</span> <span style="color:#006666;">1</span>; <span style="color:#006666;">42</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> foo <span style="color:#008000; font-style:italic;"># prints 42</span></pre></div></div>

<p>Altogether, while weighing in at a slim 382 lines of code the plugin is fairly light, but it&#8217;s pretty dense code with quite a bit of interesting stuff going on.</p>
<p>It&#8217;s still quite beta, so we expect there will be a handful of kinks to iron out and there are features we&#8217;d still like to add, but hopefully we&#8217;ll be doing that iteratively as you wonderful folks start building things with it and telling us what you need.</p>
<img src="http://feeds.feedburner.com/~r/directededge/~4/m2WtXcg0uPw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2011/03/15/the-easiest-way-to-add-recommendations-to-your-rails-app-announcing-acts_as_edgy/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2011/03/15/the-easiest-way-to-add-recommendations-to-your-rails-app-announcing-acts_as_edgy/</feedburner:origLink></item>
		<item>
		<title>Google Spam Heresy: The AdSense Paradox</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/3kZEU85OISs/</link>
		<comments>http://blog.directededge.com/2011/01/06/google-spam-heresy-the-adsense-paradox/#comments</comments>
		<pubDate>Thu, 06 Jan 2011 08:38:32 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=696</guid>
		<description><![CDATA[There&#8217;s been much ado about the problem of spam and Google of late. Being something of a search weenie, as my eyelids were feeling heavy today I found myself mulling over the problem, &#8220;How would one detect Google spamming?&#8221;
The answer turns out to be surprisingly easy. Who has an incentive to spam Google? People living [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been <a href="http://www.marco.org/2617546197">much</a> <a href="http://www.codinghorror.com/blog/2011/01/trouble-in-the-house-of-google.html">ado</a> about the problem of spam and Google of late. Being something of a search weenie, as my eyelids were feeling heavy today I found myself mulling over the problem, &#8220;How would one detect Google spamming?&#8221;</p>
<p>The answer turns out to be surprisingly easy. Who has an incentive to spam Google? People living from advertising. Who owns the largest online display ad network? Google.</p>
<p>Unlike with email, where there are heuristics at work to guess the intentions of the sender based on the content, Google has that data right in front of them.</p>
<p><strong>So, here&#8217;s the heresy: the spamminess of a web site is inversely proportional to its ad click-through.</strong></p>
<p>Think about it &#8212; in a typical internet search, a navigation path terminating at that page is the best result. If they click on an ad, it probably means you missed serving up the right page in the first place. As a corollary, the pages best optimized to pull you in via a search term and send you back out via a related ad are among the worst results.</p>
<p>So if you&#8217;re Google which value do you optimize for? More ad clicks or better search results? I&#8217;m a big enough Google fan that I believe that they&#8217;d mostly want to optimize for good search results since that&#8217;s what made them the company that they are. But what do you do if there&#8217;s an inverse correlation between the two? Bite the hand that feeds you?</p>
<p>Thinking about things this way in my opinion makes the issue even more interesting, because it seems to hint at something systemic &#8212; i.e. that there there might be something deeper problematic in financing search through display advertising.</p>
<p>Obviously this is a massive oversimplification of the problem of spam, but the paradox intrigued me.</p>
<img src="http://feeds.feedburner.com/~r/directededge/~4/3kZEU85OISs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2011/01/06/google-spam-heresy-the-adsense-paradox/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2011/01/06/google-spam-heresy-the-adsense-paradox/</feedburner:origLink></item>
		<item>
		<title>What’s happening?</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/toaL2S4K2kc/</link>
		<comments>http://blog.directededge.com/2010/11/29/whats-happening/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 05:55:55 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=687</guid>
		<description><![CDATA[
So, the blog has been a bit silent of late, mostly because there&#8217;s been a lot of incremental stuff that&#8217;s been happening. We shout that stuff out over at Twitter and Facebook, but we&#8217;ll pull some of the last couple-o-months together here. But while I still have you attention:
We need Rails beta testers. If you&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-688" title="What's happening?" src="http://blog.directededge.com/wp-content/uploads/2010/11/whats-happening.jpg" alt="" width="400" height="273" /></p>
<p>So, the blog has been a bit silent of late, mostly because there&#8217;s been a lot of incremental stuff that&#8217;s been happening. We shout that stuff out over at <a href="http://twitter.com/directededge">Twitter</a> and <a href="http://www.facebook.com/directededge">Facebook</a>, but we&#8217;ll pull some of the last couple-o-months together here. But while I still have you attention:</p>
<p><strong>We need Rails beta testers. If you&#8217;ve been thinking about adding recommendations to your Rails app, <a href="mailto:info@directededge.com">drop us a line now</a>.</strong></p>
<p>So, with that out of the way, a few of the things that have gone down in Directed Edge-land of late:</p>
<ul>
<li>We&#8217;ve been ramping up the features in our Shopify app based on things that we&#8217;ve been hearing from customers. The Shopify folks covered our new automagic bundling feature <a href="http://blog.shopify.com/2010/11/29/app-roundup">here</a>.</li>
<li>New version of our Ruby gem, 0.2.1 <a href="http://rubygems.org/gems/directed-edge">out</a>, and a couple of features added to our <a href="https://github.com/directededge/directed-edge-bindings/tree/master/Java/">Java bindings</a> so that they approach parity with the other bindings.</li>
<li>Wener Vogels, CTO of Amazon, has been spreading the good news about Directed Edge and we caught up with him when he was presenting about AWS in Berlin.</li>
<li>Yours truly will be doing a big tour out through New York, Austin and San Francisco / Silicon Valley in December and January. Holler if you want to meet and talk about recommendations.</li>
</ul>
<div id="attachment_691" class="wp-caption aligncenter" style="width: 610px"><img class="size-full wp-image-691" title="Werner Vogels - Directed Edge" src="http://blog.directededge.com/wp-content/uploads/2010/11/werner-vogels-directed-edge.jpeg" alt="" width="600" height="337" /><p class="wp-caption-text">Werner Vogels presenting Directed Edge as &quot;one of the building blocks of Cloud Computing&quot;</p></div>
<p>While a lot of the stuff in the last few months has been focused on internal tools and run-of-the-mill growing pains stuff, we&#8217;re getting pretty close to a series of announcements about new stuff coming down the pipe. (For some reason those always seem to come in batches.) We&#8217;re hoping the first of those will be ready in the next week or so.</p>
<img src="http://feeds.feedburner.com/~r/directededge/~4/toaL2S4K2kc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/11/29/whats-happening/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/11/29/whats-happening/</feedburner:origLink></item>
		<item>
		<title>Directed Edge delivering 33% of revenue for The Market Quarter</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/gD3da07kMCM/</link>
		<comments>http://blog.directededge.com/2010/06/16/directed-edge-delivering-33-of-revenue-for-the-market-quarte/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 20:44:10 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=681</guid>
		<description><![CDATA[Jonathan Briggs, who runs The Market Quarter wrote a few months back on getting up and going with our Shopify app for recommendations. He reported back today after analyzing the first few months of data:
What astounded me was how many of my customers (not just visitors) clicked on recommendations. Indeed the ExpressRex referrer is responsible [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-682" title="marketquarter" src="http://blog.directededge.com/wp-content/uploads/2010/06/marketquarter.png" alt="" width="710" height="438" /><a href="http://www.jonathanbriggs.com/">Jonathan Briggs</a>, who runs <a href="http://www.marketquarter.com/">The Market Quarter</a> wrote a few months back on <a href="http://www.jonathanbriggs.com/experimenting-with-shopify-product-recommendation-engine-app,803,AR.html">getting up and going with our Shopify app</a> for recommendations. He reported back today after analyzing the first few months of data:</p>
<blockquote><p>What astounded me was how many of my customers (not just visitors) clicked on recommendations. Indeed the ExpressRex referrer is responsible for a full third (33%) of my revenue in the last quarter and has a 36% conversion rate.</p></blockquote>
<p>You can read the <a href="http://www.jonathanbriggs.com/ecommerce/33-of-revenue-expressrex-recommendation-engine-recommended,814,AR.html">full post</a> in his blog.</p>
<img src="http://feeds.feedburner.com/~r/directededge/~4/gD3da07kMCM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/06/16/directed-edge-delivering-33-of-revenue-for-the-market-quarte/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/06/16/directed-edge-delivering-33-of-revenue-for-the-market-quarte/</feedburner:origLink></item>
		<item>
		<title>Shopify: Help Your Customers Discover Products and Grow Your Average Order Size</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/k1Hl3je1rcM/</link>
		<comments>http://blog.directededge.com/2010/06/07/shopify-help-your-customers-discover-products-and-grow-your-average-order-size/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 22:24:29 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=678</guid>
		<description><![CDATA[From over at the Shopify blog:
Eric Houtkooper of www.PupLife.com helps customers find and discover other products they may want. He has increased his customers’ average order size by recommending products as they browse the store and go through checkout. He suggests you do the same&#8230;
More there.
]]></description>
			<content:encoded><![CDATA[<p>From over at the Shopify blog:</p>
<blockquote><p>Eric Houtkooper of <a href="http://www.puplife.com/">www.PupLife.com</a> helps customers find and discover other products they may want. He has increased his customers’ average order size by recommending products as they browse the store and go through checkout. He suggests you do the same&#8230;</p></blockquote>
<p>More <a href="http://blog.shopify.com/2010/6/7/help-your-customers-discover-products-and-grow-your-average-order-size">there</a>.</p>
<img src="http://feeds.feedburner.com/~r/directededge/~4/k1Hl3je1rcM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/06/07/shopify-help-your-customers-discover-products-and-grow-your-average-order-size/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/06/07/shopify-help-your-customers-discover-products-and-grow-your-average-order-size/</feedburner:origLink></item>
		<item>
		<title>Using taps without running a taps server</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/FeRHIAwK1K8/</link>
		<comments>http://blog.directededge.com/2010/06/05/using-taps-without-running-a-taps-server/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 04:50:18 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=674</guid>
		<description><![CDATA[So, the Ruby world has a nifty thinger for syncing up databases over the interwebs. It&#8217;s called Taps, from the superheroes over at Heroku. It&#8217;s great &#8212; you just run a little Sinatra-based server and then give the database URLs and it handles all of the plumbing.
But, you see, I was none-too-keen on having another [...]]]></description>
			<content:encoded><![CDATA[<p>So, the Ruby world has a nifty thinger for syncing up databases over the interwebs. It&#8217;s called <a href="http://adam.heroku.com/past/2009/2/11/taps_for_easy_database_transfers/">Taps</a>, from the superheroes over at <a href="http://heroku.com/">Heroku</a>. It&#8217;s great &#8212; you just run a little Sinatra-based server and then give the database URLs and it handles all of the plumbing.</p>
<p>But, you see, I was none-too-keen on having another long-running Ruby process, not to mention an open port with production database data lumbering around on it, so I thought I&#8217;d let you guys in on a little hack we produced internally to let you get all of the fun of taps, but without the taps server.</p>
<p>Basically it starts up the taps server on the remote server, tunnels the transfer over SSH, then sends a ctrl-c to the server to kill it&#8217;s done. It&#8217;s pull-only very intentionally &#8212; I want to push from a development database to a production database about like I want a hole in my head.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#008000; font-style:italic;">#!/usr/bin/env ruby</span>
&nbsp;
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_support/secure_random'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'net/ssh'</span>
&nbsp;
SSH_USER = <span style="color:#996600;">'[sshuser]'</span>
SSH_HOST = <span style="color:#996600;">'[dbhost]'</span>
&nbsp;
LOCAL_DB = <span style="color:#996600;">'mysql://[dbuser]:[dbpass]@localhost/[dbname]'</span>
REMOTE_DB = <span style="color:#996600;">'mysql://[dbuser]:[dbpass]@localhost/[dbname]'</span>
&nbsp;
TAPS_USER = <span style="color:#6666ff; font-weight:bold;">ActiveSupport::SecureRandom</span>.<span style="color:#9900CC;">hex</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">16</span><span style="color:#006600; font-weight:bold;">&#41;</span>
TAPS_PASS = <span style="color:#6666ff; font-weight:bold;">ActiveSupport::SecureRandom</span>.<span style="color:#9900CC;">hex</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">16</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
URL = <span style="color:#996600;">&quot;http://#{TAPS_USER}:#{TAPS_PASS}@localhost:5000&quot;</span>
&nbsp;
<span style="color:#6666ff; font-weight:bold;">Net::SSH</span>.<span style="color:#9900CC;">start</span><span style="color:#006600; font-weight:bold;">&#40;</span>SSH_HOST, SSH_USER, <span style="color:#ff3333; font-weight:bold;">:compression</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>ssh<span style="color:#006600; font-weight:bold;">|</span>
  ssh.<span style="color:#9900CC;">forward</span>.<span style="color:#9900CC;">local</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">5000</span>, <span style="color:#996600;">'localhost'</span>, <span style="color:#006666;">5000</span><span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
  ready = <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
  channel = ssh.<span style="color:#9900CC;">open_channel</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span>
    c.<span style="color:#9900CC;">request_pty</span>
    c.<span style="color:#9900CC;">on_data</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>c, data<span style="color:#006600; font-weight:bold;">|</span> ready = <span style="color:#0000FF; font-weight:bold;">true</span> <span style="color:#9966CC; font-weight:bold;">if</span> data =~ <span style="color:#006600; font-weight:bold;">/</span>port=<span style="color:#006666;">5000</span><span style="color:#006600; font-weight:bold;">/</span> <span style="color:#006600; font-weight:bold;">&#125;</span>
    c.<span style="color:#CC0066; font-weight:bold;">exec</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;taps server #{REMOTE_DB} #{TAPS_USER} #{TAPS_PASS}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  finished = <span style="color:#0000FF; font-weight:bold;">false</span>
&nbsp;
  <span style="color:#CC00FF; font-weight:bold;">Thread</span>.<span style="color:#9900CC;">new</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    <span style="color:#CC0066; font-weight:bold;">sleep</span> <span style="color:#006666;">0.1</span> <span style="color:#9966CC; font-weight:bold;">until</span> ready
    <span style="color:#CC0066; font-weight:bold;">system</span> <span style="color:#996600;">&quot;taps pull #{LOCAL_DB} #{URL}&quot;</span>
    finished = <span style="color:#0000FF; font-weight:bold;">true</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  ssh.<span style="color:#CC0066; font-weight:bold;">loop</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0.1</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    channel.<span style="color:#9900CC;">send_data</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#6666ff; font-weight:bold;">Net::SSH::Connection::Term::VINTR</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> finished
    !finished
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Substitute in the right values in the constants up at the top and you&#8217;ve got a nifty way to securely use taps without leaving a server running.</p>
<img src="http://feeds.feedburner.com/~r/directededge/~4/FeRHIAwK1K8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/06/05/using-taps-without-running-a-taps-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/06/05/using-taps-without-running-a-taps-server/</feedburner:origLink></item>
		<item>
		<title>What programming languages do our customers use?</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/s5nLfQ57PqE/</link>
		<comments>http://blog.directededge.com/2010/05/30/what-programming-languages-do-our-customers-use/#comments</comments>
		<pubDate>Sun, 30 May 2010 08:12:28 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=660</guid>
		<description><![CDATA[
No huge shockers, but a few places where it&#8217;s interesting to compare perceptions to reality:

PHP, for better or worse, still dominates web development.
Python&#8217;s much closer to Ruby in the usage we see, despite making less noise.
Scala, despite being the new hotness has very little actual uptake.
Perl is all but out of the game (though still [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-665" title="programming-languages" src="http://blog.directededge.com/wp-content/uploads/2010/05/programming-languages.png" alt="" width="580" height="619" /></p>
<p>No huge shockers, but a few places where it&#8217;s interesting to compare perceptions to reality:</p>
<ul>
<li>PHP, for better or worse, still dominates web development.</li>
<li>Python&#8217;s much closer to Ruby in the usage we see, despite making less noise.</li>
<li>Scala, despite being the new hotness has very little actual uptake.</li>
<li>Perl is all but out of the game (though still more than Scala)</li>
</ul>
<img src="http://feeds.feedburner.com/~r/directededge/~4/s5nLfQ57PqE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/05/30/what-programming-languages-do-our-customers-use/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/05/30/what-programming-languages-do-our-customers-use/</feedburner:origLink></item>
		<item>
		<title>Making ActiveResource 34x faster: QActiveResource</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/9aKEMwS0bhM/</link>
		<comments>http://blog.directededge.com/2010/05/06/making-activeresource-34x-faster-qactiveresource/#comments</comments>
		<pubDate>Thu, 06 May 2010 17:32:10 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[activeresource]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[qt]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=619</guid>
		<description><![CDATA[One of the things that really hurts us when we&#8217;re pulling data from ActiveResource (as we do with Shopify and a couple projects internally) is the slowness of Rails&#8217; ActiveResource. Using the Nokogiri backend helps a lot, but it&#8217;s still painfully slow. It&#8217;s so slow that the bottle neck is actually parsing the data rather [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things that really hurts us when we&#8217;re pulling data from ActiveResource (as we do with Shopify and a couple projects internally) is the slowness of Rails&#8217; ActiveResource. Using the Nokogiri backend helps a lot, but it&#8217;s still painfully slow. It&#8217;s so slow that the bottle neck is actually parsing the data rather than transfering it.</p>
<p>So I set off yesterday to rewrite our importer in C++ using Qt (and libcurl to grab the data). The result is a nice Qt-ified ActiveResource consumer that throws things into a collection of QVariant / hashes / lists.</p>
<p>Once I had that done I wondered, &#8220;What would the performance look like if I wrote a Ruby wrapper for the C++ implementation?&#8221; The answer was, fortunately, &#8220;Great!&#8221; meaning fortunately that the application logic can stay in Ruby with QActiveResource doing the heavy lifting.</p>
<p>It&#8217;s still relatively light on features &#8212; it just supports the find method, but the numbers speak for themselves:</p>
<p><img class="aligncenter size-full wp-image-652" title="ActiveResource Benchmark" src="http://blog.directededge.com/wp-content/uploads/2010/05/active-resource-benchmark.png" alt="" width="698" height="545" /></p>
<p>The first column is the default pure-Ruby ActiveResource implementation, the second is with the same, but using the implemented-in-C Nokogiri backend. The third is just using my C++ backend directly and the fourth is with that bound to Ruby objects.</p>
<h3 style="padding-bottom: 1em;">Methodology:</h3>
<p>The data set is the set of products that we have in our test shop on Shopify. There are 17 of them, for a total of a 36k XML file. Each test iterates over reading that set 100 times. To remove other bottlenecks, I copied the file to a web server on localhost and queried that directly.</p>
<p>So, then that&#8217;s reading 1700 records for each backend over 100 request, with that the average times were:</p>
<ul>
<li><strong>Ruby / ActiveResource / REXML</strong>: 34.60 seconds</li>
<li><strong>Ruby / ActiveResource / Nokogiri</strong>: 12.87 seconds</li>
<li><strong>C++ / QActiveResource</strong>: 0.79 seconds</li>
<li><strong>Ruby / QActiveResource</strong>: 1.01 seconds</li>
</ul>
<p>All of the code is up on GitHub <a href="http://github.com/directededge/QActiveResource">here</a>, including the <a href="http://github.com/directededge/QActiveResource/blob/master/Benchmark/tests.xml">test data</a> and the <a href="http://github.com/directededge/QActiveResource/blob/master/Benchmark/results">raw results</a>.</p>
<h3 style="padding-bottom: 1em;">API in Ruby and C++:</h3>
<p>The Ruby API is very similar to a limited version of ActiveResource and supports things like this, for example:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">resource = <span style="color:#6666ff; font-weight:bold;">QAR::Resource</span>.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'AR_BASE'</span><span style="color:#006600; font-weight:bold;">&#93;</span>, ENV<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">'AR_RESOURCE'</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
resource.<span style="color:#9900CC;">find</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:all</span>, <span style="color:#ff3333; font-weight:bold;">:params</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#ff3333; font-weight:bold;">:page</span> =<span style="color:#006600; font-weight:bold;">&amp;</span>gt; <span style="color:#006666;">1</span> <span style="color:#006600; font-weight:bold;">&#125;</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#006600; font-weight:bold;">|</span>record<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">puts</span> record<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:title</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>The C++ implementation also follows the same basic conventions, e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include </span>
<span style="color: #339900;">#include </span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    QActiveResource<span style="color: #008080;">::</span><span style="color: #007788;">Resource</span> resource<span style="color: #008000;">&#40;</span>QUrl<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">getenv</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;AR_BASE&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>, <span style="color: #0000dd;">getenv</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;AR_RESOURCE&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    foreach<span style="color: #008000;">&#40;</span>QActiveResource<span style="color: #008080;">::</span><span style="color: #007788;">Record</span> record, resource.<span style="color: #007788;">find</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        qDebug<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span><span style="color: #000040;">&amp;</span>lt<span style="color: #008080;">;</span> record<span style="color: #008000;">&#91;</span><span style="color: #FF0000;">&quot;title&quot;</span><span style="color: #008000;">&#93;</span>.<span style="color: #007788;">toString</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>At present this naturally requires Qt and libcurl to build. I may consider building a version which doesn&#8217;t require Qt if there&#8217;s general interest in such (we use Qt in the C++ bits of our code anyway, so there was no extra cost to schlurping it in).</p>
<p>There are more examples in the <a href="http://github.com/directededge/QActiveResource/tree/master/Ruby/">Ruby directory</a> on GitHub. Once it matures a wee bit we&#8217;ll get it packaged up as a Gem.</p>
<h3 style="padding-bottom: 1em;">Edit:</h3>
<p>The API&#8217;s already been going through some changes, now it can be easily used as a mixin, a la:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'active_resource'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'QAR'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">class</span> Product <span style="color:#006600; font-weight:bold;">&amp;</span>lt; <span style="color:#6666ff; font-weight:bold;">ActiveResource::Base</span>
  extend QAR
  <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">site</span> = <span style="color:#996600;">'http://localhost/'</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<img src="http://feeds.feedburner.com/~r/directededge/~4/9aKEMwS0bhM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/05/06/making-activeresource-34x-faster-qactiveresource/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/05/06/making-activeresource-34x-faster-qactiveresource/</feedburner:origLink></item>
		<item>
		<title>The curious case of equidistant boxes, a CSS fail</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/0YHkNTYYOxg/</link>
		<comments>http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/#comments</comments>
		<pubDate>Sat, 01 May 2010 06:32:10 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=551</guid>
		<description><![CDATA[
The above is not an exercise in geometric abstraction. It&#8217;s an attempt to do something seemingly simple, but to the best of my knowledge, impossible in CSS. The challenge is this:
Given a container, fill the container with n items of variable width, with the leftmost item flush with the left border, and the rightmost item [...]]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter size-full wp-image-556" title="layout boxes" src="http://blog.directededge.com/wp-content/uploads/2010/04/layout-boxes.png" alt="" width="522" height="463" /></p>
<p>The above is not an exercise in <a href="http://en.wikipedia.org/wiki/Geometric_abstraction">geometric abstraction</a>. It&#8217;s an attempt to do something seemingly simple, but to the best of my knowledge, impossible in CSS. The challenge is this:</p>
<blockquote style="font-size: 1.1em; color: black"><p>Given a container, fill the container with <em>n</em> items of variable width, with the leftmost item flush with the left border, and the rightmost item flush with the right border, and an equal amount of space between each.</p></blockquote>
<p>Unpossible! Try it.</p>
<p>This isn&#8217;t a contrived example. Being a pixel pedant, when we started in on <a href="http://bit.ly/de-app">our app for Shopify</a>, where images may be any size within a bounding square, distributing them equidistantly seemed The Thing To Do. Here&#8217;s a shot from our test shop with the items properly distributed and the text properly centered under them:</p>
<p><img class="aligncenter size-full wp-image-550" title="Test Shop Recommendations" src="http://blog.directededge.com/wp-content/uploads/2010/04/recommendations-test-shop.png" alt="" width="680" height="258" style="border: 1px solid #ccc"/></p>
<p>So, let&#8217;s step through the options:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.container</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#333</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">520px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">margin-bottom</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1em</span><span style="color: #00AA00;">;</span>
 <span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.container</span> ul <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.container</span> ul li <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">inline</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;div class=&quot;container&quot;&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;img src=&quot;80.png&quot; /&gt;&lt;/li&gt;
    &lt;li&gt;&lt;img src=&quot;100.png&quot; /&gt;&lt;/li&gt;
    &lt;li&gt;&lt;img src=&quot;80.png&quot; /&gt;&lt;/li&gt;
    &lt;li&gt;&lt;img src=&quot;100.png&quot; /&gt;&lt;/li&gt;
    &lt;li&gt;&lt;img src=&quot;60.png&quot; /&gt;&lt;/li&gt;
  &lt;/ul&gt;
&lt;/div&gt;</pre></div></div>

<p><img src="http://blog.directededge.com/wp-content/uploads/2010/04/1.png" alt="" title="1" width="522" height="106" class="aligncenter size-full wp-image-562" /></p>
<p>That gives us the first box, things are messily clumped along the left side of the container. I quickly threw in the towel and went for a table. With a table it was easy to get things distributed evenly, but with ragged extreme borders:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">table<span style="color: #6666ff;">.container</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">522px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">border-spacing</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.container</span> td <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">center</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;table class=&quot;container&quot;&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;img src=&quot;80.png&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;100.png&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;80.png&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;100.png&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;60.png&quot; /&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;</pre></div></div>

<p><img src="http://blog.directededge.com/wp-content/uploads/2010/04/2.png" alt="" title="2" width="522" height="102" class="aligncenter size-full wp-image-563" /></p>
<p>But if we want to make the extremities flush, we&#8217;re stuck with a larger-than-mean gap between the first two and last two boxes:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.flush</span> td<span style="color: #6666ff;">.first</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #000000; font-weight: bold;">left</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.flush</span> td<span style="color: #6666ff;">.last</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #000000; font-weight: bold;">right</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;table class=&quot;container flush&quot;&gt;
  &lt;tr&gt;
    &lt;td class=&quot;first&quot;&gt;&lt;img src=&quot;80.png&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;100.png&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;80.png&quot; /&gt;&lt;/td&gt;
    &lt;td&gt;&lt;img src=&quot;100.png&quot; /&gt;&lt;/td&gt;
    &lt;td class=&quot;last&quot;&gt;&lt;img src=&quot;60.png&quot; /&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;</pre></div></div>

<p><img src="http://blog.directededge.com/wp-content/uploads/2010/04/3.png" alt="" title="3" width="522" height="102" class="aligncenter size-full wp-image-563" /></p>
<p>It turns out that the only way to do this seemingly simple task is to compute the margins ourselves and set them via Javascript. Here we take a table just like our second one, but with a &#8220;adjust&#8221; ID so that we can find it easily:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> adjust<span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> table <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;adjust&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> row <span style="color: #339933;">=</span> table.<span style="color: #660066;">firstElementChild</span>.<span style="color: #660066;">firstElementChild</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> cells <span style="color: #339933;">=</span> row.<span style="color: #660066;">children</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> totalImagesWidth <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cells.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> image <span style="color: #339933;">=</span> cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">firstElementChild</span><span style="color: #339933;">;</span>
        totalImagesWidth <span style="color: #339933;">+=</span> image.<span style="color: #660066;">offsetWidth</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> extra <span style="color: #339933;">=</span> row.<span style="color: #660066;">offsetWidth</span> <span style="color: #339933;">-</span> totalImagesWidth<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cells.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> image <span style="color: #339933;">=</span> cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">firstElementChild</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> padding <span style="color: #339933;">=</span> extra <span style="color: #339933;">/</span> <span style="color: #009900;">&#40;</span>cells.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> buffer <span style="color: #339933;">=</span> Math.<span style="color: #660066;">floor</span><span style="color: #009900;">&#40;</span>padding <span style="color: #339933;">*</span> i<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> Math.<span style="color: #660066;">floor</span><span style="color: #009900;">&#40;</span>padding <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span> <span style="color: #339933;">||</span> i <span style="color: #339933;">==</span> cells.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span> <span style="color: #339933;">&amp;&amp;</span> cells.<span style="color: #660066;">length</span> <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">textAlign</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">&quot;left&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;right&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>image.<span style="color: #660066;">offsetWidth</span> <span style="color: #339933;">+</span> Math.<span style="color: #660066;">floor</span><span style="color: #009900;">&#40;</span>buffer <span style="color: #339933;">/</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;px&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066; font-weight: bold;">else</span>
        <span style="color: #009900;">&#123;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">textAlign</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;center&quot;</span><span style="color: #339933;">;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>image.<span style="color: #660066;">offsetWidth</span> <span style="color: #339933;">+</span> buffer<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;px&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>window.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    window.<span style="color: #660066;">addEventListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;load&quot;</span><span style="color: #339933;">,</span> adjust<span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000066; font-weight: bold;">else</span> <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>window.<span style="color: #660066;">attachEvent</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    window.<span style="color: #660066;">attachEvent</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;onload&quot;</span><span style="color: #339933;">,</span> adjust<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><img src="http://blog.directededge.com/wp-content/uploads/2010/04/4.png" alt="" title="2" width="522" height="102" class="aligncenter size-full wp-image-563" /></p>
<p>Now things get adjusted just as we&#8217;d want them. Let&#8217;s walk through the steps:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #003366; font-weight: bold;">var</span> table <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementById</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;adjust&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> row <span style="color: #339933;">=</span> table.<span style="color: #660066;">firstElementChild</span>.<span style="color: #660066;">firstElementChild</span><span style="color: #339933;">;</span>
    <span style="color: #003366; font-weight: bold;">var</span> cells <span style="color: #339933;">=</span> row.<span style="color: #660066;">children</span><span style="color: #339933;">;</span></pre></div></div>

<p>Here we just get a handle to our building blocks, the table, row and cells.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #003366; font-weight: bold;">var</span> totalImagesWidth <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cells.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> image <span style="color: #339933;">=</span> cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">firstElementChild</span><span style="color: #339933;">;</span>
        totalImagesWidth <span style="color: #339933;">+=</span> image.<span style="color: #660066;">offsetWidth</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now we compute the total width of all of the images used in the table. We&#8217;ll use that to figure out how much left-over space we have to distribute:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #003366; font-weight: bold;">var</span> extra <span style="color: #339933;">=</span> row.<span style="color: #660066;">offsetWidth</span> <span style="color: #339933;">-</span> totalImagesWidth<span style="color: #339933;">;</span></pre></div></div>

<p>From there we go in to assign this to each cell:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #000066; font-weight: bold;">for</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> cells.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> image <span style="color: #339933;">=</span> cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">firstElementChild</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> padding <span style="color: #339933;">=</span> extra <span style="color: #339933;">/</span> <span style="color: #009900;">&#40;</span>cells.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> buffer <span style="color: #339933;">=</span> Math.<span style="color: #660066;">floor</span><span style="color: #009900;">&#40;</span>padding <span style="color: #339933;">*</span> i<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> Math.<span style="color: #660066;">floor</span><span style="color: #009900;">&#40;</span>padding <span style="color: #339933;">*</span> <span style="color: #009900;">&#40;</span>i <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>The padding is simply the extra space divided by the number of gaps that we have, but we compute the buffer for each iteration so that all of the left over pixels don&#8217;t accumulate at the end &#8212; i.e. if we had 7 items and the space between each should be in theory 10.333&#8230; pixels, that would leave us with 3 extra pixels stuck into the last gap. By doing the floor of each iteration and subtracting the previous value, we end up with appropriately distributed spare pixels.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">        <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span> <span style="color: #339933;">||</span> i <span style="color: #339933;">==</span> cells.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span> <span style="color: #339933;">&amp;&amp;</span> cells.<span style="color: #660066;">length</span> <span style="color: #339933;">&gt;=</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">textAlign</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">&quot;left&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;right&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>image.<span style="color: #660066;">offsetWidth</span> <span style="color: #339933;">+</span> Math.<span style="color: #660066;">floor</span><span style="color: #009900;">&#40;</span>buffer <span style="color: #339933;">/</span> <span style="color: #CC0000;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;px&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066; font-weight: bold;">else</span>
        <span style="color: #009900;">&#123;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">textAlign</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;center&quot;</span><span style="color: #339933;">;</span>
            cells<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">style</span>.<span style="color: #660066;">width</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>image.<span style="color: #660066;">offsetWidth</span> <span style="color: #339933;">+</span> buffer<span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;px&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>The second half of the loop just sets the cells at the extremities to be left / right aligned and gives each cell half of the buffer space for each of their internal gaps. The ones on the edges only need half of the buffer allocation since they don&#8217;t have a buffer on their outside edges.</p>
<p>The sad thing is this is actually a much simplified version of the real code. The real code also accounts for:</p>
<ul>
<li>Centering text under these images (Sounds easy right? No. You have to compute the margins manually also.)</li>
<li>Dealing with stylesheets where images have margins, padding and borders and still making the right thing happen.</li>
<li>Only one item being shown.</li>
<li>Minimum sizes for images, centering them if they&#8217;re smaller (you don&#8217;t want to try to center text below a 5 pixel wide image that&#8217;s right aligned)</li>
</ul>
<p>I can get into the mechanics of those in another post if necessary and have been considering stripping the real implementation out of our widget and throwing it up on Github where it can take a nice, clean JSON structure and turn it into a table of images, text, prices and links. Give a holler in the comments if you&#8217;d find such useful.</p>
<p>And with that, I&#8217;ll leave you with a gallery of what-this-looks-like-in-real-life shops, from the annals of our Shopify customers.</p>

<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-1/' title='shop-1'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-1-150x150.png" class="attachment-thumbnail" alt="" title="shop-1" /></a>
<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-2/' title='shop-2'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-2-150x150.png" class="attachment-thumbnail" alt="" title="shop-2" /></a>
<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-3/' title='shop-3'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-3-150x150.png" class="attachment-thumbnail" alt="" title="shop-3" /></a>
<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-4/' title='shop-4'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-4-150x150.png" class="attachment-thumbnail" alt="" title="shop-4" /></a>
<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-5/' title='shop-5'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-5-150x150.png" class="attachment-thumbnail" alt="" title="shop-5" /></a>
<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-6/' title='shop-6'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-6-150x150.png" class="attachment-thumbnail" alt="" title="shop-6" /></a>
<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-7/' title='shop-7'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-7-150x150.png" class="attachment-thumbnail" alt="" title="shop-7" /></a>
<a href='http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/shop-8/' title='shop-8'><img width="150" height="150" src="http://blog.directededge.com/wp-content/uploads/2010/04/shop-8-150x150.png" class="attachment-thumbnail" alt="" title="shop-8" /></a>

<img src="http://feeds.feedburner.com/~r/directededge/~4/0YHkNTYYOxg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/04/30/the-curious-case-of-equidistant-boxes-a-css-fail/</feedburner:origLink></item>
		<item>
		<title>For the love of POSIX: A more useful way to not segfault from null pointers</title>
		<link>http://feedproxy.google.com/~r/directededge/~3/NrbR3DPvnQU/</link>
		<comments>http://blog.directededge.com/2010/03/31/for-the-love-of-posix-a-more-useful-way-to-not-segfault-from-null-pointers/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 20:05:07 +0000</pubDate>
		<dc:creator>Scott Wheeler</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.directededge.com/?p=537</guid>
		<description><![CDATA[There&#8217;s a post making the rounds on Hacker News about actually mapping the address 0 to make it possible to not crash when dereferencing a null pointer.
The thing is, POSIX provides a more useful mechanism for recovering from null pointer dereferences using signal handlers.
See, signals in UNIX can be caught and you can do things [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s a <a href="http://blog.ksplice.com/2010/03/null-pointers-part-i/">post</a> making the rounds on <a href="http://news.ycombinator.com/">Hacker News</a> about actually mapping the address 0 to make it possible to not crash when dereferencing a null pointer.</p>
<p>The thing is, <a href="http://en.wikipedia.org/wiki/POSIX">POSIX</a> provides a more useful mechanism for recovering from null pointer dereferences using signal handlers.</p>
<p>See, signals in UNIX can be caught and you can do things with them. Let&#8217;s say that we&#8217;ve got an event-driven application and we want to move on to the next event if the handler for one event caused a segfault. We can do that by catching the SIGSEGV and SIGBUS signals and returning to our event loop to process the next event.</p>
<p>Let&#8217;s look at some code:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include &lt;stdio.h&gt;</span>
<span style="color: #339933;">#include &lt;signal.h&gt;</span>
<span style="color: #339933;">#include &lt;setjmp.h&gt;</span>
<span style="color: #339933;">#include &lt;string.h&gt;</span>
&nbsp;
<span style="color: #993333;">static</span> jmp_buf event_loop_jump<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">void</span> process_event<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> event_id<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>event_id <span style="color: #339933;">%</span> <span style="color: #0000dd;">10</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #808080; font-style: italic;">/* Boom. */</span>
&nbsp;
        <span style="color: #993333;">int</span> <span style="color: #339933;">*</span>i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
        <span style="color: #339933;">++*</span>i<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Processed Event: %i<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> event_id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">void</span> handler<span style="color: #009900;">&#40;</span><span style="color: #993333;">int</span> signum<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Caught %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> strsignal<span style="color: #009900;">&#40;</span>signum<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    longjmp<span style="color: #009900;">&#40;</span>event_loop_jump<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">static</span> <span style="color: #993333;">void</span> run_event_loop<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">int</span> event_id <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">for</span><span style="color: #009900;">&#40;</span>event_id <span style="color: #339933;">=</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span> event_id <span style="color: #339933;">&lt;=</span> <span style="color: #0000dd;">20</span><span style="color: #339933;">;</span> event_id<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>setjmp<span style="color: #009900;">&#40;</span>event_loop_jump<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Couldn't process event: %i<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> event_id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #b1b100;">else</span>
        <span style="color: #009900;">&#123;</span>
            process_event<span style="color: #009900;">&#40;</span>event_id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">int</span> main<span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    signal<span style="color: #009900;">&#40;</span>SIGSEGV<span style="color: #339933;">,</span> handler<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    signal<span style="color: #009900;">&#40;</span>SIGBUS<span style="color: #339933;">,</span> handler<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    run_event_loop<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And that give us:</p>
<pre>Processed Event: 1
Processed Event: 2
Processed Event: 3
Processed Event: 4
Processed Event: 5
Processed Event: 6
Processed Event: 7
Processed Event: 8
Processed Event: 9
Caught Bus error
Couldn't process event: 10
Processed Event: 11
Processed Event: 12
Processed Event: 13
Processed Event: 14
Processed Event: 15
Processed Event: 16
Processed Event: 17
Processed Event: 18
Processed Event: 19
Caught Bus error
Couldn't process event: 20</pre>
<h4>What&#8217;s happening, Peter</h4>
<p>So, let&#8217;s break that down a bit &#8212; we&#8217;ve created a function called <tt>handler</tt> that matches the signature required for signal handlers.  <tt>man signal</tt> knows more, or check out the <a href="http://www.gnu.org/s/libc/manual/html_node/Signal-Handling.html">GNU documentation</a>. In <tt>main</tt> we specify that we want to use that function to handle SIGSEGV and SIGBUS, the typical things you&#8217;ll be looking at when dereferencing null pointers.  From there we call <tt>run_event_loop</tt>, whose function should be obvious.</p>
<h4>Jump Around</h4>
<p><tt>run_event_loop</tt> just loops through 20 fake events, but the interesting bit is setjmp. That saves our stack (the variables in use, basically). During normal execution it just returns 0, so we fall through to our <tt> process_event</tt> call below, which just pretends to handle and event and prints out a message.</p>
<p>We&#8217;ve wired our event handler to blow up once every 10 times. When it does execution is suspended and we cut over to our signal handler. Our signal handler, in turn, prints a little message and then breaks out of the signal handler and back into the normal event handling flow with a <tt>longjmp</tt> call that corresponds to our <tt>setjmp</tt> from before.</p>
<p>So once we call that we&#8217;re back at our line with the <tt>setjmp</tt> call, only this time it returns the value that we passed to <tt>longjmp</tt> &#8212; 1, and since that evaluates to true, we end up printing a message saying that we weren&#8217;t able to process the event.</p>
<h4>In Context</h4>
<p>On the whole this seems far more useful than mapping address zero. However, There Be Dragons in these waters, and it no doubt opens up a can of worms in terms of what&#8217;s done with static variables in the functions you&#8217;re breaking out of and if they&#8217;re left in a secure state &#8212; in other words, this does open up another potential security vector.</p>
<p>I&#8217;ll also note that we don&#8217;t actually do this in any of our stuff at Directed Edge, going for the less exciting, but more predictable process watchers to handle restarts when our C++ engine falls foul of memory protection (which, blessedly, is a rare occurrence).</p>
<h4>Update:</h4>
<p>For posterity, and based on some of the comments here and on Hacker News, it seems apt to note that this method isn&#8217;t being seriously suggested for production code; the idea behind the post was more as a novelty and a brief exploration in signal handling.</p>
<img src="http://feeds.feedburner.com/~r/directededge/~4/NrbR3DPvnQU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.directededge.com/2010/03/31/for-the-love-of-posix-a-more-useful-way-to-not-segfault-from-null-pointers/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://blog.directededge.com/2010/03/31/for-the-love-of-posix-a-more-useful-way-to-not-segfault-from-null-pointers/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 0.580 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-30 16:21:19 --><!-- Compression = gzip -->

