<?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>zach's blog</title>
	
	<link>http://zmsmith.com</link>
	<description>Just an awesome WordPress weblog</description>
	<lastBuildDate>Thu, 10 Nov 2011 17:06:49 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>

   <image>
    <title>zach's blog</title>
    <url>http://0.gravatar.com/avatar/4da367970053ff57f1ed464e18358249?s=48&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536</url>
    <link>http://zmsmith.com</link>
   </image>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/zmsmith/zucu" /><feedburner:info uri="zmsmith/zucu" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>How Yipit Deploys Django</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/ek2pbuQBL5Y/</link>
		<comments>http://zmsmith.com/2011/11/how-yipit-deploys-django/#comments</comments>
		<pubDate>Thu, 10 Nov 2011 16:57:45 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=47</guid>
		<description><![CDATA[This post is republished from the Yipit Django Blog If you&#8217;re managing your own servers, and you don&#8217;t use a tool like Chef, you&#8217;re crazy. It&#8217;s just that simple. We&#8217;ve been using Chef here at Yipit for about 6 months, and when I think about provisioning a new server with our old load book, I cringe. [...]]]></description>
				<content:encoded><![CDATA[<p><em>This post is republished from the <a href="http://tech.yipit.com">Yipit Django Blog</a></em></p>
<p><strong>If you&#8217;re managing your own servers, and you don&#8217;t use a tool like Chef, you&#8217;re crazy.</strong> It&#8217;s just that simple.</p>
<p>We&#8217;ve been using Chef here at Yipit for about 6 months, and when I think about provisioning a new server with our old load book, I cringe.</p>
<p>There were some pretty high upfront costs to learning Chef, especially since no one here had any real Ruby experience (Chef is written in Ruby), but the time we invested into getting set up with Chef has been 100% worth it.</p>
<p>I&#8217;m hoping this post will help people get up and running with Django and Chef as quickly as possible. Opscode has <a href="https://github.com/opscode/django-quick-start">their own django-quick-start repository,</a> but I think it&#8217;s too complex if you&#8217;re not familiar with Chef. This tutorial will cover:</p>
<ul>
<li>Getting set up with Opscode, a hosted chef-server</li>
<li>Installing Ruby, Chef, and some knife plugins</li>
<li>Setting up your chef-repo and installing a Django/github quickstart cookbook</li>
<li>Using a Python script to deploy to ec2</li>
</ul>
<p>If you don&#8217;t understand what any of those things mean, <a href="http://wiki.opscode.com/display/chef/Home" target="_blank">Opscode maintains a pretty good wiki</a>.</p>
<h4>Before We Start</h4>
<p>This tutorial makes the following assumptions about your systems:</p>
<ul>
<li>Locally, you run a Mac.</li>
<li>Remotely, you want to use Ubuntu on AWS</li>
<li>Your AWS account has security groups named &#8220;web&#8221; and &#8220;linux&#8221; that allow access on ports 22 and 80</li>
<li>The private key for the AWS ssh key you define in add_server.py (we&#8217;ll get to that later) is located in ~/.ssh/ on your local machine</li>
<li>Your Django app contains a pip requirements file at conf/external_apps.txt (and that file contains gunicorn)</li>
<li>Your Django app contains a gunicorn configuration file at conf/gunicorn/gunicorn.conf</li>
<li>You&#8217;re interested in learning about Chef and managing your own servers. Seriously. If you&#8217;re just looking for a simple deployment solution, use Heroku. If you want to manage and automate your own infrastructure, use Chef</li>
</ul>
<p>If you&#8217;re not familiar with AWS security groups and key pairs, <a href="http://www.nczonline.net/blog/2011/07/21/quick-and-dirty-spinning-up-a-new-ec2-web-server-in-five-minutes/">this tutorial</a> should help. I&#8217;ve also provided <a href="https://github.com/zmsmith/djangohelloworld">a simple &#8220;Hello World&#8221; Django application</a> that I use as an example.</p>
<h4>Get the Gems</h4>
<p>I like using homebrew for everything, so even though your mac comes with ruby&#8230;</p>
<pre>brew install ruby
gem install -n /usr/local/bin/ chef
gem install knife-ec2
gem install knife-github-cookbooks</pre>
<h4>Set up a chef-repo</h4>
<p>We&#8217;re going to be adding some python scripts to help us manage our servers, so I like to set up my chef-repo in a virtualenv. From wherever you keep your virtualenvs&#8230;</p>
<pre>virtualenv chef-env
cd chef-env
git clone https://github.com/opscode/chef-repo.git
cd chef-repo</pre>
<p>Now you have the barebones Chef repository distributed by opscode.</p>
<h4>Get started with opscode and your knife.rb file</h4>
<p>Next you&#8217;ll want to get setup with Opscode to manage your chef server. You can create an account at <a href="http://opscode.com">opscode.com</a>.</p>
<p>After you&#8217;ve signed up, download your private key. You can download it by clicking on your username on the top right of the console, and then following the link to &#8220;get private key&#8221;.</p>
<p>Next you&#8217;ll need to set up an organization and download the organization validator key. You&#8217;ll also want to to download the knife.rb file that opscode will generate for you.</p>
<p>Lastly, throw it all in a .chef directory in your chef-reop.</p>
<p>You should also append this code to your knife.rb:<br />
<script type="text/javascript" src="https://gist.github.com/1346825.js?file=knife.rb"></script><br />
This changes the amount of time knife will wait for ec2 to spawn a new server for you. I&#8217;ve found that sometimes the default wait time isn&#8217;t long enough for ebs-backed instances.</p>
<h4>Setting up your project</h4>
<p>Next we need to set up chef to actually do something. Let&#8217;s start by installing a <a href="https://github.com/Yipit/djangoquickstart-cookbook">Django quick start cookbook</a> I put together. This cookbook will install a django application behind nginx and gunicorn, which will be managed by supervisor. You should read through the commented code for an explanation of how it works.</p>
<pre>knife cookbook github install Yipit/djangoquickstart-cookbook</pre>
<p>This cookbook has a dependency on the python cookbook, so we&#8217;ll want to install that too.</p>
<pre>knife cookbook site install python</pre>
<p>Note that &#8220;site&#8221; version of the install command will handle dependencies automatically, while the github command will not. When you use &#8220;site&#8221;, however, you&#8217;re limited to cookbooks distributed by opscode.</p>
<p>The next thing we&#8217;ll want to do is define a role. In your chef-repo, put something like this in roles/web.rb:</p>
<p><script type="text/javascript" src="https://gist.github.com/1346825.js?file=web.rb"></script></p>
<h4>Get Some Python In there</h4>
<p>Knife has a pretty good plugin system, but it requires you to write Ruby. Writing Ruby is worth it in the cookbooks because it&#8217;s the only option, but for helper scripts, I just use python. Aside from being more comfortable with the language, familiarity with the libraries is a huge plus. Here&#8217;s a script similar to the one we use to add servers at Yipit:</p>
<p><script type="text/javascript" src="https://gist.github.com/1346825.js?file=add_server.py"></script></p>
<p>Fill in your AWS keys and put this code into a file called add_server.py. This script requires boto and pychef, so from within your virtualenv:</p>
<pre>pip install boto pychef</pre>
<p>I keep this file in right in the chef repo.</p>
<p>The last thing we need to do before we get started is upload our roles and cookbooks to the chef server.</p>
<pre>knife cookbook upload --all
knife role from file roles/web.rb</pre>
<p>Now, if you run the add_server.py script, you should be able to bootstrap your own web server running your django application through gunicorn behind nginx. The add server script does restart the machine, so you may need to wait a minute or two.</p>
<p>Hopefully you can visit your new web server and see your application.</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/ek2pbuQBL5Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2011/11/how-yipit-deploys-django/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2011/11/how-yipit-deploys-django/</feedburner:origLink></item>
		<item>
		<title>New and Improved Two Column Layout</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/Lkd_8DbkEtY/</link>
		<comments>http://zmsmith.com/2010/12/new-and-improved-two-column-layout/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 16:09:18 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[UI]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=36</guid>
		<description><![CDATA[Two column layouts are all the rage on the internet right now. Twitter did it. Hashable did it.  Even facebook thought about doing it. It&#8217;s a great way to consume content, but most current implementations have some serious limitations: There is a clear and predefined relationship between the two columns - One columns is the parent, and [...]]]></description>
				<content:encoded><![CDATA[<p>Two column layouts are all the rage on the internet right now. <a href="http://twitter.com" target="_blank">Twitter</a> did it. <a href="http://hashable.com">Hashable</a> did it.  Even <a href="http://techcrunch.com/2010/04/21/facebook-design/" target="_blank">facebook thought about doing it</a>. It&#8217;s a great way to consume content, but most current implementations have some serious limitations:</p>
<ol>
<li><strong>There is a clear and predefined relationship between the two columns </strong>- One columns is the parent, and the other is the child. This relationship limits the amount of content available in the lesser of the two panels. Most implementations limit the height of the child column to the height of the browser window and use an overflow for additional content.</li>
<li><strong>Navigation is inconsistant</strong> &#8211; The page will react differently depending on which browser element is in focus. Because the child column usually uses overflow for extra content, scrolling up or down does not guarantee getting any additional content located in that direction in both columns.</li>
</ol>
<p>I&#8217;ve built a proof of concept demo of a two column layout with no hierarchy between the columns.</p>
<p><strong>You can check it out <a href="http://zmsmith.github.com/two-column/">here</a>. </strong></p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/Lkd_8DbkEtY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/12/new-and-improved-two-column-layout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/12/new-and-improved-two-column-layout/</feedburner:origLink></item>
		<item>
		<title>Easy Ajax Forms with Fancybox</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/Ld6YVOwCoSA/</link>
		<comments>http://zmsmith.com/2010/09/easy-ajax-forms-with-fancybox/#comments</comments>
		<pubDate>Thu, 16 Sep 2010 15:41:21 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ajax]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[fancybox]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=30</guid>
		<description><![CDATA[Note: The fancybox jQuery plugin can be found here. Last week we rolled out a new design for yipit, which I&#8217;m really excited about. It looks awesome. Sam Brown did an amazing job. In a few different places we decided to use modal forms that would submit via Ajax. I think technique provides great UX, [...]]]></description>
				<content:encoded><![CDATA[<p><em>Note: The fancybox jQuery plugin can be found </em><a href="http://fancybox.net" target="_blank"><em>here</em></a><em>.</em></p>
<p>Last week we rolled out a new design for <a href="http://yipit.com" target="_blank">yipit</a>, which I&#8217;m really excited about. It looks awesome. <a href="http://massiveblue.com" target="_blank">Sam Brown</a> did an amazing job. In a few different places we decided to use modal forms that would submit via Ajax. I think technique provides great UX, but  if the forms require server-side validation,  displaying the appropriate HTML can be a bit of a headache.</p>
<p><span id="more-30"></span></p>
<h3>First Attempts</h3>
<p>The initial strategy was to have the server respond with JSON containing any errors and then show them appropriately to the user. This is a totally valid approach, but every form is different, which meant writing form specific code both server and client-side. I also find injecting HTML into an existing page to be pretty tedious, so having to write JavaScript to do exactly that for every form was not a solution I was happy with.</p>
<p>In addition, if the form did validate, it was unclear where the success HTML should live. We could have the server return it, but this made for an awkward transaction since we also needed to pass back whether or not the form had validated. The HTML could be part of the JavaScript, but this would break MVC and not allow us to leverage Django&#8217;s templating system. Either way, the django views we were using looked very different than the views for standard pages, and having to switch gears slows down development.</p>
<p><strong>I wanted to find a solution that met these criteria:</strong></p>
<ol>
<li>Minimal custom JavaScript</li>
<li>Familiar server-side code</li>
<li>Adhere to MVC</li>
</ol>
<h3>Change of Plans</h3>
<p>Fancybox makes it really easy to draw an overlay with HTML returned via Ajax. Fancybox also only allows one overlay at a time. This is a limitation, but it does make it really easy to replace one overlay with another. Leveraging both these behaviors, we realized we could have every call to the server result in a new fancybox that would replace one currently being displayed. This way we cold write traditional Django views to handle the Ajax request and take full advantage of the Django templating system, including the display of form errors.</p>
<p>The first iteration of this involved every fancybox containing the javascript necessary to launch the next fancybox. This worked really well on Firefox, Safari, and Chrome, but IE was no so cooperative. In IE, we could show a second fancybox, if that fancybox contained JavaScript, the browser would crash. Also, it didn&#8217;t satisfy the requirement of not having to write custom JavaScript for every form. Using a little client-side recursion (who knew there were practical applications?) and a couple of guidelines, we were able to launch new fancyboxes without new scripts.</p>
<h3>Guidelines</h3>
<ol>
<li>Every &lt;a&gt; tag that launches a fancybox form must share common class.</li>
<li>Every fancybox that contains a form must share a common class.</li>
<li>Every form must have an explicit action containing the destination URL for the Ajax request.</li>
<li>Every response contains the html for a new fancybox (and must adhere to guidelines 2 and 3 to allow for chaining)</li>
</ol>
<h3>Sample Code</h3>
<p>Django View:<br />
<script src="http://gist.github.com/579149.js?file=AjaxFancyBox.py"></script> Django Template: <script src="http://gist.github.com/579149.js?file=AjaxFancyBox.html"> </script><br />
Javascript (assumes jQuery 1.4 and fancybox 1.3.1):<br />
<script src="http://gist.github.com/579149.js?file=AjaxFancyBox.js"></script></p>
<p>Any server-side implementation will work if you adhere to the guidelines. The real meat is in the JavaScript .</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/Ld6YVOwCoSA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/09/easy-ajax-forms-with-fancybox/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/09/easy-ajax-forms-with-fancybox/</feedburner:origLink></item>
		<item>
		<title>Optimized Django M2M “in” Queries</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/3wt6Varq6fA/</link>
		<comments>http://zmsmith.com/2010/08/optimized-django-m2m-in-queries/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 21:20:47 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[ManyToManyField]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=26</guid>
		<description><![CDATA[ManyToManyFields in Django have a big inefficiency when running a query to get objects that share a ManyToMany relation with another object. Consider these three models: We can run this query to see what Authors are available in a particular bookstore: What&#8217;s The Problem? That QuerySet produces the following SQL: Look at the subquery. There&#8217;s [...]]]></description>
				<content:encoded><![CDATA[<p><code>ManyToManyField</code>s in Django have a big inefficiency when running a query to get objects that share a <code>ManyToMany</code> relation with another object. Consider these three models:<br />
<script src="http://gist.github.com/540375.js?file=gistfile1.py"></script></p>
<p><span id="more-26"></span></p>
<p>We can run this query to see what Authors are available in a particular bookstore: <script src="http://gist.github.com/540376.js?file=gistfile1.py"></script></p>
<h3>What&#8217;s The Problem?</h3>
<p>That QuerySet produces the following SQL:</p>
<p><script src="http://gist.github.com/540455.js?file=gistfile1.sql"></script> Look at the subquery. There&#8217;s an unnecessary join against the table <code>book</code>. The information returned by that subquery is the <code>id</code>s of books associated with a particular bookstore. This information is available directly from M2M table <code>bookstore_book</code>.</p>
<h3>So What Can We Do?</h3>
<p>We&#8217;re really looking at two problems here:</p>
<ol>
<li>Django doesn&#8217;t realize we only need the <code>id</code>s of the books and can obtain them without accessing the <code>book</code> table. (I&#8217;m not going to dive into this one)</li>
<li>Even if the developer realizes, there is no easy way to extract that information using the ORM.</li>
</ol>
<p>This second issue can be solved by subclassing two Django classes and creating an attribute that collects the data we need in a more efficicent way. Here&#8217;s the code I came up with:<br />
<script src="http://gist.github.com/540384.js?file=gistfile1.py"></script><br />
This <code>NewManyToManyField</code> will give the <code>ManyRelatedManager</code> accessed through the attribute <code>books</code> the attribute <code>id_list</code>, which is a method that returns a <code>QuerySet</code> containing the list of  the <code>id</code>s of the target model that have a connection to the current object.  In this case it returns a list of book ids in the B&amp;N book store. If we declare our models using the <code>NewManyToManyField</code> we can take advantage of this new attribute:</p>
<p><script src="http://gist.github.com/540459.js?file=gistfile1.py"></script> Now we can use the following code:  <script src="http://gist.github.com/540460.js?file=gistfile1.py"></script></p>
<p>Which produces this SQL<br />
<script src="http://gist.github.com/540391.js?file=gistfile1.py"></script><br />
Check out the subquery. We&#8217;ve saved a <code>JOIN</code> against the book table. This may seem like an insignificant optimization, but if there are a lot of people on your site  visting pages that require this type of query, losing that <code>JOIN</code> can really speed things up.</p>
<h3>How does it work?</h3>
<p>During class creation of a model, a method called <code>contribute_to_class</code> is called for every database field. This method gives the class an attribute that is the name of the field and gives an instance access to the value of that field. For <code>ManyToManyField</code>s this attribute is a <code>ReverseManyRelatedObjectsDescriptor</code> object, which returns an instance of <code>ManyRelatedManager</code> for accessing the related rows of the related table. The code subclasses <code>ReverseManyRelatedObjectsDescriptor</code>, catches the <code>ManyToManyRelated</code> manager on the way out, and then assigns it the attribute <code>id_list</code>, which is method that returns a <code>QuerySet</code> that only accesses the M2M table and contains the <code>id</code>s of the related objects.</p>
<p>There is still a lot of room for improvement, but this gets the job done. For starters, the <code>ManyRelatedManager</code> gets created behind the scenes here and is then overwritten. Also, <code>id_list</code> isn&#8217;t a bound method of the <code>ManyRelatedManager</code>. I know both this issues could be solved by jumping down one more level and also subclassing <code>ManyRelatedManager</code>, but I think this is good enough for now.</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/3wt6Varq6fA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/08/optimized-django-m2m-in-queries/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/08/optimized-django-m2m-in-queries/</feedburner:origLink></item>
		<item>
		<title>Does Social Media Make Us Stupider?</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/ycf-zOW45AA/</link>
		<comments>http://zmsmith.com/2010/08/does-social-media-make-us-stupider/#comments</comments>
		<pubDate>Thu, 12 Aug 2010 14:26:10 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Random Thoughts]]></category>
		<category><![CDATA[Intelligence]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=24</guid>
		<description><![CDATA[There is a lot of debate as to whether the internet makes us smarter or dumber. I&#8217;ve always argued that the internet increases our intelligence. It certainly makes us more knowledgeable, and while there is a certain level of intelligence necessary to grasp knowledge, it is our knowledge-base that allows us to act intelligently. It&#8217;s a classic Chicken-Egg Situation, [...]]]></description>
				<content:encoded><![CDATA[<p>There is a lot of debate as to whether the internet makes us <a href="http://online.wsj.com/article/SB10001424052748704025304575284973472694334.html" target="_blank">smarter</a> or <a href="http://online.wsj.com/article/SB10001424052748704025304575284981644790098.html">dumber</a>. I&#8217;ve always argued that the internet increases our intelligence. It certainly makes us more knowledgeable, and while there is a certain level of intelligence necessary to grasp knowledge, it is our knowledge-base that allows us to act intelligently. It&#8217;s a classic <a href="http://www.youtube.com/watch?v=rpKqMC2YfwI" target="_blank">Chicken-Egg Situation</a>, but if I had to choose, I&#8217;d say knowledge is the more significant propellent of human achievement. The real difficulty of this debate lies in the fact that words like intelligence and knowledge can be hard to define, let alone measure.<span id="more-24"></span></p>
<p>One way to evaluate  intelligence is to consider one&#8217;s ability to think. It&#8217;s not a great measurement for people since everyone (or so they say) can think, but it is an interesting way to evaluate the intelligence of machines. Because thinking is inherently human, Alan Turing proposed we could evaluate a machine&#8217;s ability to think through its ability to act as a human. If the machine could successfully impersonate a human, the machine would demonstrate its ability to think, and thus its intelligence. This is the test he proposed:</p>
<blockquote><p>The Turing test is a proposal for a test of a machine&#8217;s ability to demonstrate intelligence. It proceeds as follows: a human judge engages in a natural language conversation with one human and one machine, each of which tries to appear human. All participants are placed in isolated locations. If the judge cannot reliably tell the machine from the human, the machine is said to have passed the test. In order to test the machine&#8217;s intelligence rather than its ability to render words into audio, the conversation is limited to a text-only channel such as a computer keyboard and screen. (<a href="http://en.wikipedia.org/wiki/Turing_test" target="_blank">Wikipedia</a>)</p></blockquote>
<p>No machine has ever passed the Turing Test.</p>
<p>And it&#8217;s certainly not for lack of trying. If you were on AIM in the late 90&#8242;s, you most likely participated in a Turing Test. Remember SmarterChild (or any of the other bots that popped on on instant messaging services)? If you do, then  I&#8217;m sure you&#8217;ll agree with me that they were not very convincing human representations.</p>
<p>But what if we modernized the rules a little bit, and conducted a Twitter Turing Test &#8212; Given two twitter users, one human and one machine, could a third twitter user, who follows and is followed by both, determine which one is human and which one is not? The twitter bot would have access to the twitter api, and I imagine the algorithm would employ some of these strategies:</p>
<ul>
<li>Copy tweets that originiate from close social proximity to the targeted user, but wouldn&#8217;t show up in the user&#8217;s stream.</li>
<li>Copy tweets that originiate from from a certain geographical area to give the appearance of living there</li>
<li>Participate in trending topics, both global and local</li>
<li>Share links found through StumbleUpon, Digg, or other social bookmarking services.</li>
<li>Retweet popular tweets</li>
</ul>
<p>I believe that someone could build a machine to pass the Twitter Turing Test today . Sure, it&#8217;s  less intimate (and therefore less challenging) than the original Turing Test, but it&#8217;s also  more analogous to our current forms of virtual communication. Social media has created a type of communication that is less synchronous, less personal, and (if you agree with Alan Turing about what the Turing Test proves) involves less thinking.</p>
<p>If social media is what will allow machines to pass the Turing Test, and the Turing Test is an indication of a machine&#8217;s intelligence, then what does that say about social media&#8217;s impact on our intelligence?</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/ycf-zOW45AA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/08/does-social-media-make-us-stupider/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/08/does-social-media-make-us-stupider/</feedburner:origLink></item>
		<item>
		<title>Email Isn’t Going Anywhere</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/CpxTsVnJhbM/</link>
		<comments>http://zmsmith.com/2010/06/email-isnt-going-anywhere/#comments</comments>
		<pubDate>Fri, 18 Jun 2010 16:45:52 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Random Thoughts]]></category>
		<category><![CDATA[email]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=21</guid>
		<description><![CDATA[Yesterday Sheryl Sandberg proclaimed that &#8220;email is probably going away&#8221; because teenagers don&#8217;t it as their primary mode of social communication. It&#8217;s not. Here&#8217;s why: Teenagers have never used email as their primary mode of social communication, or any form of communication for that matter. Before the explosion of social media, most teenagers opted to use [...]]]></description>
				<content:encoded><![CDATA[<p>Yesterday <a href="http://www.businessinsider.com/facebook-coo-email-is-probably-going-away-2010-6" target="_blank">Sheryl Sandberg proclaimed </a> that &#8220;email is probably going away&#8221; because teenagers don&#8217;t it as their primary mode of social communication. It&#8217;s not. Here&#8217;s why:</p>
<p><span id="more-21"></span></p>
<ol>
<li>Teenagers have never used email as their primary mode of social communication, or any form of communication for that matter. Before the explosion of social media, most teenagers opted to use instant messaging to communicate online. Only after people move into a situation where they are forced to coordinate with others who they don&#8217;t know very well or don&#8217;t have very much face time with (think college professor or business contact) does email become the preferred way to correspond. Once we adjust to email, we start to use it socially. <br />
<br/>When old fashioned snail mail was the standard, parents got a lot of mail; kids did not. Teenagers didn&#8217;t really need mail then, and they don&#8217;t really need email now. The only reason teenagers have email addresses is to sign up for online services, which brings me to my next point&#8230;.</li>
<p></br></p>
<li>We need email as the <a href="http://en.wikipedia.org/wiki/Lowest_common_denominator#Figurative_uses" target="_blank">greatest common divisor</a> of the web. Now that oAuth is widely adopted, email appears to be less important. You can register for almost every new service through twitter, or facebook, or foursqaure, but when push comes to shove, every account you have can be traced back to your email address. It is your unique identifier. While I agree people will start to use email less often, it will never cease to exist. It&#8217;s like social security. We&#8217;re probably all going to start getting less of it; we may get none of it; but the system isn&#8217;t going anywhere because too many other processes would fail if we couldn&#8217;t be identified by it.</li>
</ol>
<p>I&#8217;m sure Sheryl Sandberg hopes email goes away; it would only drive more traffic to facebook. In reality, it isn&#8217;t going anywhere.</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/CpxTsVnJhbM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/06/email-isnt-going-anywhere/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/06/email-isnt-going-anywhere/</feedburner:origLink></item>
		<item>
		<title>Django: Check If a Field has Changed</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/wznPnKvbm-Q/</link>
		<comments>http://zmsmith.com/2010/05/django-check-if-a-field-has-changed/#comments</comments>
		<pubDate>Wed, 26 May 2010 16:55:32 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=19</guid>
		<description><![CDATA[I got fed up with manually checking if a field has changed in the save method of Django models so I quickly wrote this snippet to generalize it: def has_changed(instance, field): if not instance.pk: return False old_value = instance.__class__._default_manager.\ filter(pk=instance.pk).values(field).get()[field] return not getattr(instance, field) == old_value Here&#8217;s how could be used: class Sneetch(models.Model): has_star = [...]]]></description>
				<content:encoded><![CDATA[<p>I got fed up with manually checking if a field has changed in the <code>save</code> method of Django models so I quickly wrote this snippet to generalize it:</p>
<pre class="brush:python">def has_changed(instance, field):
    if not instance.pk:
        return False
    old_value = instance.__class__._default_manager.\
             filter(pk=instance.pk).values(field).get()[field]
    return not getattr(instance, field) == old_value
</pre>
<p>Here&#8217;s how could be used:</p>
<pre class="brush:python">class Sneetch(models.Model):
    has_star = models.BooleanField(default=False)
    succumbs_to_peer_pressure = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        if has_changed(self, 'has_star'):
            self.succumbs_to_peer_pressure = True
        super(Sneetch, self).save(*args, **kwargs)
</pre>
<p>Let me know if you improve it&#8230;</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/wznPnKvbm-Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/05/django-check-if-a-field-has-changed/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/05/django-check-if-a-field-has-changed/</feedburner:origLink></item>
		<item>
		<title>3 Ways To Guarantee I’ll Never Work For You</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/NGtcYZoPETs/</link>
		<comments>http://zmsmith.com/2010/05/3-ways-to-guarantee-ill-never-work-for-you/#comments</comments>
		<pubDate>Fri, 21 May 2010 17:57:07 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Random Thoughts]]></category>
		<category><![CDATA[employment]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=18</guid>
		<description><![CDATA[It&#8217;s not easy to find developer in New York. At the moment, this city does not have enough technical talent. I think this will change quickly as NYU leads a charge for universities to become more involved in the startup scene, but as things stand, there are lot of business guys, a lot of ideas, [...]]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s not easy to find developer in New York. At the moment, this city does not have enough technical talent. I think this will change quickly as NYU leads a charge for universities to become more involved in the startup scene, but as things stand, there are lot of business guys, a lot of ideas, and not a lot of people who code. Almost every New York Tech Meetup presentation ends with &#8220;By the way, we&#8217;re looking for (Ruby|Python) developers, so contact us if you&#8217;re interested.&#8221;</p>
<p>Most companies put themselves at an even greater disadvantage in recruiting by writing awful job listings. If you include any of these 3 things, I promise to not be interested:</p>
<p><span id="more-18"></span></p>
<ol>
<li><strong>We&#8217;re in Stealth Mode</strong> &#8212; Listen, I understand first-mover advantage. I took Management 101 freshman year of college too. Your company being in stealth mode signals a couple of things to me:
<ul>
<li>There is going to be way too much back and forth before I even find out what your company does. First we&#8217;re going to send a couple of emails &#8211; You want to make sure I&#8217;m actually a developer and not just trying to steal your idea. Then we&#8217;re going to have a phone interview &#8211; You need to make sure I&#8217;d be a good fit. Next we need to do an in person interview &#8211; It&#8217;s very important that this interview is in person so that I can sign an NDA. Finally, you&#8217;ll share your mediocre idea with me.</li>
<li>You don&#8217;t really understand how startups work. I used to believe in stealth mode. I had all these ideas; all I had to do was pick one of them, and I&#8217;d be a millionaire. Guess what? Plenty of other people also had these ideas, but they actually made something happen. Now they&#8217;re millionaires. Success is about execution. In order to execute,  you&#8217;ll also need traction. If you are in stealth mode, you cannot acquire users.</li>
</ul>
<p><em>Note: Saying that &#8220;This product is going to change the way people [ambiguous verb]&#8221; or &#8220;We&#8217;re the next (Google|Twitter|Facebook)&#8221; does not count as telling me what your product doesn&#8217;t do yet.</em></li>
<li><strong>Absurd, Hyperbolic Nouns</strong> &#8212; Unless you&#8217;re trying to recruit a 16 year-old out of his mother&#8217;s basement, I do not anticipate you having success looking for JavaScript Ninjas, Ruby Gurus, of Python Rockstars. Despite the apparent industry acceptance of the word, I&#8217;m also less likely to take your company seriously if you&#8217;re looking for a &#8220;hacker&#8221;.  I&#8217;m not impressed by your misunderstanding of developer speak.</li>
<li><strong>No Equity Offer</strong> &#8212; Anyone who wants to work at a start-up for solely financial benefiet is not a good candidate. On the other hand, anyone who is willing to work for a start-up and not get a piece of the upside is a sucker. There&#8217;s a saying I love: &#8220;Equity is like shit; if you spread it around, beautiful things grow, but if you keep it all in one place, it just sits in a pile and stinks.&#8221; I have no desire to help you increase the value of your stinking pile of shit.</li>
</ol>
<p>Here&#8217;s my make nice:</p>
<p>There are some non-technical founders with really good ideas trying to launch companies. Unfortunately, many of them don&#8217;t know how to attract the technical support they need. Maybe this list will help.</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/NGtcYZoPETs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/05/3-ways-to-guarantee-ill-never-work-for-you/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/05/3-ways-to-guarantee-ill-never-work-for-you/</feedburner:origLink></item>
		<item>
		<title>Ambiguous Pricing Sells Businesses Short</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/VOq-UYG5fHc/</link>
		<comments>http://zmsmith.com/2010/05/ambiguous-pricing-sells-businesses-short/#comments</comments>
		<pubDate>Thu, 06 May 2010 23:57:14 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Random Thoughts]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[pricing]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=15</guid>
		<description><![CDATA[Last night I went to grab some late night pizza with my friend Matt. (It was technically May 6th, so I no longer felt obligated to eat tacos.) There was no posted menu, so when we got the front of the line, I decided to ask about the price difference between a plain slice and [...]]]></description>
				<content:encoded><![CDATA[<p>Last night I went to grab some late night pizza with my friend Matt. (It was technically May 6th, so I no longer felt obligated to eat tacos.) There was no posted menu, so when we got the front of the line, I decided to ask about the price difference between a plain slice and a slice with toppings. I was told that both were $3.50, so I ordered a slice of sausage. Matt got a slice with pepperoni and mushroom, and he was also charged $3.50. The guy behind us got a slice with sausage and pepperoni; he was charged $5.00. If I could remember which pizza place we were at, I wouldn&#8217;t go back.</p>
<p>There&#8217;s a delicious pasta place on 22nd and 3rd called <a href="http://www.yelp.com/biz/lamarca-pasta-new-york" target="_blank">lamarca</a>. There are two entrances: one into a cheese shop and one into a sit down restaurant. The first time I went, my group walked in and tried to figure out where we should be going. There was no menu in the cheese shop, so we decided on the restaurant. The food was great, but the pasta lunch ended up costing us each around $15, which was surprising since we had heard it was very inexpensive. Since then I&#8217;ve learned they have a 3 tiered pricing scheme:</p>
<ul>
<li>If you order form a waitress, it costs about $15 and you get a roll, a small side salad, a fancy bowl and a metal fork.</li>
<li>If you order from the cheese shop and sit down in the restaurant, it costs about $8, but you get a different bowl and a plastic fork</li>
<li>If you order to-go from the cheese shop, it costs about $7; no bowl, but you still get the fork</li>
</ul>
<p>I&#8217;ve been back to lamarca because the food is great and affordable (now that I&#8217;m on the inside), but I never feel good about giving them my money. I&#8217;d go there a lot more often if they had been straightforward with their pricing the first time I went.</p>
<p>I hate when businesses don&#8217;t make pricing information available to their customers and then try to take advantage of the fact that their customers and uninformed. While these tactics do promote <a href="http://en.wikipedia.org/wiki/Price_discrimination" target="_blank">price discrimination</a> and, therefore, short term profits, they are myopic and bad for business.</p>
<p>When <a href="http://twitter.com/benokur" target="_blank">Ben</a> and I ran <a href="http://washuwash.com/" target="_blank">Wash-U-Wash</a>, we  prided ourselves on customer satisfaction. One year many of our customers gave us more pounds of laundry then they had paid for. While most customers never asked us about the status of their account, we were also irresponsible about reaching out to our customers when they went over. Contractually, we had the right to collect a significant amount of money; however, we felt that we weren&#8217;t transparent enough about account balances. We decided to inform the relevant customers that they had gone over their poundage, but that we would forgive the balance on their account. This proved to be a good decision as over 70% of our non graduating customer base returned the next year.</p>
<p>Being ambiguous about pricing is a great way to irritate and ultimately drive away your customer base.</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/VOq-UYG5fHc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/05/ambiguous-pricing-sells-businesses-short/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/05/ambiguous-pricing-sells-businesses-short/</feedburner:origLink></item>
		<item>
		<title>Using Custom Django QuerySets</title>
		<link>http://feedproxy.google.com/~r/zmsmith/zucu/~3/bsztao3_sww/</link>
		<comments>http://zmsmith.com/2010/04/using-custom-django-querysets/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 14:56:36 +0000</pubDate>
		<dc:creator>Zach</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://zmsmith.com/?p=14</guid>
		<description><![CDATA[When I first started working with Django, I became frustrated that managers were not chainable. (If you don&#8217;t know what a Manager is you probably won&#8217;t find this post very useful. I recommend the DjangoBook for beginners.) Here&#8217;s a tutorial on a coding pattern our development team uses all the time on our PerformMatch product. [...]]]></description>
				<content:encoded><![CDATA[<p>When I first started working with Django, I became frustrated that managers were not chainable. (If you don&#8217;t know what a Manager is you probably won&#8217;t find this post very useful. I recommend the <a href="http://www.djangobook.com/en/2.0/chapter10/">DjangoBook</a> for beginners.) Here&#8217;s a tutorial on a coding pattern our <a href="http://varud.com">development team</a> uses all the time on our <a href="http://performline.com/transparency.html">PerformMatch</a> product. It was developed with the help of some <a href="http://www.djangosnippets.org/">Django Snippets</a> and <a href="http://ycharts.com">Ara Anjargolian</a>.</p>
<p><span id="more-14"></span></p>
<p>For our example, we&#8217;ll use <a href="http://en.wikipedia.org/wiki/The_Sneetches_and_Other_Stories">Sneetches</a>. Let&#8217;s start with a simple model:</p>
<pre class="brush:python">from django.db import models

class Sneetch(models.Model):
    has_star = models.BooleanField(default=False)</pre>
<p>Now Sneetches are bigots. Obviously having a star is either unequivocally better or worse than not having a star, but preference can change quickly. We want to to be able to change our code just as rapidly. To achieve this we can build a custom manager to keep our logic in one place. It will look something like this:</p>
<pre class="brush:python">
class SneetchManager(models.Manager):
    def get_query_set(self):
        return self.filter(has_star=True)</pre>
<p>We&#8217;ll also need to assign this manager to the model, so here&#8217;s what we&#8217;ll end up with:</p>
<pre class="brush:python">from django.db import models

class SuperiorSneetchManager(models.Manager):
    def get_query_set(self):
        return self.filter(has_star=True)

class Sneetch(models.Model):
    has_star = models.BooleanField(default=False)

    superior_sneetches = SuperiorSneetchManager()</pre>
<p>This is what django recommends in the documentation for writing managers, and it&#8217;s pretty good. I can make this call wherever I want:</p>
<pre class="brush:python">    Sneetch.superior_sneetches.all()</pre>
<p>And because of the way we organized the code, we can change our mind about whether Sneetches with stars on their bellies are better than Sneetches without stars on thars.</p>
<p>Overriding the <code>get_query_set</code> method is great, but it&#8217;s static. We can&#8217;t pass in any arguments. Maybe we want to work with either the superior or the inferior Sneetches. To do this, we can make a method that is an attribute of a manager. So let&#8217;s rewrite the manager, and this time we&#8217;ll just assign it to the the <code>objects</code> attribute of our class. Since models, by default, have an attribute <code>objects</code> which is the class <code>models.Manager</code>, we can override this attribute and since we will be replacing it with a class that extends <code>models.Manager</code>, we won&#8217;t lose any functionality:</p>
<pre class="brush:python">
class SneetchManager(models.Manager):
    def segregate(self, superior=True):
        if superior:
            return self.filter(has_star=True)
        else:
            return self.filter(has_star=False)

class Sneetch(models.Model):
    has_star = models.BooleanField(default=False)

    objects = SneetchManager()</pre>
<p>Now we have some choice. We can make either of these calls:</p>
<pre class="brush:python">    Sneetch.objects.segregate(superior=True)
    Sneetch.objects.segregate(superior=False)</pre>
<p>We almost have something really useful here, but we have a glaring limitation, <code>segregate</code> is not a chainable attribute. Only <code>Sneetch.objects</code> knows about <code>segregate</code>. Take a look at this code:</p>
<pre class="brush:python">    Sneetch.objects.all().segregate(superior=True)</pre>
<p>This raises an <code>AtrributeError</code> because <code>all</code> returns a <code>QuerySet</code>, which has no attribute <code>segregate</code>. We can overcome this by defining our own <code>QuerySet</code> that does have an attribute <code>segregate</code>.</p>
<pre class="brush:python">    from django.db.models.query import QuerySet

    class SneetchQuerySet(QuerySet):
        def segregate(self, superior=True):
            if superior:
                return self.filter(has_star=True)
            else:
                return self.filter(has_star=False)</pre>
<p>We know from the first example, that managers always call <code>get_query_set</code>, so let&#8217;s leverage that and write a manager that gets our <code>SneetchQuerySet</code> into the action.</p>
<pre class="brush:python">class SneetchManager(models.Manager):
    def get_query_set(self):
        return SneetchQuerySet(self.model)</pre>
<p>Now when <code>Sneetch.objects</code> calls <code>get_query_set</code> it will return a <code>SneetchQuerySet</code> which has an attribute <code>segregate</code>. We have on final step before we put it all together.</p>
<p><code>Sneetch.objects</code> still doesn&#8217;t have an attribute <code>segregate</code> so our original call of <code>Sneetch.objects.segregate(superior=False)</code> will fail. If you read the Django source, you will see that <code>models.Manager</code> defines all the documented methods of <code>QuerySet</code>. Here is an example (copied directly from the source of v1.1):</p>
<pre class="brush:python">    def filter(self, *args, **kwargs):
        return self.get_query_set().filter(*args, **kwargs)</pre>
<p>We could mimic this behavior and allow our manager to call <code>segregate</code> by defining a segregate attribute for the manager. That is perfectly legal, but it would also force us to define any new methods we add to <code>SneetchQuerySet</code> in two places. Instead, we can use the magic python method <code>__getattr__</code>. I&#8217;ll save an explanation of <code>__getattr__</code> for another post, but you can <a href="http://docs.python.org/reference/datamodel.html#object.__getattr__" target="_blank">check the docs</a>.</p>
<p>Here&#8217;s our final product:</p>
<pre class="brush:python">    from django.db import models
    from django.db.models.query import QuerySet

    class SneetchQuerySet(QuerySet):
        def segregate(self, superior=True):
            if superior:
                return self.filter(has_star=True)
            else:
                return self.filter(has_star=False)

    class SneetchManager(models.Manager):
        def get_query_set(self):
            return SneetchQuerySet(self.model)
        def __getattr__(self, name):
            return getattr(self.get_query_set(), name)

    class Sneetch(models.Model):
        has_star = models.BooleanField(default=False)

        objects = SneetchManager()

    #Both These are Valid

    Sneetch.objects.segregate()
    Sneetch.objects.filter(**kwargs).segregate()</pre>
<p>And that&#8217;s it. For any model that has repetitive/complex queries, I almost always write a custom <code>QuerySet</code> and <code>Manager</code>.</p>
<img src="http://feeds.feedburner.com/~r/zmsmith/zucu/~4/bsztao3_sww" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://zmsmith.com/2010/04/using-custom-django-querysets/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://zmsmith.com/2010/04/using-custom-django-querysets/</feedburner:origLink></item>
	</channel>
</rss>
