<?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>Paul Gross's Blog</title>
	
	<link>http://www.pgrs.net</link>
	<description />
	<lastBuildDate>Tue, 08 May 2012 03:52:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/pgrs" /><feedburner:info uri="pgrs" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>How Braintree Builds a Platform for Developers</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/Np7yENuGGRg/</link>
		<comments>http://www.pgrs.net/2012/05/02/how-braintree-builds-a-platform-for-developers/#comments</comments>
		<pubDate>Thu, 03 May 2012 01:34:35 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22468</guid>
		<description><![CDATA[The slides from my Intuit CTOF (&#8220;Create The Offering Forum&#8221;) talk are now online: How Braintree Builds a Platform for Developers. The slides were generated using showoff.]]></description>
			<content:encoded><![CDATA[<p>The slides from my <a href="http://ctof.intuit.com">Intuit CTOF</a> (&#8220;Create The Offering Forum&#8221;)</a> talk are now online: <a href='http://www.pgrs.net/wp-content/uploads/2012/05/intuit_presentation.pdf'>How Braintree Builds a Platform for Developers</a>.</p>
<p>The slides were generated using <a href="https://github.com/schacon/showoff">showoff</a>.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/Np7yENuGGRg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2012/05/02/how-braintree-builds-a-platform-for-developers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2012/05/02/how-braintree-builds-a-platform-for-developers/</feedburner:origLink></item>
		<item>
		<title>Data Migrations for NoSQL with Curator</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/F8xSYJvFnb4/</link>
		<comments>http://www.pgrs.net/2012/03/08/data-migrations-for-nosql-with-curator/#comments</comments>
		<pubDate>Thu, 08 Mar 2012 15:41:55 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22458</guid>
		<description><![CDATA[This post is cross-posted at Data Migrations for NoSQL with Curator. The NoSQL movement has brought us a wave of new data stores beyond the traditional relational databases. These data stores come with their own tradeoffs, but they provide some incredible benefits. At Braintree, we are moving in the direction of using Riak as our <a href='http://www.pgrs.net/2012/03/08/data-migrations-for-nosql-with-curator/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>This post is cross-posted at <a href="http://www.braintreepayments.com/devblog/data-migrations-for-nosql-with-curator">Data Migrations for NoSQL with Curator</a>.</p>
<p>The NoSQL movement has brought us a wave of new data stores beyond the traditional relational databases. These data stores come with their own tradeoffs, but they provide some incredible benefits. At <a href="http://www.braintreepayments.com/">Braintree</a>, we are moving in the direction of using <a href="http://basho.com/products/riak-overview/">Riak</a> as our next generation data store. We love its focus on scalability and availability. Servers can fail without causing any downtime, and we can add more capacity by simply adding more servers to the cluster.</p>
<p>One great feature of relational databases, however, is the consistency in the shape of the data. You know if you have a <code>people</code> table, every row has the same columns. Some fields might be null, but there won&#8217;t be any surprises. Furthermore, if you want to rename or modify a column, it&#8217;s a simple operation. In the case of <a href="http://www.postgresql.org/">PostgreSQL</a> and other databases, a rename is nearly instantaneous. We lose this ability with Riak and most NoSQL databases. We can easily add attributes (columns), but we cannot easily rename them or change the data within each document (row).</p>
<p>Since our apps are always evolving at Braintree, we needed a way for our data to keep up with our code. Our solution is something we&#8217;re calling lazy data migrations, and we&#8217;ve built it into our repository and model framework, <a href="https://github.com/braintree/curator">curator</a>. You can read more about curator on our blog at <a href="http://www.braintreepayments.com/devblog/untangle-domain-and-persistence-logic-with-curator">Untangle Domain and Persistence Logic with Curator</a>.</p>
<h3>The problem</h3>
<p>Say we have a collection of <code>people</code> in Riak. This is analogous to a <code>people</code> table in a relational database. When we first built the app, we added fields for <code>first_name</code> and <code>last_name</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">person = Person.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Joe&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Smith&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>Some time has passed, our app has data, and we now realize that names are a pain. What do we do with middle names? What about people with multiple first or last names? We want to just simplify the system and collect only a name. We no longer care about a separate first and last name. The problem is we have a ton of data in the old format. How do we handle that old records have a <code>first_name</code> and <code>last_name</code>, but going forward, we want just <code>name</code>?</p>
<p>In a relational database, we would simply write a database migration that looks like:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> people <span style="color: #993333; font-weight: bold;">ADD</span> <span style="color: #993333; font-weight: bold;">COLUMN</span> name <span style="color: #993333; font-weight: bold;">VARCHAR</span>;
<span style="color: #993333; font-weight: bold;">UPDATE</span> people <span style="color: #993333; font-weight: bold;">SET</span> name <span style="color: #66cc66;">=</span> first_name <span style="color: #66cc66;">||</span> <span style="color: #ff0000;">' '</span> <span style="color: #66cc66;">||</span> last_name;
<span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> people <span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">COLUMN</span> first_name<span style="color: #66cc66;">,</span> <span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">COLUMN</span> last_name;</pre></div></div>

<p>This migration might take a while to run, but once it&#8217;s done, we know that all data has been migrated. We can then change all of our code to only deal with <code>name</code>, knowing we no longer have <code>first_name</code> or <code>last_name</code>.</p>
<p>In a NoSQL database like Riak, we cannot simply change the schema. We have to come up with a different solution. Here are the steps we went through in trying to come up with the solution that made its way into <a href="https://github.com/braintree/curator">curator</a>:</p>
<h3>Solution attempt 1: Scattered conditionals</h3>
<p>The first solution is to make the <code>Person</code> class smart enough to handle both cases.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Person
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:first_name</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span>, <span style="color:#ff3333; font-weight:bold;">:name</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>We can populate whatever fields we get back from the data store. Then, when we want to do something with the <code>name</code>, we have to use code like:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">if</span> person.<span style="color:#9900CC;">name</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Name is #{person.name}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">else</span>
  <span style="color:#CC0066; font-weight:bold;">puts</span> <span style="color:#996600;">&quot;Name is #{person.first_name} #{person.last_name}&quot;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The problem with this approach is that we have to use branching code like this whenever we want to use the <code>name</code>. It quickly gets messy.</p>
<h3>Solution attempt 2: Gathered conditionals</h3>
<p>The second solution is to move this logic to the place where we read the Person out of the data store:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">attributes = fetch_from_riak
<span style="color:#9966CC; font-weight:bold;">if</span> attributes<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:name</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  person = Person.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> attributes<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:name</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">else</span>
  person = Person.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;#{attributes[:first_name]} #{attributes[:last_name]}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Now, we only have to do it once and we can change our <code>Person</code> class to only know about <code>name</code>.</p>
<p>This solution works well, but what happens a year down the road when we&#8217;ve made lots of data changes to many different models? We don&#8217;t want a bunch of conditionals all over our persistence code.</p>
<h3>Our solution: Lazy data migrations</h3>
<p>We pulled the idea from solution 2 into the idea of a migration (similar to ActiveRecord migrations). Migrations target a given collection at a given version. They look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> ConsolidateName <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Curator::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> migrate<span style="color:#006600; font-weight:bold;">&#40;</span>attributes<span style="color:#006600; font-weight:bold;">&#41;</span>
    first_name = attributes.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:first_name</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    last_name = attributes.<span style="color:#9900CC;">delete</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:last_name</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    attributes.<span style="color:#9900CC;">merge</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;#{first_name} #{last_name}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>This migration is stored in <code>db/migrate/people/0001_consolidate_name.rb</code>. We&#8217;ve also added the concept of a version to each Model. By default, models start at version 0. When they are read from the Repository, the attributes are run through any migrations that are a greater version (based on the version in the filename):</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">person = PersonRepository.<span style="color:#9900CC;">find_by_key</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;person_id&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
person.<span style="color:#9900CC;">version</span> <span style="color:#008000; font-style:italic;">#=&gt; 1</span></pre></div></div>

<p>Now, the migration logic is isolated from the rest of the application. The rest of the app can safely assume that all <code>Person</code> objects have only a <code>name</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Person
  current_version <span style="color:#006666;">1</span>
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:name</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>We mark the <code>Person</code> class with <code>current_version 1</code> to signify that new instances start at version 1, since they have a <code>name</code> attribute rather than <code>first_name</code>/<code>last_name</code>. </p>
<p>These migrations run when models are read, so they are lazy. Data will migrate as it&#8217;s used, and update when saved. This means that, unlike with relational databases, the website can be up and serving requests while the data is migrated.</p>
<p>If you want to force the data to migrate (and not wait for all data to be used), you can simply find models who haven&#8217;t been migrated and save them. The <code>version</code> attribute is indexed by default:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">PersonRepository.<span style="color:#9900CC;">find_by_version</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">0</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>person<span style="color:#006600; font-weight:bold;">|</span>
  PersonRepository.<span style="color:#9900CC;">save</span><span style="color:#006600; font-weight:bold;">&#40;</span>person<span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<h3>Testing</h3>
<p>Unlike ActiveRecord migrations, curator migrations have no side effects. They simply accept a hash and return a new hash. This makes them easy to call from a unit test:</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;">'spec_helper'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'db/migrate/people/0001_consolidate_name'</span>
&nbsp;
describe ConsolidateName <span style="color:#9966CC; font-weight:bold;">do</span>
  describe <span style="color:#996600;">&quot;migrate&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
    it <span style="color:#996600;">&quot;concatenates first_name and last_name&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span>
      attributes = <span style="color:#006600; font-weight:bold;">&#123;</span>:first_name <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Joe&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:last_name</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;Smith&quot;</span><span style="color:#006600; font-weight:bold;">&#125;</span>
      ConsolidateName.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">migrate</span><span style="color:#006600; font-weight:bold;">&#40;</span>attributes<span style="color:#006600; font-weight:bold;">&#41;</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:name</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">should</span> == <span style="color:#996600;">&quot;Joe Smith&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></pre></div></div>

<h3>Limitations</h3>
<p>Curator migrations are lazy, so at any given time you might have documents with different versions in the data store. This is not normally a problem since the migrations will run as soon as the objects are read. However, if you add a migration that changes an indexed field, you cannot rely on that index to return all of the correct values until you migrate them all. In this case, you might want to force migration by reading and saving all of the documents.</p>
<h3>Next Steps</h3>
<p>You can see these migrations in action in the <a href="https://github.com/braintree/curator_rails_example">curator_rails_example</a>.</p>
<p>Let us know what you think about lazy data migrations in <a href="https://github.com/braintree/curator">curator</a>. Feel free to open issues on GitHub, submit pull requests, and help us make it better.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/F8xSYJvFnb4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2012/03/08/data-migrations-for-nosql-with-curator/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2012/03/08/data-migrations-for-nosql-with-curator/</feedburner:origLink></item>
		<item>
		<title>Untangle Domain and Persistence Logic with Curator</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/JLNxWUkp5uo/</link>
		<comments>http://www.pgrs.net/2012/02/21/untangle-domain-and-persistence-logic-with-curator/#comments</comments>
		<pubDate>Tue, 21 Feb 2012 15:46:14 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22449</guid>
		<description><![CDATA[This post is cross-posted at http://www.braintreepayments.com/devblog/untangle-domain-and-persistence-logic-with-curator. The problem Ruby on Rails is a great web framework, and we use it extensively at Braintree to build web apps. One criticism of Rails, however, is that it encourages tight coupling of domain and persistence layers. The convention in Ruby on Rails is for domain objects to extend <a href='http://www.pgrs.net/2012/02/21/untangle-domain-and-persistence-logic-with-curator/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>This post is cross-posted at <a href="http://www.braintreepayments.com/devblog/untangle-domain-and-persistence-logic-with-curator">http://www.braintreepayments.com/devblog/untangle-domain-and-persistence-logic-with-curator</a>.</p>
<h3>The problem</h3>
<p><a href="http://rubyonrails.org/">Ruby on Rails</a> is a great web framework, and we use it extensively at <a href="http://www.braintreepayments.com/">Braintree</a> to build web apps. One criticism of Rails, however, is that it encourages tight coupling of domain and persistence layers. The convention in Ruby on Rails is for domain objects to extend <code>ActiveRecord::Base</code> and directly gain persistence. This makes building small apps easy, but as applications grow, the tight coupling starts to make things more difficult.</p>
<p>Domain objects in more complicated systems no longer have a simple mapping into a database row. For example, money might be represented as cents and currency in the database, but as a Money object in the domain layer. Now, the domain objects have to handle both the money logic and the money persistence. Even if the code is abstracted away by a gem, it still lives in the domain object. Take a look at the methods on a brand new model in Rails:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&gt;&gt;</span> <span style="color:#9966CC; font-weight:bold;">class</span> Bar <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> <span style="color:#006600; font-weight:bold;">&#40;</span>Bar.<span style="color:#9900CC;">methods</span>.<span style="color:#9900CC;">sort</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#CC00FF; font-weight:bold;">Object</span>.<span style="color:#9900CC;">methods</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">count</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">391</span></pre></div></div>

<p>These methods are in addition to anything you add to the model.</p>
<h3>The solution</h3>
<p>There&#8217;s nothing in Rails that says you have to tie your domain objects to persistence. It&#8217;s merely a convention. At <a href="http://www.braintreepayments.com/">Braintree</a>, we&#8217;re using a new convention for new projects. Our domain objects do not contain any persistence logic. Instead, we&#8217;ve introduced a <a href="http://domaindrivendesign.org/node/123">repository</a> layer which is in charge of the persistence of these domain objects. This pattern is well-documented in <a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215">Domain Driven Design</a>.</p>
<p>Introducing a Repository layer into our applications has a number of benefits. The main benefit is that it separates out different kinds of logic. Domain logic goes into the domain objects, and can be tested in isolation without any persistence. Persistence logic goes into the repository objects, which only deal with saving and retrieving objects.</p>
<p>The second big benefit is that abstracting persistence logic into a repository allows us to swap persistence back-ends without much trouble. The most notable case is that we can swap in an in-memory data store for testing (or for most tests), but use Riak for the real application. Since the repository interacts with the back-end data store, the application code is the same regardless of back-end. It also allows us to use different back-ends for different kinds of data but still have a consistent pattern around persistence.</p>
<p>We&#8217;ve extracted this model and repository framework from our current applications and released it as <a href="https://github.com/braintree/curator">curator</a>. Curator currently supports <a href="http://basho.com/">Riak</a> as the persistence back-end, but more back-ends are coming soon.</p>
<p>Domain objects include <code>Curator::Model</code>, which just gives helper methods like an initialize that sets instance variables. It also adds some helper methods for Rails.</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Note
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Curator::Model</span>
  attr_accessor <span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#ff3333; font-weight:bold;">:description</span>, <span style="color:#ff3333; font-weight:bold;">:user_id</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
note = Note.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;My Note&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:description</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;My description&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> note.<span style="color:#9900CC;">description</span></pre></div></div>

<p>These model classes don&#8217;t have a lot of extra stuff:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&gt;&gt;</span> <span style="color:#9966CC; font-weight:bold;">class</span> Bar
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span>   <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Curator::Model</span>
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
<span style="color:#006600; font-weight:bold;">&gt;&gt;</span> Bar.<span style="color:#9900CC;">methods</span>.<span style="color:#9900CC;">sort</span> <span style="color:#006600; font-weight:bold;">-</span> <span style="color:#CC00FF; font-weight:bold;">Object</span>.<span style="color:#9900CC;">methods</span>
<span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:_to_partial_path</span>, <span style="color:#ff3333; font-weight:bold;">:current_version</span>, <span style="color:#ff3333; font-weight:bold;">:model_name</span>, <span style="color:#ff3333; font-weight:bold;">:version</span><span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>

<p>Repositories include the <code>Curator::Repository</code> module:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> NoteRepository
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Curator::Repository</span>
  indexed_fields <span style="color:#ff3333; font-weight:bold;">:user_id</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Repositories have <code>save</code>, <code>find_by_id</code>, and <code>find_by</code> methods for indexed fields:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">note = Note.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:user_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;my_user&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
NoteRepository.<span style="color:#9900CC;">save</span><span style="color:#006600; font-weight:bold;">&#40;</span>note<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
NoteRepository.<span style="color:#9900CC;">find_by_id</span><span style="color:#006600; font-weight:bold;">&#40;</span>note.<span style="color:#9900CC;">id</span><span style="color:#006600; font-weight:bold;">&#41;</span>
NoteRepository.<span style="color:#9900CC;">find_by_user_id</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;my_user&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>

<p>As persistence gets more complicated, repositories can implement their own serialize and deserialize methods to handle any case. For example, suppose our note object contains a PDF:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> NoteRepository
  <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Curator::Repository</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">serialize</span><span style="color:#006600; font-weight:bold;">&#40;</span>note<span style="color:#006600; font-weight:bold;">&#41;</span>
    attributes = <span style="color:#9966CC; font-weight:bold;">super</span><span style="color:#006600; font-weight:bold;">&#40;</span>note<span style="color:#006600; font-weight:bold;">&#41;</span>
    attributes<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:pdf</span><span style="color:#006600; font-weight:bold;">&#93;</span> = <span style="color:#CC00FF; font-weight:bold;">Base64</span>.<span style="color:#9900CC;">encode64</span><span style="color:#006600; font-weight:bold;">&#40;</span>note.<span style="color:#9900CC;">pdf</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> note.<span style="color:#9900CC;">pdf</span>
    attributes
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">deserialize</span><span style="color:#006600; font-weight:bold;">&#40;</span>attributes<span style="color:#006600; font-weight:bold;">&#41;</span>
    note = <span style="color:#9966CC; font-weight:bold;">super</span><span style="color:#006600; font-weight:bold;">&#40;</span>attributes<span style="color:#006600; font-weight:bold;">&#41;</span>
    note.<span style="color:#9900CC;">pdf</span> = <span style="color:#CC00FF; font-weight:bold;">Base64</span>.<span style="color:#9900CC;">decode64</span><span style="color:#006600; font-weight:bold;">&#40;</span>attributes<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:pdf</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> attributes<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:pdf</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    note
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>As you can see, all persistence logic around PDFs lives in the Repository. The Note class does not care how PDFs are stored.</p>
<h3>Curator in action</h3>
<p>If you want to see a simple, fully functional Rails application using curator, check out <a href="https://github.com/braintree/curator_rails_example">curator_rails_example</a>. I will detail the relevant bits below.</p>
<p>Thanks to Rails 3.x, you can include <code>ActiveModel::Validations</code> in any class to get validations. So if you want your note class to validate, it would look 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> Note
   <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">Curator::Model</span>
   <span style="color:#9966CC; font-weight:bold;">include</span> <span style="color:#6666ff; font-weight:bold;">ActiveModel::Validations</span>
   attr_accessor <span style="color:#ff3333; font-weight:bold;">:id</span>, <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#ff3333; font-weight:bold;">:description</span>
   validates <span style="color:#ff3333; font-weight:bold;">:title</span>, <span style="color:#ff3333; font-weight:bold;">:presence</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>
 <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>You can also build forms from these objects. new.html.erb would look like:</p>

<div class="wp_syntax"><div class="code"><pre class="erb" style="font-family:monospace;">&lt;%= form_for @note do |f| %&gt;                                  
  &lt;%= f.error_messages %&gt;                                     
  &lt;dl&gt;                                                        
    &lt;dt&gt;&lt;%= f.label :title %&gt;&lt;/dt&gt;                            
    &lt;dd&gt;&lt;%= f.text_field :title %&gt;&lt;/dd&gt;                       
    &lt;dt&gt;&lt;%= f.label :description %&gt;&lt;/dt&gt;                      
    &lt;dd&gt;&lt;%= f.text_area :description, :size =&gt; &quot;60x12&quot; %&gt;&lt;/dd&gt;
  &lt;/dl&gt;                                                       
  &lt;%= f.submit &quot;Create&quot; %&gt;                                    
&lt;% end %&gt;</pre></div></div>

<p>And the controller 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> NotesController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActionController::Base</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> new
    <span style="color:#0066ff; font-weight:bold;">@note</span> = Note.<span style="color:#9900CC;">new</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#0066ff; font-weight:bold;">@note</span> = Note.<span style="color:#9900CC;">new</span><span style="color:#006600; font-weight:bold;">&#40;</span>request.<span style="color:#9900CC;">POST</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:note</span><span style="color:#006600; font-weight:bold;">&#93;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">if</span> <span style="color:#0066ff; font-weight:bold;">@note</span>.<span style="color:#9900CC;">valid</span>?
      NoteRepository.<span style="color:#9900CC;">save</span><span style="color:#006600; font-weight:bold;">&#40;</span>@note<span style="color:#006600; font-weight:bold;">&#41;</span>
      redirect_to notes_path
    <span style="color:#9966CC; font-weight:bold;">else</span>
      render <span style="color:#ff3333; font-weight:bold;">:new</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>That&#8217;s it. Rails makes it really easy to build forms and validate against our models.<br />
Next Steps</p>
<p>Please check out the <a href="https://github.com/braintree/curator">curator</a> code and let us know what you think. Like all software, <a href="https://github.com/braintree/curator">curator</a> is a work in progress, so feel free to open issues on Github, submit pull requests, and help us make it better.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/JLNxWUkp5uo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2012/02/21/untangle-domain-and-persistence-logic-with-curator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2012/02/21/untangle-domain-and-persistence-logic-with-curator/</feedburner:origLink></item>
		<item>
		<title>Setting up a Zotac ZBOX with XBMC as a home theater PC</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/qS3OdxZlbiQ/</link>
		<comments>http://www.pgrs.net/2011/12/23/setting-up-a-zotac-zbox-with-xbmc-as-a-home-theater-pc/#comments</comments>
		<pubDate>Fri, 23 Dec 2011 21:14:20 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22427</guid>
		<description><![CDATA[I have wanted a Home theater PC for awhile to play movies, music, Hulu, and more through my TV. I thought briefly about buying a prebuilt device (like a Roku), but I decided to hack one together myself. My main motivation was flexibility and the fact that I like to tinker. Furthermore, I wanted a <a href='http://www.pgrs.net/2011/12/23/setting-up-a-zotac-zbox-with-xbmc-as-a-home-theater-pc/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I have wanted a <a href="http://en.wikipedia.org/wiki/Home_theater_PC">Home theater PC</a> for awhile to play movies, music, <a href="http://www.hulu.com">Hulu</a>, and more through my TV. I thought briefly about buying a prebuilt device (like a <a href="http://www.roku.com/">Roku</a>), but I decided to hack one together myself. My main motivation was flexibility and the fact that I like to tinker. Furthermore, I wanted a device with a hard drive that I could load up with files and play directly to a TV.</p>
<p>I asked around for recommendations, and several of my coworkers recommended <a href="http://www.zotac.com">Zotac</a>. After looking through their options, I decided on a <a href="http://www.zotac.com/index.php?page=shop.product_details&#038;flypage=flypage_images-SRW.tpl&#038;product_id=336&#038;category_id=118&#038;option=com_virtuemart&#038;Itemid=100170&#038;lang=en">Zotac ZBOX ID41</a> (here it is on <a href="http://www.amazon.com/ZOTAC-ZBOX-Intel-Mini-PC-ZBOX-ID41-PLUS-U/dp/B004WO8OBC">Amazon</a>).</p>
<h3>Setting up Ubuntu</h3>
<p>I decided to run <a href="https://wiki.ubuntu.com/OneiricOcelot">Ubuntu 11.10 Oneiric Ocelot</a> for the operating system. The Zotac ZBOX has no CD drive, so I downloaded the Ubuntu ISO from the website, and I used <a href="http://unetbootin.sourceforge.net">UNetbootin</a> to make a bootable USB drive. </p>
<p>I plugged an HDMI cable from the Zotac into my TV, and I plugged a wired USB keyboard and mouse in the Zotac. I inserted the USB drive and booted it up. It automatically booted from the drive, and I selected Install.</p>
<p>Once the installation was finished, I had to go to Settings -> Sound and choose the HDMI output. Then, sound correctly played through my TV.</p>
<h3>Setting up XMBC</h3>
<p>There is a lot of software for home theater PCs. I chose <a href="http://xbmc.org">XBMC</a> since it seems very polished and has a lot of plugins for different video sources (such as <a href="http://www.youtube.com">Youtube</a>). It&#8217;s also optimized for a remote instead of requiring a full keyboard.</p>
<p>I had to add an extra apt repository in order to install the latest version of XMBC (11.0 beta1). Here are the commands I ran:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> add-apt-repository ppa:nathan-renniewaldock<span style="color: #000000; font-weight: bold;">/</span>xbmc-stable
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> xbmc</pre></div></div>

<p>Then, I launched XBMC from Ubuntu. I was greeted with a screen that looked like:</p>
<p><a href="http://www.pgrs.net/wp-content/uploads/2011/12/xbmc-eden.jpg"><img src="http://www.pgrs.net/wp-content/uploads/2011/12/xbmc-eden-300x179.jpg" alt="" title="xbmc-eden" width="300" height="179" class="alignnone size-medium wp-image-22442" /></a></p>
<p>I went to Settings and changed my region to where I live. I also told XBMC to update my library on start. Then, I went to Weather and entered my zip code to get local weather. Next I went to Videos -> Add ons and installed a bunch of video add ons (such as Youtube, HGTV, etc).</p>
<p>At this point, I had to manually run XBMC whenever I restarted the computer. There are many strategies to boot directly into XBMC. I decided to just add XBMC as a Startup Item in Ubuntu. I also allowed Ubuntu to boot without a password. So Ubuntu boots up and then runs XBMC when it&#8217;s finished. If I need to go back to Ubuntu, I can just exit from XBMC.</p>
<h3>Uploading media</h3>
<p>XMBC uses filenames to figure out which movie or TV show a file represents. For example, with default settings, episodes of a TV show need to be named in one of the following formats:</p>
<pre>
foo.s01e01.*
foo.s01.e01.*
foo.s01_e01.*
foo_[s01]_[e01]_*
foo.1x01.*
foo.101.*
</pre>
<p>These files should be in a folder with the name of the show. The full set of instructions can be found on the XBMC website at <a href="http://wiki.xbmc.org/?title=TV_Shows_%28Video_Library%29">TV Shows (Video Library)</a>.</p>
<p>I created a Movies directory and a TV Shows directory under /home/paul/Videos and uploaded my media. Then, I added these directories to XMBC and set the content type to Movies and TV Shows respectively (see <a href="http://wiki.xbmc.org/index.php?title=Media_sources">Media Sources</a>).</p>
<p>Finally, I quit XBMC and restarted it. It scanned my directories and added the movies and TV shows to the library.</p>
<h3>Hulu</h3>
<p>Unfortunately, there are no officially supported Hulu plugins for XBMC. I managed to get an unoffical plugin working with some extra effort using <a href="http://forum.xbmc.org/showthread.php?t=79148">Bluecop&#8217;s beta video plugin repository</a>.</p>
<p>I downloaded the zip file from the site above and saved it to the Zotac. Then, in XBMC, I went to Settings -> Add ons and chose to install add ons from a zip file. At this point, the Hulu plugin appeared in the list of available plugins to install. I installed the plugin, but it still didn&#8217;t work.</p>
<p>By looking in the XBMC log (~/.xbmc/temp/xbmc.log), I discovered that Hulu requires a newer version of <a href="http://rtmpdump.mplayerhq.hu">rtmpdump</a> than Ubuntu ships with.</p>
<p>I built the latest rtmpdump from source with the following commands:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> libssl-dev
<span style="color: #c20cb9; font-weight: bold;">git</span> clone <span style="color: #c20cb9; font-weight: bold;">git</span>:<span style="color: #000000; font-weight: bold;">//</span>git.ffmpeg.org<span style="color: #000000; font-weight: bold;">/</span>rtmpdump
<span style="color: #7a0874; font-weight: bold;">cd</span> rtmpdump
<span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #007800;">sys</span>=posix
<span style="color: #c20cb9; font-weight: bold;">cp</span> librtmp<span style="color: #000000; font-weight: bold;">/</span>librtmp.so.0 <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>i386-linux-gnu<span style="color: #000000; font-weight: bold;">/</span>librtmp.so.0</pre></div></div>

<p>The last step copies the new librtmp on top of the existing one, which isn&#8217;t great. Unfortunately, XBMC runs with a specified library path, so I couldn&#8217;t find an easy way to add a different directory to the path.</p>
<p>Now, Hulu works. Unfortunately, I have to browse for videos to play. If I search for a video, and then play it, I get the following error in the xbmc.log:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">ERROR: Error Type: <span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'exceptions.AttributeError'</span><span style="color: #66cc66;">&gt;</span>
ERROR: Error Contents: _Info instance has no attribute <span style="color: #483d8b;">'videoid'</span>
ERROR: Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
                      File <span style="color: #483d8b;">&quot;/home/paul/.xbmc/addons/plugin.video.hulu/default.py&quot;</span>, line <span style="color: #ff4500;">56</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
                        modes <span style="color: black;">&#40;</span> <span style="color: black;">&#41;</span>
                      File <span style="color: #483d8b;">&quot;/home/paul/.xbmc/addons/plugin.video.hulu/default.py&quot;</span>, line <span style="color: #ff4500;">36</span>, <span style="color: #ff7700;font-weight:bold;">in</span> modes
                        stream_media.<span style="color: black;">Main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                      File <span style="color: #483d8b;">&quot;/home/paul/.xbmc/addons/plugin.video.hulu/resources/lib/stream_hulu.py&quot;</span>, line <span style="color: #ff4500;">148</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__init__</span>
                        <span style="color: #008000;">self</span>.<span style="color: black;">queueAD</span><span style="color: black;">&#40;</span>video_id,<span style="color: #ff4500;">2</span>,<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
                      File <span style="color: #483d8b;">&quot;/home/paul/.xbmc/addons/plugin.video.hulu/resources/lib/stream_hulu.py&quot;</span>, line <span style="color: #ff4500;">420</span>, <span style="color: #ff7700;font-weight:bold;">in</span> queueAD
                        u += <span style="color: #483d8b;">'&amp;videoid=&quot;'</span>+<span style="color: #dc143c;">urllib</span>.<span style="color: black;">quote_plus</span><span style="color: black;">&#40;</span>common.<span style="color: black;">args</span>.<span style="color: black;">videoid</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">'&quot;'</span>
                    <span style="color: #008000;">AttributeError</span>: _Info instance has no attribute <span style="color: #483d8b;">'videoid'</span></pre></div></div>

<p>Browsing works just fine, though, so I only browse for videos.</p>
<h3>Next Steps</h3>
<p>I&#8217;m still using a wired USB keyboard and mouse, but I&#8217;m planning to get a home theater friendly wireless keyboard/mouse combo. Something along the lines of a <a href="http://www.amazon.com/Wireless-Keyboard-Built-TouchPad-Pointer/dp/B003UE52ME">Rii Mini Wireless Keyboard</a>.</p>
<p>There are also hundreds of XBMC plugins I haven&#8217;t checked out yet, as well as other ways to customize XBMC.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/qS3OdxZlbiQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2011/12/23/setting-up-a-zotac-zbox-with-xbmc-as-a-home-theater-pc/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2011/12/23/setting-up-a-zotac-zbox-with-xbmc-as-a-home-theater-pc/</feedburner:origLink></item>
		<item>
		<title>Running multiple ruby projects with foreman and subcontractor</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/Mcrqk6OJNs0/</link>
		<comments>http://www.pgrs.net/2011/12/15/running-multiple-ruby-projects-with-foreman-and-subcontractor/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 03:11:50 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22422</guid>
		<description><![CDATA[We have a suite of ruby applications at Braintree. There are many times when we need to run more than one of these apps at the same time. For example, we might need to run our login app in addition to whichever app we are working on. We use foreman as our process launcher, but <a href='http://www.pgrs.net/2011/12/15/running-multiple-ruby-projects-with-foreman-and-subcontractor/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>We have a suite of ruby applications at <a href="http://www.braintreepayments.com">Braintree</a>. There are many times when we need to run more than one of these apps at the same time. For example, we might need to run our login app in addition to whichever app we are working on.</p>
<p>We use <a href="https://github.com/ddollar/foreman">foreman</a> as our process launcher, but foreman does not handle running other projects in other rvm gemsets (and possibly ruby versions). One of my fellow developers, <a href="http://tony.pitluga.com">Tony Pitluga</a>, released a gem called <a href="https://github.com/pitluga/subcontractor">subcontractor</a> that handles these cases.</p>
<p>For example, our Procfile looks like:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">app: rails server
login: subcontract <span style="color:#006600; font-weight:bold;">--</span>rvm <span style="color:#996600;">&quot;--with-rubies rvmrc&quot;</span> <span style="color:#006600; font-weight:bold;">--</span>chdir ..<span style="color:#006600; font-weight:bold;">/</span>login <span style="color:#006600; font-weight:bold;">--</span>signal INT <span style="color:#006600; font-weight:bold;">--</span> rails server <span style="color:#006600; font-weight:bold;">-</span><span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#006666;">4000</span></pre></div></div>

<p>This runs the current app on port 3000 and the login app on port 4000 with a different home folder, ruby and gemset. The login line is roughly equivalent to running <code>cd ../login &#038;&#038; rvm --with-rubies rvmrc exec rails server -p 4000</code> The option <code>--with-rubies rvmrc</code> tells rvm to use the .rvmrc file to load the correct ruby and gemset. If a project doesn&#8217;t have an .rvmrc file, you can specify the ruby version:</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">another_app: subcontract <span style="color:#006600; font-weight:bold;">--</span>rvm ruby<span style="color:#006600; font-weight:bold;">-</span>1.8.7<span style="color:#006600; font-weight:bold;">-</span>p249@another_app <span style="color:#006600; font-weight:bold;">--</span>chdir ..<span style="color:#006600; font-weight:bold;">/</span>another_app <span style="color:#006600; font-weight:bold;">--</span>signal INT <span style="color:#006600; font-weight:bold;">--</span> rails server <span style="color:#006600; font-weight:bold;">-</span><span style="color:#CC0066; font-weight:bold;">p</span> <span style="color:#006666;">4000</span></pre></div></div>

<img src="http://feeds.feedburner.com/~r/pgrs/~4/Mcrqk6OJNs0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2011/12/15/running-multiple-ruby-projects-with-foreman-and-subcontractor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2011/12/15/running-multiple-ruby-projects-with-foreman-and-subcontractor/</feedburner:origLink></item>
		<item>
		<title>speclj-growl 1.0 released</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/bhRRkdwUfRQ/</link>
		<comments>http://www.pgrs.net/2011/12/06/speclj-growl-1-0-released/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 05:46:27 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22389</guid>
		<description><![CDATA[I just released version 1.0 of speclj-growl. This is a plugin for the speclj test framework for clojure which adds Growl popups for each spec run. For those unfamiliar with Growl, it is a notification system for Mac OS X which allows applications to show custom messages in system popups. speclj comes with autotest built <a href='http://www.pgrs.net/2011/12/06/speclj-growl-1-0-released/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I just released version 1.0 of <a href="https://github.com/pgr0ss/speclj-growl">speclj-growl</a>. This is a plugin for the <a href="https://github.com/slagyr/speclj">speclj</a> test framework for clojure which adds <a href="http://growl.info">Growl</a> popups for each spec run. For those unfamiliar with <a href="http://growl.info">Growl</a>, it is a notification system for Mac OS X which allows applications to show custom messages in system popups.</p>
<p><a href="https://github.com/slagyr/speclj">speclj</a> comes with autotest built in. You can start an autotest process which will monitor the filesystem for changes. When tests or code change, the tests will be automatically run again. <a href="https://github.com/pgr0ss/speclj-growl">speclj-growl</a> adds to this process by showing the test results in a growl popup, so you can stay within your editor, glance at the corner of the screen, and see whether your tests passed or failed.</p>
<p>For example, say you have a clojure project using both speclj and speclj-growl (in my example, the speclj-growl project itself). The command <code>lein spec -a -f growl</code> will start autotest <code>(-a)</code> and add the growl formatter <code>(-f growl)</code>:</p>
<pre>
% lein spec -a -f growl

----- Tue Dec 06 23:03:32 CST 2011 -------------------------------------------------------------------
took 0.89041 seconds to determine file statuses.
reloading files:
  /Users/paul/speclj-growl/spec/speclj/report/growl_spec.clj

Growl Reporter
  report-runs
  - growls summary information for no test runs
  - growls a successful run
  - growls an unsuccessful run

Finished in 0.02542 seconds
3 examples, 0 failures
</pre>
<p>A growl message also appears on screen when the specs finish:</p>
<p><a href="http://www.pgrs.net/wp-content/uploads/2011/12/growl_success.png"><img src="http://www.pgrs.net/wp-content/uploads/2011/12/growl_success-300x95.png" alt="" title="growl_success" width="300" height="95" class="alignnone size-medium wp-image-22402" /></a></p>
<p>Now, if I change a spec to intentionally break it, the terminal automatically updates with the new spec output and a new growl message appears:</p>
<pre>
----- Tue Dec 06 23:04:58 CST 2011 -------------------------------------------------------------------
took 0.00414 seconds to determine file statuses.
reloading files:
  /Users/paul/speclj-growl/spec/speclj/report/growl_spec.clj

Growl Reporter
  report-runs  - growls summary information for no test runs (FAILED)
  - growls a successful run
  - growls an unsuccessful run

Failures:

  1) Growl Reporter report-runs growls summary information for no test runs     Expected: <"Failure">
          got: <"Success"> (using =)
     /Users/paul/speclj-growl/spec/speclj/report/growl_spec.clj:28

Finished in 0.00705 seconds
3 examples, 1 failures
</pre>
<p><a href="http://www.pgrs.net/wp-content/uploads/2011/12/growl_failure.png"><img src="http://www.pgrs.net/wp-content/uploads/2011/12/growl_failure-300x95.png" alt="" title="growl_failure" width="300" height="95" class="alignnone size-medium wp-image-22396" /></a></p>
<p>This cycle continues every time the source or spec files change.</p>
<p>Check out the code and installation instructions on github: <a href="https://github.com/pgr0ss/speclj-growl">https://github.com/pgr0ss/speclj-growl</a></p>
<p>Thanks to <a href="https://github.com/slagyr">Micah Martin</a> for both speclj and help with speclj-growl.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/bhRRkdwUfRQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2011/12/06/speclj-growl-1-0-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2011/12/06/speclj-growl-1-0-released/</feedburner:origLink></item>
		<item>
		<title>Using local jars with leiningen</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/IuIGAiBRmlA/</link>
		<comments>http://www.pgrs.net/2011/10/30/using-local-jars-with-leiningen/#comments</comments>
		<pubDate>Sun, 30 Oct 2011 23:18:11 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22374</guid>
		<description><![CDATA[Leiningen uses Maven to make dependency management of clojure projects much simpler. However, if you need to depend on jars that are not in a Maven repository, things get a little more complicated. For example, the Jukebox2 project depends on a bunch of java audio libraries like Jaad that do not live in a Maven <a href='http://www.pgrs.net/2011/10/30/using-local-jars-with-leiningen/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/technomancy/leiningen">Leiningen</a> uses <a href="http://maven.apache.org/">Maven</a> to make dependency management of clojure projects much simpler. However, if you need to depend on jars that are not in a Maven repository, things get a little more complicated.</p>
<p>For example, the <a href="https://github.com/thehammer/jukebox2">Jukebox2</a> project depends on a bunch of java audio libraries like <a href="http://jaadec.sourceforge.net">Jaad</a> that do not live in a Maven repository. We tried checking these jars directly into the lib directory, but leiningen would delete these jars whenever we ran &#8220;lein deps.&#8221;</p>
<p>The solution we came up with was to make a local Maven repository within the project. Then, anyone can clone the project and run &#8220;lein deps&#8221; and get all of the dependencies, including the local jars. Here are the steps:</p>
<ol>
<li>
    Create a directory in the project</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">mkdir</span> maven_repository</pre></div></div>

</li>
<li>
    Add local jars to this repository</p>
<p>    For example, this command adds the jaad-0.8.3.jar file to the maven repository.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">mvn <span style="color: #c20cb9; font-weight: bold;">install</span>:install-file <span style="color: #660033;">-Dfile</span>=jaad-0.8.3.jar <span style="color: #660033;">-DartifactId</span>=jaad <span style="color: #660033;">-Dversion</span>=0.8.3 <span style="color: #660033;">-DgroupId</span>=jaad <span style="color: #660033;">-Dpackaging</span>=jar <span style="color: #660033;">-DlocalRepositoryPath</span>=maven_repository</pre></div></div>

</li>
<li>
    Add the following to project.clj</p>

<div class="wp_syntax"><div class="code"><pre class="clojure" style="font-family:monospace;">:<span style="color: #555;">repositories</span> <span style="color: #66cc66;">&#123;</span><span style="color: #ff0000;">&quot;local&quot;</span> ~<span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">str</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">.</span>toURI <span style="color: #66cc66;">&#40;</span>java<span style="color: #66cc66;">.</span>io<span style="color: #66cc66;">.</span>File<span style="color: #66cc66;">.</span> <span style="color: #ff0000;">&quot;maven_repository&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#125;</span></pre></div></div>

</li>
<li>
    Now a regular lein deps should work</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">lein deps
&nbsp;
Downloading: jaad<span style="color: #000000; font-weight: bold;">/</span>jaad<span style="color: #000000; font-weight: bold;">/</span>0.8.3<span style="color: #000000; font-weight: bold;">/</span>jaad-0.8.3.pom from <span style="color: #7a0874; font-weight: bold;">local</span>
Transferring 0K from <span style="color: #7a0874; font-weight: bold;">local</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>WARNING<span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #000000; font-weight: bold;">***</span> CHECKSUM FAILED - Error retrieving checksum <span style="color: #c20cb9; font-weight: bold;">file</span> <span style="color: #000000; font-weight: bold;">for</span> jaad<span style="color: #000000; font-weight: bold;">/</span>jaad<span style="color: #000000; font-weight: bold;">/</span>0.8.3<span style="color: #000000; font-weight: bold;">/</span>jaad-0.8.3.pom - IGNORING</pre></div></div>

<p>    The warning can be ignored, since the jar will be checked into the project and not downloaded from the internet.
  </li>
</ol>
<p>The final results can be seen in the <a href="https://github.com/thehammer/jukebox2">Jukebox2</a> project.</p>
<p>Thanks to Matjaz on the <a href="http://groups.google.com/group/leiningen/browse_thread/thread/edd90c2285e7a413">Leiningen mailing list</a> for helping me figure out the right syntax for project.clj.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/IuIGAiBRmlA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2011/10/30/using-local-jars-with-leiningen/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2011/10/30/using-local-jars-with-leiningen/</feedburner:origLink></item>
		<item>
		<title>Why I don’t like feature branches</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/_CV2tb-szvg/</link>
		<comments>http://www.pgrs.net/2011/08/29/why-i-dont-like-feature-branches/#comments</comments>
		<pubDate>Tue, 30 Aug 2011 04:15:55 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22336</guid>
		<description><![CDATA[Before I dive into my main arguments, I do believe feature branches make sense for open source development. Generally, developers will work on branches dedicated to given features. This way, when they are done, they can present the branches to the community, get feedback, and make changes. Often times, they will not even have commit <a href='http://www.pgrs.net/2011/08/29/why-i-dont-like-feature-branches/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Before I dive into my main arguments, I do believe feature branches make sense for open source development.  Generally, developers will work on branches dedicated to given features. This way, when they are done, they can present the branches to the community, get feedback, and make changes. Often times, they will not even have commit rights, so a committer will have to take the branch and merge it in. This is much harder if the work was a collection of commits and not a cohesive feature branch. It is also common in open source for features to get rejected, so it&#8217;s helpful if these commits don&#8217;t clutter up the git history. Open source projects also tend to have more sporadic development as opposed to lots of developers all working in the code full time.</p>
<p>The problem is that most work done at companies do not have the same flow. For example, at <a href="http://www.braintreepayments.com">Braintree Payments</a>, we have about six developer pairs all working on different stories, all committing at the same time, and all with commit rights to our project. We trust that if a pair wrote the code, it&#8217;s good and is going into the project. In 99% of cases, if we are working on a feature, it is going to get released.</p>
<p>Given this kind of working environment, here is why I do not like feature branches:</p>
<h3>Feature branches make for nasty commit history</h3>
<p>Feature branching as a practice encourages lots of small commits, often before tests are passing or the code is in a useable state. Since these commits are on a branch, most people think it&#8217;s ok as long as the final merge commit back into master passes all of the tests.</p>
<p>The problem with this practice is that the commit history of the project is now full of broken work and non-passing code. I often use git history to get an idea of why a feature was done, or what other code was changed at the same time. I will &#8220;git blame&#8221; a method name to see when it was added, and what the code looked like at that point. With feature branches, I can no longer trust that commit. It may have been done on a branch, it may have broken half of the tests, and it may have been completely scrapped before the code went into master.</p>
<p>Furthermore, If feature branches are deleted once they are merged into master, where do bug fixes go? On a new feature branch or on master? There will no longer be an easy way to find a list of the commits that went into a feature. If feature branches are not deleted right away, the repository will likely end up with a huge number of branches.</p>
<h3>Feature branches generally have no builds</h3>
<p>We use <a href="http://jenkins-ci.org/">Jenkins</a> to continually test our application. We run numerous builds on every commit, including integration builds that call out to external dependencies.</p>
<p>When we do work on feature branches, we no longer have these builds. Developers will run the main suite of tests before they check in, but no one is going to run the full suite of integration tests on every commit. Furthermore, setting up new builds can be annoying, so we&#8217;re unlikely to do it unless we are going to maintain a branch for a long time.</p>
<h3>Lots of branches become cumbersome</h3>
<p>The lack of builds is one aspect of where lots of branches become cumbersome. Another is user testing. It is common to want the product owner or someone else to take a look at the feature before it&#8217;s done to get feedback. If you have a testing environment, they might want to deploy your code there to take a look (rather than looking over your shoulder on the workstation). But if you have feature branches, then they have to deploy your branch, which means they can no longer test other features at the same time. If they are in the middle of testing another feature that requires specific data, they may not be able to deploy your branch (e.g., if it has different database migrations that would require the database to be rebuilt).</p>
<h3>Feature branches make refactoring harder</h3>
<p>Modern version control tools like git make branching and merging much easier, but they are far from perfect. If we do large refactorings (especially refactorings that take numerous commits), it can become really hard to merge in feature branches. For example, if we rename methods, shift code between classes, or even reorder the methods in a class, the feature branch will likely get tons of conflicts on the merge. Then, someone has to go through each conflict and figure out where the code went. The longer the feature branch lives, the worse the merge becomes.</p>
<p>To take a specific example, say we want to switch our tests from one factory pattern to another. With feature branching, we would create a branch, and spend a few days porting over our tests. Then, when we merge back, we are going to run into conflicts with any tests that were changed by other feature branches. Even worse, while we are porting tests, other developers are still writing tests on their feature branches in the old style.</p>
<p>If we decide to make the test changes on master, but still have feature branches, all of the currently running feature branches have to continually merge from master in order to get the new tests. If they forget, and start modifying tests that have not been ported yet, they are still going to get conflicts when they merge back.</p>
<p>In contrast, if everyone is working in master, the people doing the refactoring can pull, make the changes, and commit frequently. As long as other developers also pull frequently (since everyone is making small, frequent commits), they automatically get the changes.</p>
<h3>My preferences</h3>
<p>Given that I don&#8217;t like feature branches, here is what I prefer:</p>
<p>All developers work in the master branch. When we are ready to release code to production, we merge master into a release branch, which gets some extra regression testing. We then tag from release and deploy the tag.</p>
<p>We use descriptive commit messages to signify what feature we are working on. For example, we use messages like &#8220;#card &#8211; message.&#8221; If we need to see all of the commits for a given feature, we can grep the git history for the card number. Likewise, if &#8220;git blame&#8221; a line of code, you can get back to the original story card and see why the feature was developed.</p>
<p>Commits only get pushed if they pass all of the tests. If a developer wants to make temp commits, that&#8217;s fine as long as they get squashed into a decent commit before pushing. Spike branches are fine for playing around, but the real work should be done on master once the approach is finalized.</p>
<p>On my last few projects, we have used a tool called <a href="https://github.com/pgr0ss/rake_commit">rake_commit</a> to do much of this work for us. It will prompt for a pair, story, and commit message, squash unpushed changes, run &#8220;git pull &#8211;rebase&#8221; (if working in git), run tests, and then push if the tests pass. This tool ensures a clean, linear git history.</p>
<p>For long running features, I prefer <a href="http://paulhammant.com/blog/branch_by_abstraction.html">Branch by Abstraction</a> and feature switches. This way, the features can be developed in master along side other development with the full suite of builds, but not necessarily impact the end user until the work is complete. If we have to release early for some reason (feature X just has to go out today), then we can release without the new features in use.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/_CV2tb-szvg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2011/08/29/why-i-dont-like-feature-branches/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2011/08/29/why-i-dont-like-feature-branches/</feedburner:origLink></item>
		<item>
		<title>Useful unix tricks – part 4</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/qe9a7chOtoo/</link>
		<comments>http://www.pgrs.net/2011/08/16/useful-unix-tricks-part-4/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 16:40:56 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pgrs.net/?p=22302</guid>
		<description><![CDATA[Here is part 4 of my useful unix tricks series: Useful unix tricks Useful unix tricks &#8211; part 2 Useful unix tricks &#8211; part 3 Use mount -o bind to remount a filesystem When you mount a filesystem in linux, anything that was in the existing directory is now hidden and out of reach. For <a href='http://www.pgrs.net/2011/08/16/useful-unix-tricks-part-4/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>Here is part 4 of my useful unix tricks series:</p>
<ul>
<li><a href="http://www.pgrs.net/2007/9/6/useful-unix-tricks">Useful unix tricks</a></li>
<li><a href="http://www.pgrs.net/2007/10/8/useful-unix-tricks-part-2">Useful unix tricks &#8211; part 2</a></li>
<li><a href="http://www.pgrs.net/2009/02/20/useful-unix-tricks-part-3">Useful unix tricks &#8211; part 3</a></li>
</ul>
<h3>Use mount -o bind to remount a filesystem</h3>
<p>When you mount a filesystem in linux, anything that was in the existing directory is now hidden and out of reach. For example:</p>
<pre>% touch /mnt/foo
% ls /mnt
./  ../  foo

% sudo mount /dev/sdb1 /mnt
% ls /mnt
./  ../</pre>
<p>If you want access to those files again, you can remount / using mount -o bind:</p>
<pre>% sudo mkdir /mnt2
% sudo mount -o bind / /mnt2
% ls /mnt2/mnt/foo
./  ../  foo</pre>
<p>This command remounts / under /mnt2, so you can access any file through /mnt2.</p>
<h3>less -R shows colors for control characters</h3>
<p>Programs like Rails write log output with terminal coloring information. If you open these files in less, you&#8217;ll see something like:</p>
<pre>% less development.log

ESC[4;36;1mSQL (0.2ms)ESC[0m   ESC[0;1mSET client_min_messages TO 'panic'ESC[0m
ESC[4;35;1mSQL (0.1ms)ESC[0m   ESC[0mSET client_min_messages TO 'notice'ESC[0m</pre>
<p>If you add the -R flag to less, it tells less to output raw control characters, which will color your terminal:</p>
<pre>% less -R development.log
SQL (0.2ms)   SET client_min_messages TO 'panic'
SQL (0.1ms)   SET client_min_messages TO 'notice'</pre>
<h3>Pressing alt+. will put in the previous command's last argument</h3>
<p>Pressing alt+. (the alt key and period) will drop the argument from the previous command into the terminal. For example:</p>
<pre>% mv foo.txt bar.txt
% cat &lt;press alt and .&gt;

# this becomes
% cat bar.txt
</pre>
<p>This is especially useful for combo commands, such as unstaging and checking out a file in git:</p>
<pre>
% git st
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#       modified:   foo
#

% git reset HEAD foo
Unstaged changes after reset:
M       foo

% git co &lt;alt+.&gt;
</pre>
<p>This is part of the emacs key bindings, and you can read more about them on stack overflow: <a href="http://stackoverflow.com/questions/4009412/bash-first-argument-of-the-previous-command">bash - first argument of the previous command</a></p>
<h3>Show git branch info in the prompt with coloring</h3>
<p>I do a lot of development with git, and I have a lot of different git repositories. It's handy to show git info in the prompt when I cd into a repo directory. At a minimum, I like seeing the current branch I have checked out.</p>
<p>For example, my prompt looks like:</p>
<pre>host:~% cd repo
host:~/repo (master)%
host:~/repo (master)% git co -b some_branch
Switched to a new branch 'some_branch'
host:~/repo (some_branch)%</pre>
<p>In zsh, getting a prompt like this is as simple as adding this to your .zshrc (or .zshenv) file:</p>
<pre>git_prompt_info() {
  ref=$(/usr/local/bin/git symbolic-ref HEAD 2&gt; /dev/null) || return
  echo " (${ref#refs/heads/})"
}

export PROMPT='%m:%~$(git_prompt_info)%# '</pre>
<p>I like colors in my prompt as well, so my .zshenv looks like:</p>
<pre>autoload -U colors
colors

git_prompt_info() {
  ref=$(/usr/local/bin/git symbolic-ref HEAD 2&gt; /dev/null) || return
  echo " (${ref#refs/heads/})"
}

export PROMPT='%{$fg_bold[green]%}%m:%{$fg_bold[blue]%}%~%{$fg_bold[green]%}$(git_prompt_info)%{$reset_color%}%# '</pre>
<p>After I load colors, I can use %{$fg_bold[color_name]} to change the following text to that color.</p>
<h3>Use tmux instead of screen</h3>
<p>For those that aren&#8217;t familiar with <a href="http://www.gnu.org/software/screen/">screen</a> or <a href="http://tmux.sourceforge.net/">tmux</a>, here is the description from the tmux website:</p>
<blockquote><p>
tmux is a terminal multiplexer: it enables a number of terminals (or windows), each running a separate program, to be created, accessed, and controlled from a single screen. tmux may be detached from a screen and continue running in the background, then later reattached.
</p></blockquote>
<p>Being able to detach and reattach is really nice when working on remote servers. You can ssh to a server, start tmux, run a long running process and then detach. Hours later, you can ssh to the server again and reattach to the tmux window. The program continued running after you detached, and you can see the output as if you never left.</p>
<p>tmux is also great for working with others remotely. Everyone can ssh into one server and connect to the same tmux. Then, everyone can see the same file, commands, etc. This is often how we work together on deploys at <a href="http://www.braintreepayments.com/">Braintree Payments</a>.</p>
<p>If you currently use screen, considering switching to tmux. They are very similar (both support everything I mentioned above), but tmux adds a few nice features:</p>
<ol>
<li>
tmux allows you to split the screen vertically so you can have two windows side by side. This is great for working on servers. You can tail the log in one split, and work in the other so you can keep an eye on the logs. Screen lets you split horizontally, but I find vertical splits more useful on widescreen monitors since there is not as much vertical real estate.
</li>
<li>
tmux adds a customizable status bar to the bottom of the terminal with information like which server you are on, the current time, tabs, etc.
</li>
<li>
If different people all connect to the same tmux, it will adjust the viewable area to be the smallest window size. Larger monitors will see a grayed out background filling in the extra space. In contrast, screen might put output where the smaller windows cannot see it.
</li>
</ol>
<h3>column -t will reformat input into columns</h3>
<p>Use column -t when printing tabular output where the columns do not align. For example:</p>
<pre>% print "one two\nthree four"
one two
three four

% print "one two\nthree four" | column -t
one    two
three  four</pre>
<p>I use this all the time with the program pg_lsclusters, which prints out postgresql cluster information:</p>
<pre>% pg_lsclusters
Version Cluster   Port Status Owner    Data directory                     Log file
8.4     backup_main 5433 down   postgres /var/lib/postgresql/8.4/backup_main /var/log/postgresql/postgresql-8.4-backup_main.log
8.4     main      5432 online postgres /var/lib/postgresql/8.4/main       /var/log/postgresql/postgresql-8.4-main.log

% pg_lsclusters | column -t
Version  Cluster      Port  Status  Owner     Data                                 directory                                           Log  file
8.4      backup_main  5433  down    postgres  /var/lib/postgresql/8.4/backup_main  /var/log/postgresql/postgresql-8.4-backup_main.log
8.4      main         5432  online  postgres  /var/lib/postgresql/8.4/main         /var/log/postgresql/postgresql-8.4-main.log</pre>
<h3>ctrl+p and ctrl+n cycle through terminal history</h3>
<p>If you want to run a previous command in terminal, it&#8217;s common to press the up and down arrows to cycle through old commands. You can also use ctrl+p for previous and ctrl+n for next. I prefer these keys since it leaves my hands near the home row rather than having to reach for the arrow keys.</p>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/qe9a7chOtoo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2011/08/16/useful-unix-tricks-part-4/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2011/08/16/useful-unix-tricks-part-4/</feedburner:origLink></item>
		<item>
		<title>Migrated blog from Mephisto to WordPress</title>
		<link>http://feedproxy.google.com/~r/pgrs/~3/YCC4Ll2bOIA/</link>
		<comments>http://www.pgrs.net/2011/07/15/migrated-blog-from-mephisto-to-wordpress/#comments</comments>
		<pubDate>Fri, 15 Jul 2011 21:25:58 +0000</pubDate>
		<dc:creator>Paul Gross</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://wordpress.pgrs.net/?p=22227</guid>
		<description><![CDATA[I used to host my blog with Mephisto. Mephisto is blogging software written in Ruby on Rails, and I really enjoyed it. Unfortunately, the Mephisto project has been abandoned: http://techno-weenie.net/2010/6/23/you-can-let-go-now While it was still running fine for me, I wanted to make changes to my blog, and I figured it was time to move to <a href='http://www.pgrs.net/2011/07/15/migrated-blog-from-mephisto-to-wordpress/' class='excerpt-more'>[...]</a>]]></description>
			<content:encoded><![CDATA[<p>I used to host my blog with <a href="https://github.com/technoweenie/mephisto">Mephisto</a>. Mephisto is blogging software written in Ruby on Rails, and I really enjoyed it. Unfortunately, the Mephisto project has been abandoned: <a href="http://techno-weenie.net/2010/6/23/you-can-let-go-now">http://techno-weenie.net/2010/6/23/you-can-let-go-now</a></p>
<p>While it was still running fine for me, I wanted to make changes to my blog, and I figured it was time to move to software that is still active.</p>
<p>After searching around, I decided to move to <a href="http://wordpress.com">WordPress</a>. My main reasons were:</p>
<ol>
<li>Existing script to migrate all of my posts and comments from Mephisto.</li>
<li>Lots and lots of useful plugins.</li>
<li>Widely used and actively developed.</li>
</ol>
<p>I used a project on github called <a href="https://github.com/iamruinous/mephisto-to-wxr">mephisto-to-wxr</a> to export my Mephisto content as a WordPress export file. The script was a little outdated, so I forked and got it working with with my setup. You can check out my fork at: <a href="https://github.com/pgr0ss/mephisto-to-wxr">https://github.com/pgr0ss/mephisto-to-wxr</a></p>
<p>The syntax highlighting plugin I used with Mephisto required tags around code that looked like:</p>
<pre>
&lt;pre&gt;&lt;code class="ruby"&gt;
&lt;/code&gt;&lt;/pre&gt;
</pre>
<p>In WordPress, I&#8217;m using a plugin called <a href="http://wordpress.org/extend/plugins/wp-syntax/">WP-Syntax</a> which requires tags like:</p>
<pre>
&lt;pre lang="ruby"&gt;
&lt;/pre&gt;
</pre>
<p>To get the required output, I ran the WordPress export (which is xml) through the following sed command:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/&lt;pre&gt;&lt;code class=/&lt;pre lang=/g'</span> pgrs.net.wxr <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">'s/&lt;\/code&gt;&lt;\/pre&gt;/&lt;\/pre&gt;/g'</span> <span style="color: #000000; font-weight: bold;">&gt;</span> pgrs.net.syntax_fix.wxr</pre></div></div>

<p>For those interested, here is my current setup in WordPress:</p>
<ul>
<li><a href="http://aquoid.com/news/themes/suffusion/">Suffusion</a> theme</li>
<li>Plugins:
<ul>
<li><a href="http://wordpress.org/extend/plugins/wordpress-importer/">WordPress Importer</a> to import the exported wxr file</li>
<li><a href="http://wordpress.org/extend/plugins/akismet/">Akismet</a> to prevent comment spam</li>
<li><a href="http://wordpress.org/extend/plugins/about-me-3000/">About Me 3000</a> for the About Me in the upper right</li>
<li><a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP Super Cache</a> for page caching</li>
<li><a href="http://wordpress.org/extend/plugins/wp-syntax/">WP Syntax</a> for syntax highlighting</li>
</ul>
</li>
</ul>
<img src="http://feeds.feedburner.com/~r/pgrs/~4/YCC4Ll2bOIA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.pgrs.net/2011/07/15/migrated-blog-from-mephisto-to-wordpress/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.pgrs.net/2011/07/15/migrated-blog-from-mephisto-to-wordpress/</feedburner:origLink></item>
	</channel>
</rss><!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: basic
Database Caching using disk: basic
Object Caching 540/660 objects using disk: basic

Served from: www.pgrs.net @ 2012-05-24 10:32:02 -->

