<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Bradley Holt &#187; REST</title>
	<atom:link href="http://bradley-holt.com/tag/rest/feed/" rel="self" type="application/rss+xml" />
	<link>http://bradley-holt.com</link>
	<description></description>
	<lastBuildDate>Fri, 06 Jan 2012 18:57:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Top Five Posts of 2011</title>
		<link>http://bradley-holt.com/2011/12/top-five-posts-of-2011/</link>
		<comments>http://bradley-holt.com/2011/12/top-five-posts-of-2011/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 17:15:32 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[AMQP]]></category>
		<category><![CDATA[CouchApp]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Domain-Driven Design]]></category>
		<category><![CDATA[FOSS]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[Open Standards]]></category>
		<category><![CDATA[OSCON]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[PHP-QAT]]></category>
		<category><![CDATA[Quality Assurance]]></category>
		<category><![CDATA[RabbitMQ]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Scaling]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=1480</guid>
		<description><![CDATA[Continuing a trend started by Cal Evans and then followed by Chris Cornutt, Matthew Turland, and Joe Devon; here are the top five most viewed posts from my blog in 2011. 5. CouchDB and Domain-Driven Design This post covered two topics that are of great interest to me. Document databases like CouchDB have much potential [...]]]></description>
			<content:encoded><![CDATA[<p>Continuing a trend started by <a href="http://blog.calevans.com/2011/12/29/top-three-posts-of-2011/">Cal Evans</a> and then followed by <a href="http://blog.phpdeveloper.org/?p=425">Chris Cornutt</a>, <a href="http://matthewturland.com/2011/12/29/top-10-posts-of-2011/">Matthew Turland</a>, and <a href="http://mysqltalk.wordpress.com/2011/12/30/top-posts-of-2011/">Joe Devon</a>; here are the top five most viewed posts from my blog in 2011.</p>
<h3>5. <a href="http://bradley-holt.com/2011/08/couchdb-and-domain-driven-design/">CouchDB and Domain-Driven Design</a></h3>
<p>This post covered two topics that are of great interest to me. Document databases like CouchDB have much potential when it comes to domain-driven design. The post outlined some techniques for serializing domain objects into CouchDB documents.</p>
<h3>4. <a href="http://bradley-holt.com/2011/07/addressing-the-nosql-criticism/">Addressing the NoSQL Criticism</a></h3>
<p>I heard a lot of NoSQL bashing this year at OSCON. As a result, I decided to write a rebuttal to many of the criticisms that I heard. This post inspired a lively <a href="http://bradley-holt.com/2011/07/addressing-the-nosql-criticism/#comments">comment thread</a>.</p>
<h3>3. <a href="http://bradley-holt.com/2011/07/testing-php-5-4/">Testing PHP 5.4</a></h3>
<p>This was a short post on how to help the <a href="http://qa.php.net/">PHP Quality Assurance Team</a> by running the tests for the latest development version of PHP 5.4. It covered downloading, compiling, and running the tests. Most importantly, it also covered reporting your test results.</p>
<h3>2. <a href="http://bradley-holt.com/2011/07/exploring-rabbitmq-and-php/">Exploring RabbitMQ and PHP</a></h3>
<p>I was exploring the possibility of using RabbitMQ for an upcoming project. I decided to post some notes on my experience getting started with RabbitMQ and integrating it with PHP. I haven&#8217;t ended up using RabbitMQ in production yet, but I&#8217;m confident that I&#8217;ll end up using it at some point.</p>
<h3>1. <a href="http://bradley-holt.com/2011/07/couchdb-jquery-plugin-reference/">CouchDB jQuery Plugin Reference</a></h3>
<p>I had been frustrated by the lack of documentation for the CouchDB jQuery plugin—so decided to write my own. After I wrote the blog post, <a href="http://www.maxogden.com/">Max Ogden</a> pointed me to <a href="http://arandomurl.com/">Dale Harvey</a>‘s <a href="https://github.com/daleharvey/jquery.couch.js-docs">documentation generator for jquery.couch.js</a> and a copy of the generated <a href="http://daleharvey.github.com/jquery.couch.js-docs/symbols/index.html">jQuery CouchDB documentation</a>. Max and Dale are also working on a more flexible jquery.couch2.js.</p>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/12/top-five-posts-of-2011/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Defining a RESTful Framework</title>
		<link>http://bradley-holt.com/2011/08/defining-a-restful-framework/</link>
		<comments>http://bradley-holt.com/2011/08/defining-a-restful-framework/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 17:41:49 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Hypermedia]]></category>
		<category><![CDATA[Open Standards]]></category>
		<category><![CDATA[PHACTOR]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Web Application Frameworks]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=1327</guid>
		<description><![CDATA[Web application frameworks have varying support for the concepts behind Representational State Transfer (REST). Most web application frameworks, if not all, allow you to create &#8220;fully&#8221; RESTful web applications. However, there does not seem to be a focus on explicitly applying RESTful principles. So, here are the key concepts that I&#8217;d like to see addressed: [...]]]></description>
			<content:encoded><![CDATA[<p>Web application frameworks have varying support for the concepts behind <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">Representational State Transfer</a> (REST). Most web application frameworks, if not all, allow you to create &#8220;fully&#8221; RESTful web applications. However, there does not seem to be a focus on explicitly applying RESTful principles. So, here are the key concepts that I&#8217;d like to see addressed:</p>
<ul>
<li>Embrace, and don&#8217;t abstract, the <a href="http://www.w3.org/Protocols/">Hypertext Transfer Protocol</a> (HTTP).</li>
<li>Focus on entities/resources—identified by full Uniform Resource Identifiers (URIs).</li>
<li>Use HTTP methods (<code>GET</code>, <code>POST</code>, <code>PUT</code>, <code>DELETE</code>, <code>OPTIONS</code>, <code>HEAD</code>) to perform operations on entities/resources.</li>
<li>Allow for self-described messages through the use of header fields, such as <code>Accept</code> and <code>Content-Type</code>.</li>
<li>Make <a href="http://www.amundsen.com/hypermedia/">hypermedia</a> controls a core concept (perhaps using <a href="http://amundsen.com/media-types/phactor/">PHACTOR</a> as a starting point), not just a byproduct of rendering.</li>
<li>Think of web applications as <a href="http://en.wikipedia.org/wiki/State_transition_system">state transition systems</a>. Representations of entities/resources are states, and hypermedia controls define the available state transitions.</li>
</ul>
<p>Benefits:</p>
<ul>
<li>Interoperability: Focusing on open standards allows for easier integration with other systems.</li>
<li>Cacheability: Embracing HTTP gives you many caching options, almost for free.</li>
<li>Testability: Self-contained and self-describing messages are very testable.  Decomposing a complex system into states and available state transitions  greatly reduces the complexity of the system and its tests.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/08/defining-a-restful-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CouchDB jQuery Plugin Reference</title>
		<link>http://bradley-holt.com/2011/07/couchdb-jquery-plugin-reference/</link>
		<comments>http://bradley-holt.com/2011/07/couchdb-jquery-plugin-reference/#comments</comments>
		<pubDate>Thu, 14 Jul 2011 22:18:46 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CouchApp]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[HTML5]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=1143</guid>
		<description><![CDATA[I&#8217;ve had a difficult time finding documentation on the CouchDB jQuery plugin that ships with CouchDB. So, I&#8217;ve decided to create my own reference and share it with you. This should cover almost the entire CouchDB API that is available through the version of the plugin that ships with CouchDB 1.1.0. Setup The same-origin policy [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had a difficult time finding documentation on the <a href="https://github.com/apache/couchdb/blob/trunk/share/www/script/jquery.couch.js">CouchDB jQuery plugin</a> that ships with CouchDB. So, I&#8217;ve decided to create my own reference and share it with you. This should cover almost the entire CouchDB API that is available through the version of the plugin that ships with CouchDB 1.1.0.</p>
<h3>Setup</h3>
<p>The <a href="http://www.w3.org/Security/wiki/Same_Origin_Policy">same-origin policy</a> effectively requires that the HTML from which the JavaScript is loaded must be served up from CouchDB (you could instead use a reverse proxy server). This can be done by attaching an HTML document to a CouchDB document. You can do this manually, or through the use of <a href="http://couchapp.org/">CouchApps</a>.</p>
<p>CouchDB ships with several useful JavaScript libraries, including jQuery. Here is an example of an HTML document that takes advantage of CouchDB&#8217;s included JavaScript libraries:</p>
<pre><code class="html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;CouchDB jQuery Examples&lt;/title&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
    &lt;script src="/_utils/script/json2.js"&gt;&lt;/script&gt;
    &lt;script src="/_utils/script/sha1.js"&gt;&lt;/script&gt;
    &lt;script src="/_utils/script/jquery.js?1.4.2"&gt;&lt;/script&gt;
    &lt;script src="/_utils/script/jquery.couch.js?0.11.0"&gt;&lt;/script&gt;
    &lt;script src="/_utils/script/jquery.dialog.js?0.11.0"&gt;&lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>By default, CouchDB will use an empty string as its URL prefix. However, you can configure this before your first API call. For example:</p>
<pre><code class="javascript">$.couch.urlPrefix = "http://localhost:5984";</code></pre>
<p>You will typically not want to change this value since the same-origin policy prevents you from accessing CouchDB databases hosted at a different origin.</p>
<h3>Server API</h3>
<h4>Server Information</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.info({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/ <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "couchdb"="Welcome",
    "version"="1.1.0"
}</code></pre>
<h4>All DBs</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.allDbs({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/_all_dbs <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">[
    "_replicator",
    "_users"
]</code></pre>
<h4>User Signup</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">var userDoc = {
    _id: "org.couchdb.user:bob",
    name: "bob"
};
$.couch.signup(userDoc, "supersecurepassword", {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>PUT</strong> http://localhost:5984/_users/org.couchdb.user%3Abob <strong>201 Created</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok"=true,
    "id"="org.couchdb.user:bob",
    "rev"="1-230dc0625bd3c4aac735846cc152c296"
}</code></pre>
<h4>Login</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.login({
    name: "bob",
    password: "supersecurepassword",
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST</strong> http://localhost:5984/_session <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true,
    "name":"bob",
    "roles":[]
}</code></pre>
<p>This will result in an <code>AuthSession</code> cookie being set and then sent back to the server on subsequent requests, authenticating the user on each request. The session length is 10 minutes by default, but can be set in CouchDB&#8217;s <code>couch_httpd_auth.timeout</code> configuration option.</p>
<h4>Session</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.session({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/_session <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true,
    "userCtx":{
        "name":"bob",
         "roles":[]
    },
    "info":{
        "authentication_db":"_users",
        "authentication_handlers":[
            "oauth",
            "cookie",
            "default"
        ],
        "authenticated":"cookie"
    }
}</code></pre>
<h4>Logout</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.logout({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>DELETE</strong> http://_:_@localhost:5984/_session <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true
}</code></pre>
<p>This will set the <code>AuthSession</code> cookie to an empty string, effectively logging the client out.</p>
<h4>Active Tasks</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.activeTasks({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/_active_tasks <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">[]</code></pre>
<h4>Server Configuration</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.config({
    success: function(data) {
        console.log(data);
    }
}, "uuids", "algorithm");</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/_config/uuids/algorithm <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">"sequential"</code></pre>
<p>The second and third parameters are the <code>section</code> and <code>option</code> parameters, respectively. Omit the <code>option</code> parameter if you&#8217;d like to retrieve the entire section. Omit both the <code>section</code> and <code>option</code> parameters if you&#8217;d like to see the entire server configuration. Add an optional fourth parameter to set the configuration option&#8217;s value, which will result in a <code>PUT</code> request with the value.</p>
<h4>User DB</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.userDb(function(data) {
    console.log(data);
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/_session <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "name"="_users",
    "uri"="../_users/"
}</code></pre>
<p>The URI will be relative to the HTML executing the script.</p>
<h4>New UUID</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">var uuid = $.couch.newUUID();
console.log(uuid);</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/_uuids?count=1 <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">d12ee5ea1df6baa2b06451f44a0156fa</code></pre>
<p>This function takes a <code>count</code> parameter as an optional first parameter. If the <code>count</code> parameter is greater than one, then it will keep a cache of UUIDs that will be returned on subsequent calls, rather than making another request to the server.</p>
<h4>Replicate</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.replicate("mydb", "otherdb", {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
}, {
    create_target: true
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST</strong> http://localhost:5984/_replicate <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true,
    "session_id":"705797bae87456c52f5b76f44fe5f245",
    "source_last_seq":27,
    "replication_id_version":2,
    "history":[
        {
            "session_id":"705797bae87456c52f5b76f44fe5f245",
            "start_time":"Wed, 13 Jul 2011 22:40:09 GMT",
            "end_time":"Wed, 13 Jul 2011 22:40:09 GMT",
            "start_last_seq":0,
            "end_last_seq":27,
            "recorded_seq":27,
            "missing_checked":0,
            "missing_found":14,
            "docs_read":14,
            "docs_written":14,
            "doc_write_failures":0
        }
    ]
}</code></pre>
<h3>Database API</h3>
<h4>Create Database</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").create({
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>PUT</strong> http://localhost:5984/mydb/ <strong>201 Created</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true
}</code></pre>
<h4>Database Info</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").info({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/mydb/ <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "db_name":"mydb",
    "doc_count":0,
    "doc_del_count":0,
    "update_seq":0,
    "purge_seq":0,
    "compact_running":false,
    "disk_size":79,
    "instance_start_time":"1310597000825187",
    "disk_format_version":5,
    "committed_update_seq":0
}</code></pre>
<h4>Save New Document</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">var doc = {};
$.couch.db("mydb").saveDoc(doc, {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST</strong> http://localhost:5984/mydb/ <strong>201 Created</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true,
    "id":"d12ee5ea1df6baa2b06451f44a019ab9",
    "rev":"1-967a00dff5e02add41819138abb3284d"
}</code></pre>
<h4>Open Document</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").openDoc("d12ee5ea1df6baa2b06451f44a019ab9", {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET</strong> http://localhost:5984/mydb/d12ee5ea1df6baa2b06451f44a019ab9 <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "_id":"d12ee5ea1df6baa2b06451f44a019ab9",
    "_rev":"1-967a00dff5e02add41819138abb3284d"
}</code></pre>
<p>Note that the HTTP response includes an <code>Etag</code> HTTP header. If you do a subsequent request for the same document, and your client supports caching and conditional HTTP requests, then an <code>If-None-Match</code> header should be sent using the value from the previous response&#8217;s <code>Etag</code> header. If the document has not been modified, then CouchDB will send a <code>304 Not Modified</code> response and no response body, saving bandwidth and speeding up the response.</p>
<h4>Save Updated Document</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">var doc = {
    _id: "d12ee5ea1df6baa2b06451f44a019ab9",
    _rev: "1-967a00dff5e02add41819138abb3284d",
    foo: "bar"
};
$.couch.db("mydb").saveDoc(doc, {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>PUT </strong>http://localhost:5984/mydb/d12ee5ea1df6baa2b06451f44a019ab9 <strong>201 Created</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true,
    "id":"d12ee5ea1df6baa2b06451f44a019ab9",
    "rev":"2-13839535feb250d3d8290998b8af17c3"
}</code></pre>
<h4>Remove Document</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">var doc = {
    _id: "d12ee5ea1df6baa2b06451f44a019ab9",
    _rev: "2-13839535feb250d3d8290998b8af17c3"
};
$.couch.db("mydb").removeDoc(doc, {
     success: function(data) {
         console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>DELETE </strong>http://localhost:5984/mydb/d12ee5ea1df6baa2b06451f44a019ab9?rev=2-13839535… <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "id":d12ee5ea1df6baa2b06451f44a019ab9
    "ok":true,
    "rev":"3-1f04f977685e1108b4664f70b09c6f65"
}</code></pre>
<h4>Bulk Save</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").bulkSave({"docs": [{}, {}]}, {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST </strong>http://localhost:5984/mydb/_bulk_docs?successStatus=201 <strong>201 Created</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">[
    {
        "id":"d12ee5ea1df6baa2b06451f44a01a0d8",
        "rev":"1-967a00dff5e02add41819138abb3284d"
    },
    {
        "id":"d12ee5ea1df6baa2b06451f44a01a75a",
        "rev":"1-967a00dff5e02add41819138abb3284d"
    }
]</code></pre>
<h4>Bulk Remove</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">var docs = [
    {
        _id: "d12ee5ea1df6baa2b06451f44a01a0d8",
        _rev: "1-967a00dff5e02add41819138abb3284d"
    },
    {
        _id: "d12ee5ea1df6baa2b06451f44a01a75a",
        _rev: "1-967a00dff5e02add41819138abb3284d"
    }
];
$.couch.db("mydb").bulkRemove({"docs": docs}, {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST </strong>http://localhost:5984/mydb/_bulk_docs?successStatus=201 <strong>201 Created</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">[
    {
        "id":"d12ee5ea1df6baa2b06451f44a01a0d8",
        "rev":"2-eec205a9d413992850a6e32678485900"
    },
    {
        "id":"d12ee5ea1df6baa2b06451f44a01a75a",
        "rev":"2-eec205a9d413992850a6e32678485900"
    }
]</code></pre>
<p>This operates almost exactly like the bulk save, but instead sets the <code>deleted</code> flag to <code>true</code> on the documents.</p>
<h4>All Documents</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").allDocs({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET </strong>http://localhost:5984/mydb/_all_docs <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "total_rows":11,
    "offset":0,
    "rows":[
        {
            "id":"_design/default",
            "key":"_design/default",
            "value":{
                "rev":"9-5212dde9da06f1933dbe29811fc380d4"
            }
        },
        {
            "id":"d12ee5ea1df6baa2b06451f44a002cef",
            "key":"d12ee5ea1df6baa2b06451f44a002cef",
            "value":{
                "rev":"1-967a00dff5e02add41819138abb3284d"
            }
        },
        …
    ]
}</code></pre>
<h4>All Design Documents</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").allDesignDocs({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET </strong>
http://localhost:5984/mydb/_all_docs?startkey=%22_design%22&amp;endkey=%22_design0%22 <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "total_rows":11,
    "offset":0,
    "rows":[
        {
            "id":"_design/default",
            "key":"_design/default",
            "value":{
                "rev":"9-5212dde9da06f1933dbe29811fc380d4"
            }
        }
    ]
}</code></pre>
<h4>All Apps</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("tutorial").allApps({
    success: function(data) {
        console.log(data);
    },
    eachApp: function(appName, appPath, ddoc) {
        console.log(appName);
        console.log(appPath);
        console.log(ddoc);
    }
});</code></pre>
<p>Resulting HTTP requests:</p>
<pre><code class="no-highlight"><strong>GET </strong>http://localhost:5984/tutorial/_all_docs?startkey=%22_design%22&amp;endkey=%22_design0%22 <strong>200 OK</strong></code></pre>
<pre><code class="no-highlight"><strong>GET </strong>http://localhost:5984/tutorial/_design/tutorial <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">tutorial</code></pre>
<pre><code class="javascript">/tutorial/_design/tutorial/index.html</code></pre>
<pre><code class="javascript">{
    "_id":"_design/tutorial",
    "_rev":"5-276897ecff6dc272c0b9143aa23e8a2e",
    …
}</code></pre>
<p>This is intended as a convenience to find metadata about CouchApps.</p>
<h4>Query</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">var mapFunction = function(doc) {
    emit();
};
$.couch.db("mydb").query(mapFunction, "_count", "javascript", {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    },
    reduce: false
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST </strong>http://localhost:5984/mydb/_temp_view?reduce=false <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "total_rows":10,
    "offset":0,
    "rows":[
        {
            "id":"d12ee5ea1df6baa2b06451f44a002cef",
            "key":null,
            "value":null
        },
        {
            "id":"d12ee5ea1df6baa2b06451f44a0037b5",
            "key":null,
            "value":null
        },
        {
            "id":"d12ee5ea1df6baa2b06451f44a003b06",
            "key":null,
            "value":null
        },
        …
    ]
}</code></pre>
<p>This creates a temporary view as defined by your map and reduce functions. Temporary views are useful in development, but should be replaced with views permanently saved to design documents for production. Temporary views are slow, especially with a large number of documents.</p>
<h4>View</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").view("default/all", {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    },
    reduce: false
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET </strong>http://localhost:5984/mydb/_design/default/_view/all?reduce=false <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "total_rows":10,
    "offset":0,
    "rows":[
        {
            "id":"d12ee5ea1df6baa2b06451f44a002cef",
            "key":null,
            "value":null
        },
        {
            "id":"d12ee5ea1df6baa2b06451f44a0037b5",
            "key":null,
            "value":null
        },
        {
            "id":"d12ee5ea1df6baa2b06451f44a003b06",
            "key":null,
            "value":null
        },
        …
    ]
}</code></pre>
<h4>List</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").list("default/all", "all", {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    },
    reduce: false
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>GET </strong>http://localhost:5984/mydb/_design/default/_list/all/all?reduce=false <strong>200 OK</strong></code></pre>
<p>The console output will depend on your list&#8217;s behavior.</p>
<h4>Compact</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").compact({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST </strong>http://localhost:5984/mydb/_compact <strong>202 Accepted</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true
}</code></pre>
<h4>View Cleanup</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").viewCleanup({
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST </strong>http://localhost:5984/mydb/_view_cleanup <strong>202 Accepted</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true
}</code></pre>
<h4>Compact View</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").compactView("default", {
    success: function(data) {
        console.log(data);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>POST </strong>http://localhost:5984/mydb/_compact/default <strong>202 Accepted</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true
}</code></pre>
<h4>Changes</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").changes().onChange(function(data) {
    console.log(data);
});</code></pre>
<p>Resulting HTTP requests:</p>
<pre><code class="no-highlight"><strong>GET </strong>http://localhost:5984/mydb/ <strong>200 OK</strong></code></pre>
<pre><code class="no-highlight"><strong>GET </strong>http://localhost:5984/mydb/_changes?heartbeat=10000&amp;feed=longpoll&amp;since=34 <strong>200 OK</strong></code></pre>
<p>This will keep a connection open until changes are detected, and then open up another connection to listen for subsequent changes starting from the next sequence.</p>
<p>Console output when a new document is created:</p>
<pre><code class="javascript">{
    "results":[
        {
            "seq":35,
            "id":"d12ee5ea1df6baa2b06451f44a01b7b5",
            "changes":[
                {
                    "rev":"1-967a00dff5e02add41819138abb3284d"
                }
            ]
        }
    ],
    "last_seq":35
}</code></pre>
<p>This is very powerful feature. It allows you to listen for any changes to documents in the database and immediately respond to those changes.</p>
<h4>Copy Document</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").copyDoc("d12ee5ea1df6baa2b06451f44a01b7b5", {
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
}, {
    beforeSend: function(xhr) {
        xhr.setRequestHeader("Destination", "aNewDocId");
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>COPY </strong>http://localhost:5984/mydb/d12ee5ea1df6baa2b06451f44a01b7b5 <strong>201 Created</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "id":"aNewDocId",
    "rev":"1-967a00dff5e02add41819138abb3284d"
}</code></pre>
<h4>Drop Database</h4>
<p>JavaScript example:</p>
<pre><code class="javascript">$.couch.db("mydb").drop({
    success: function(data) {
        console.log(data);
    },
    error: function(status) {
        console.log(status);
    }
});</code></pre>
<p>Resulting HTTP request:</p>
<pre><code class="no-highlight"><strong>DELETE </strong>http://localhost:5984/mydb/ <strong>200 OK</strong></code></pre>
<p>Console output:</p>
<pre><code class="javascript">{
    "ok":true
}</code></pre>
<p><a href="https://en.oreilly.com/oscon2011/public/regwith/os11rad"><img class="alignleft" style="border: 0pt none;" title="O'Reilly OSCON" src="http://radar.oreilly.com/oscon-code-os11rad.png" border="0" alt="O'Reilly OSCON" width="148" height="160" /></a>I&#8217;ll be <a href="http://www.oscon.com/oscon2011/public/schedule/detail/18958">giving a presentation on CouchApps at OSCON</a> if you want to learn more about building CouchApps. This presentation will be a part of the <a href="http://www.oscon.com/oscon2011/public/schedule/topic/Javascript+&amp;+HTML5">JavaScript and HTML5 track</a>. You can <a href="https://en.oreilly.com/oscon2011/public/regwith/os11rad">save 20% on registration with the code OS11RAD</a>. I&#8217;ll also be presenting a <a href="http://www.oscon.com/oscon2011/public/schedule/detail/18964">tutorial on Learning CouchDB at OSCON Data</a>.</p>
<p>You can also check out my books <a href="http://oreilly.com/catalog/9781449303129/">Writing and Querying MapReduce Views in CouchDB</a> and <a href="http://oreilly.com/catalog/9781449303433/">Scaling CouchDB</a> if you&#8217;re interested in learning more about CouchDB in general.</p>
<p><em>Update (7/15/2011)</em>: <a href="http://www.maxogden.com/">Max Ogden</a> has pointed me to <a href="http://arandomurl.com/">Dale Harvey</a>&#8216;s <a href="https://github.com/daleharvey/jquery.couch.js-docs">documentation generator for jquery.couch.js</a> and a copy of the generated <a href="http://daleharvey.github.com/jquery.couch.js-docs/symbols/index.html">jQuery CouchDB documentation</a>. Max and Dale are also working on a more flexible <a href="https://github.com/maxogden/removalist/blob/master/attachments/script/jquery.couch2.js">jquery.couch2.js</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/07/couchdb-jquery-plugin-reference/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>CouchDB 1.1 Released</title>
		<link>http://bradley-holt.com/2011/06/couchdb-1-1-released/</link>
		<comments>http://bradley-holt.com/2011/06/couchdb-1-1-released/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 21:40:11 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=1107</guid>
		<description><![CDATA[CouchDB 1.1 was released this past Friday. CouchBase has a CouchDB Release 1.1 Feature Guide that provides details on the new features available in CouchDB 1.1. Some of the key new features include: A replicator database that stores replications which are automatically restarted when the server restarts Native SSL support—you can now connect to CouchDB [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://couchdb.apache.org/">CouchDB</a> 1.1 was released this past Friday. CouchBase has a <a href="http://docs.couchbase.org/couchdb-release-1.1/">CouchDB Release 1.1 Feature Guide</a> that provides details on the new features available in CouchDB 1.1. Some of the key new features include:</p>
<ul>
<li>A <a href="http://docs.couchbase.org/couchdb-release-1.1/index.html#couchb-release-1.1-replicatordb">replicator database</a> that stores replications which are automatically restarted when the server restarts</li>
<li><a href="http://docs.couchbase.org/couchdb-release-1.1/index.html#couchdb-release-1.1-ssl">Native SSL support</a>—you can now connect to CouchDB securely without maintaining a separate proxy server that handles SSL</li>
<li><a href="http://docs.couchbase.org/couchdb-release-1.1/index.html#couchdb-release-1.1-httprange">HTTP range requests</a>—this allows for resumable downloads and skippable audio and video streams</li>
<li><a href="http://docs.couchbase.org/couchdb-release-1.1/index.html#couchdb-release-1.1-proxying">HTTP proxying</a>—allows external content to be served from your CouchDB URL</li>
<li><a href="http://docs.couchbase.org/couchdb-release-1.1/index.html#couchdb-release-1.1-commonjs">Map functions now support CommonJS</a>—this allows for reuse of JavaScript code</li>
<li><a href="http://docs.couchbase.org/couchdb-release-1.1/index.html#couchdb-release-1.1-etag">More granular ETags on view responses</a>—this increases the probability of a <code>304 Not Modified</code> response when doing conditional requests</li>
</ul>
<p>See the <a href="http://docs.couchbase.org/couchdb-release-1.1/">CouchDB Release 1.1 Feature Guide</a> for the complete list and more detail.</p>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/06/couchdb-1-1-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scaling CouchDB</title>
		<link>http://bradley-holt.com/2011/03/scaling-couchdb/</link>
		<comments>http://bradley-holt.com/2011/03/scaling-couchdb/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 14:41:55 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[FOSS]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Load Testing]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Scaling]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=1041</guid>
		<description><![CDATA[My latest book, Scaling CouchDB, is now available in ebook format. This is a short book (about 72 pages) and serves as a practical guide to scaling CouchDB and designing a distributed system to meet your capacity needs. Replication, conflict resolution, load balancing, clustering, distributed load testing, and monitoring are covered. The chapters on load [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://oreilly.com/catalog/9781449303433/"><img class="alignright" src="http://covers.oreilly.com/images/0636920018407/cat.gif" border="0" alt="Scaling CouchDB" width="180" height="236" /></a>My latest book, <a href="http://oreilly.com/catalog/9781449303433/">Scaling CouchDB</a>, is now available in ebook format. This is a short book (about 72 pages) and serves as a practical guide to scaling CouchDB and designing a distributed system to meet your capacity needs. Replication, conflict resolution, load balancing, clustering, distributed load testing, and monitoring are covered. The chapters on load balancing (using Apache) and distributed load testing (using Tsung) are broadly applicable, even if you aren&#8217;t a CouchDB user.</p>
<p>If you blog and would like to review <a href="http://oreilly.com/catalog/9781449303433/">Scaling CouchDB</a> or my previous book, <a href="http://oreilly.com/catalog/9781449303129/">Writing and Querying MapReduce Views in CouchDB</a>, then please let me know and I can arrange to have you sent a review copy.</p>
<p><em>Update (3/31/2011)</em>: At the request of a commenter, here is the table of contents:</p>
<ol>
<li>Defining Scaling Goals
<ol>
<li>What is Scalability?</li>
<li>Capacity Planning</li>
<li>The CAP Theorem
<ol>
<li>Consistency</li>
<li>Availability</li>
<li>Partition Tolerance</li>
</ol>
</li>
</ol>
</li>
<li>Tuning and Designing for Scale
<ol>
<li>Performance Tips</li>
<li>Document Design</li>
</ol>
</li>
<li>Replication
<ol>
<li>Filters and Specifying Documents</li>
<li>Conflict Resolution
<ol>
<li>Picking the Same Revision as CouchDB</li>
<li>Picking a Conflicted Revision</li>
<li>Merging Revisions</li>
</ol>
</li>
</ol>
</li>
<li>Load Balancing
<ol>
<li>CouchDB Nodes</li>
<li>Replication Setup</li>
<li>Proxy Server Configuration</li>
<li>Testing</li>
</ol>
</li>
<li>Clustering
<ol>
<li>BigCouch</li>
<li>Lounge</li>
<li>Pillow</li>
</ol>
</li>
<li>Distributed Load Testing
<ol>
<li>Installing Tsung</li>
<li>Configuring Tsung</li>
<li>Running Tsung</li>
<li>Monitoring</li>
<li>Identifying Bottlenecks</li>
<li>Test Configuration</li>
</ol>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/03/scaling-couchdb/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>One Web</title>
		<link>http://bradley-holt.com/2011/03/one-web/</link>
		<comments>http://bradley-holt.com/2011/03/one-web/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 16:41:50 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Best Practices]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Mobile Computing]]></category>
		<category><![CDATA[One Web]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Web Design]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=1027</guid>
		<description><![CDATA[Almost two years ago, Luke Wroblewski first described a trend in web development called mobile first. The basic idea was that web applications should be designed for mobile first, as opposed to designed for the desktop first. Luke provided some compelling reasons for this including the explosive growth of mobile adoption, the fact that mobile [...]]]></description>
			<content:encoded><![CDATA[<p>Almost two years ago, Luke Wroblewski first described a trend in web development called <a href="http://www.lukew.com/ff/entry.asp?933">mobile first</a>. The basic idea was that web applications should be designed for mobile first, as opposed to designed for the desktop first. Luke provided some compelling reasons for this including the explosive growth of mobile adoption, the fact that mobile forces you to focus on key areas of your application, and that mobile extends your capabilities. Today I saw <a href="https://twitter.com/shiflett/status/52391738085605376">this tweet from Chris Shiflett</a>:</p>
<blockquote><p>The Web still trumps the Mobile Web. If you’re making a web app, don’t let “mobile first” lead you astray.</p></blockquote>
<p>Luke&#8217;s original premise is not wrong, but I think many web developers have interpreted &#8220;mobile first&#8221; as &#8220;mobile only&#8221;—often intentionally, sometimes by accident. As Chris pointed out, it&#8217;s easy to let &#8220;mobile first&#8221; lead you astray. My response to Chris was that the goal should be <a href="http://www.w3.org/TR/mobile-bp/#OneWeb"><em>One Web</em></a>, even if &#8220;mobile first&#8221;. &#8220;Mobile only&#8221; should rarely, if ever, be the goal. The concept of One Web is described in the W3C&#8217;s <a href="http://www.w3.org/TR/mobile-bp/">Mobile Web Best Practices 1.0 Basic Guidelines</a>. From the original document:</p>
<blockquote><p>The recommendations in this document are  intended to improve the experience of the Web on mobile devices. While  the recommendations are not specifically addressed at the desktop  browsing experience, it must be understood that they are made in the  context of wishing to work towards &#8220;One Web&#8221;.</p>
<p>As discussed in the Scope document <a href="http://www.w3.org/TR/mobile-bp/#Scope">[Scope]</a>, <em>One Web</em> means making, as far as is reasonable, the same information and  services available to users irrespective of the device they are using.  However, it does not mean that exactly the same information is available  in exactly the same <a href="http://www.w3.org/TR/di-gloss/#def-http-representation">representation</a> across all devices. The context of mobile use, device capability  variations, bandwidth issues and mobile network capabilities all affect  the representation. Furthermore, some services and information are more  suitable for and targeted at particular user contexts (see <a href="http://www.w3.org/TR/mobile-bp/#tc">5.1.1 Thematic Consistency of Resource Identified by a URI</a>).</p></blockquote>
<p>Let&#8217;s not let the web fragment into a &#8220;mobile web&#8221;, a &#8220;desktop web&#8221;, and a &#8220;whatever comes next&#8221; web—there&#8217;s no reason for this. The underlying technology is designed to allow for One Web, as <a href="https://twitter.com/ramsey/status/52393492273561600">Ben Ramsey added</a>:</p>
<blockquote><p>@<a href="http://twitter.com/BradleyHolt">BradleyHolt</a> @<a href="http://twitter.com/shiflett">shiflett</a> This is why we have content types, accept headers, user agent strings, and content negotiation. <img src='http://bradley-holt.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p></blockquote>
<p>If you&#8217;re considering taking a mobile first approach, please consider taking the One Web approach instead. Your main focus can be on mobile to start, but at least deliver <em>something</em> of value that is not dependent on the client being a mobile device. As Ben suggested, use content types, accept headers, user agent strings, and <a href="http://en.wikipedia.org/wiki/Content_negotiation">content negotiation</a> to deliver the best experience based on your user&#8217;s device or browser.</p>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/03/one-web/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CouchDB at New York PHP</title>
		<link>http://bradley-holt.com/2011/02/couchdb-at-new-york-php/</link>
		<comments>http://bradley-holt.com/2011/02/couchdb-at-new-york-php/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 23:06:49 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[MapReduce]]></category>
		<category><![CDATA[NYC]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Scaling]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=971</guid>
		<description><![CDATA[Last night I gave a presentation on CouchDB at the New York PHP User Group. I talked about the basics of CouchDB, its JSON documents, its RESTful API, writing and querying MapReduce views, using CouchDB from within PHP, and scaling. The talk was broadcast and recorded on Ustream. A big thanks to New York PHP [...]]]></description>
			<content:encoded><![CDATA[<p>Last night I gave a presentation on <a href="http://couchdb.apache.org/">CouchDB</a> at the <a href="http://www.nyphp.org/">New York PHP User Group</a>. I talked about the basics of CouchDB, its JSON documents, its RESTful API, writing and querying MapReduce views, using CouchDB from within PHP, and scaling. The talk was broadcast and <a href="http://www.ustream.tv/recorded/12874763">recorded on Ustream</a>.</p>
<p><object id="utv157837" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="480" height="296" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="name" value="utv_n_324875" /><param name="flashvars" value="loc=%2F&amp;autoplay=false&amp;vid=12874763&amp;locale=en_US&amp;hasticket=false&amp;id=12874763&amp;v3=1" /><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.ustream.tv/flash/viewer.swf" /><embed id="utv157837" type="application/x-shockwave-flash" width="480" height="296" src="http://www.ustream.tv/flash/viewer.swf" allowscriptaccess="always" allowfullscreen="true" flashvars="loc=%2F&amp;autoplay=false&amp;vid=12874763&amp;locale=en_US&amp;hasticket=false&amp;id=12874763&amp;v3=1" name="utv_n_324875"></embed></object></p>
<p>A big thanks to New York PHP (especially Hans Zaunere, Daniel Krook, Alan Seiden, and Isaac Foster) for having me as a guest! If you like what you see here then I hope you&#8217;ll consider buying my book, <a href="http://oreilly.com/catalog/9781449303129/">Writing and Querying MapReduce Views in CouchDB</a> or my upcoming book, <a href="http://oreilly.com/catalog/9781449303433/">Scaling CouchDB</a>.</p>
<p><em>Update (2/27/2011)</em>: I&#8217;ve uploaded the <a href="http://www.slideshare.net/bradley.holt/couchdb-at-new-york-php">slides from my talk</a> to SlideShare and used the recorded audio to create a slidecast.</p>
<div id="__ss_7059795" style="width: 425px;"><strong style="display: block; margin: 12px 0 4px;"><a title="CouchDB at New York PHP" href="http://www.slideshare.net/bradley.holt/couchdb-at-new-york-php">CouchDB at New York PHP</a></strong> <object id="__sse7059795" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=couchdb-nyphp-110225122327-phpapp01&amp;stripped_title=couchdb-at-new-york-php&amp;userName=bradley.holt" /><param name="name" value="__sse7059795" /><param name="allowfullscreen" value="true" /><embed id="__sse7059795" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=couchdb-nyphp-110225122327-phpapp01&amp;stripped_title=couchdb-at-new-york-php&amp;userName=bradley.holt" name="__sse7059795" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/">webinars</a> from <a href="http://www.slideshare.net/bradley.holt">Bradley Holt</a></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/02/couchdb-at-new-york-php/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Writing and Querying MapReduce Views in CouchDB</title>
		<link>http://bradley-holt.com/2011/01/writing-and-querying-mapreduce-views-in-couchdb/</link>
		<comments>http://bradley-holt.com/2011/01/writing-and-querying-mapreduce-views-in-couchdb/#comments</comments>
		<pubDate>Mon, 31 Jan 2011 16:43:29 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[FOSS]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=959</guid>
		<description><![CDATA[My first book, Writing and Querying MapReduce Views in CouchDB, has been published by O&#8217;Reilly Media. It is a short and concise ebook with step-by-step instructions and lots of sample code. Most examples are provided both in Futon and using CouchDB&#8217;s RESTful HTTP API (using cURL). In my experience, web developers who are new to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://oreilly.com/catalog/9781449303129/"><img class="alignright" style="border: 0pt none;" src="http://covers.oreilly.com/images/0636920018247/lrg.jpg" border="0" alt="Writing and Querying MapReduce Views in CouchDB: Indexing and Querying Documents" width="352" height="462" /></a>My first book, <a href="http://oreilly.com/catalog/9781449303129/"><em>Writing and Querying MapReduce Views in CouchDB</em></a>, has been published by O&#8217;Reilly Media. It is a short and concise ebook with step-by-step instructions and lots of sample code. Most examples are provided both in Futon and using CouchDB&#8217;s RESTful HTTP API (using cURL).</p>
<p>In my experience, web developers who are new to CouchDB often encounter three main barriers to understanding and using CouchDB. First, its JSON documents. Second, its RESTful HTTP API. Third, its MapReduce views. The first two are fairly straightforward and many web developers already have experience with JSON and RESTful HTTP APIs. Once you understand the benefits of using JSON as a document format and exposing the database through a RESTful HTTP API, then understanding MapReduce views becomes the main barrier.</p>
<p>The goal of this book is to walk readers through both writing MapReduce views and then querying these same views. Both the Map and Reduce steps are explained separately. Several example Map functions are demonstrated and the built-in Reduce functions are covered. There are also discussions about custom Reduce functions and the limitations of MapReduce. There are examples of creating both temporary views and saving views permanently to design documents. Finally, there is a chapter on querying views which talks about range queries, limiting rows, skipping rows, reversing results, exact grouping, group levels, and including the original documents in query results.</p>
<p>P.S. If you are a blogger and would like to review this book, then please ping me and let me know.</p>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2011/01/writing-and-querying-mapreduce-views-in-couchdb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Behind The New VPR Homepage</title>
		<link>http://bradley-holt.com/2010/10/behind-the-new-vpr-homepage/</link>
		<comments>http://bradley-holt.com/2010/10/behind-the-new-vpr-homepage/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 15:09:47 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Atom Syndication Format]]></category>
		<category><![CDATA[ClearBearing]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[FOSS]]></category>
		<category><![CDATA[Found Line]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[Mobile Computing]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[Open Standards]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Public Media]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Vermont]]></category>
		<category><![CDATA[VPR]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=888</guid>
		<description><![CDATA[Found Line had the privilege of designing and developing Vermont Public Radio&#8216;s (VPR) new homepage. VPR&#8217;s Online Manager, Jonathan Butler, wrote a blog post about how the redesigned homepage delivers more content to VPR.net visitors. Here I&#8217;ll talk about the technology behind this new homepage. Atom Syndication Format Most of VPR&#8217;s web content is currently [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://foundline.com/">Found Line</a> had the privilege of designing and developing <a href="http://www.vpr.net/">Vermont Public Radio</a>&#8216;s (VPR) new homepage. VPR&#8217;s Online Manager, Jonathan Butler, wrote a blog post about how the <a href="http://vprblog.blogspot.com/2010/10/new-vprnet-homepage.html">redesigned homepage delivers more content to VPR.net visitors.</a> Here I&#8217;ll talk about the technology behind this new homepage.</p>
<h3>Atom Syndication Format</h3>
<p>Most of VPR&#8217;s web content is currently stored in a proprietary content management system (CMS). The first step was publishing the needed content from the CMS out into an open format. VPR&#8217;s Dan Allen published from the CMS <a href="http://www.atomenabled.org/">Atom</a> feeds of the various content we would need for the new homepage.</p>
<h3>PHP and Zend Framework</h3>
<p>Once we had the needed Atom feeds, we created a <a href="http://framework.zend.com/">Zend Framework</a> web application to import these feeds. Components such as <a href="http://framework.zend.com/manual/en/zend.feed.reader.html">Zend_Feed_Reader</a> made the job easier. The weather data comes from the National Oceanic and Atmospheric Administration&#8217;s (NOAA) National Weather Service&#8217;s <a href="http://www.weather.gov/forecasts/xml/rest.php">National Digital Forecast Database XML/REST Service</a>. The market data comes from the <a href="http://code.google.com/apis/finance/">Google Finance API</a>.</p>
<h3>CouchDB</h3>
<p>All of the data (except for weather, which is pulled directly with a bit of caching) is stored in <a href="http://couchdb.apache.org/">CouchDB</a>. Since we&#8217;re storing documents with varying metadata (i.e. Atom entries) choosing a document-oriented database made a lot of sense. CouchDB&#8217;s map/reduce views make for very efficient queries. Its RESTful HTTP API provides a lot of options for scaling and caching. We&#8217;re caching documents within the Zend Framework application and conditionally requesting these documents from CouchDB with ETags when a cache is available. The current cache is simply file-based but we&#8217;re considering using <a href="http://memcached.org/">Memcached</a> for even better performance. On a related note, the homepage itself also supports conditional HTTP requests.</p>
<h3>Apache and nginx</h3>
<p>We had the pleasure of working with another great Vermont company, <a href="http://www.clearbearing.com/">ClearBearing</a>, on this project. ClearBearing handles the infrastructure layer for <a href="http://www.vpr.net/">VPR.net</a>. The current website was (and still is) served up by <a href="http://httpd.apache.org/">Apache</a>. ClearBearing already had <a href="http://nginx.org/">nginx</a> in place as a reverse proxy to handle caching. Since we weren&#8217;t replacing the entire CMS we needed a way for the existing CMS and this new application to coexist. We decided to host the new application separately (still administered by ClearBearing) and reverse proxy requests for certain URIs (primarily the homepage) to the new application. This provides a clean separation between the new application and the existing CMS while still allowing for them to be hosted on the same domain from an end-user perspective.</p>
<h3>Licensing</h3>
<p>You&#8217;ll notice that all of the standards used are open standards and all of the technologies used are free and open source software. Additionally, all of the code we have written for VPR is licensed to them under the permissive <a href="http://www.opensource.org/licenses/bsd-license.php">New BSD License</a>. This means that VPR is free to use this code however they want, study and modify the code, and redistribute the code as-is or modified. They can do all of this without paying additional licensing fees.</p>
<h3>Design</h3>
<p>While this post is primarily about the technology behind VPR&#8217;s new homepage, I should mention that Found Line&#8217;s <a href="http://foundline.com/people/jason-pelletier">Jason Pelletier</a> designed the new homepage and implemented all of its HTML and CSS. We worked closely with Jonathan Butler and John Van Hoesen, Vice President for News &amp; Programming, to make sure the new design meets the needs of website visitors and the organization.</p>
<h3>Next Steps</h3>
<p>The launch of this new homepage was just one iteration with many more to come. As Jonathan Butler mentioned in his blog post, VPR has plans to further improve online services for their listeners. Look for a redesigned VPR Classical page soon. There are also plans for better mobile access to VPR and VPR Classical programming. Fortunately much of the work that has been done can be leveraged to create additional online services for VPR&#8217;s listeners.</p>
<p>A special thanks for the <a href="http://www.vpr.net/support/">support of VPR&#8217;s listeners</a>—you made this new homepage possible! If you have questions, comments, complaints, or suggestions about the new homepage then please <a href="http://www.vpr.net/inside_vpr/contact_us/?subject=VPR+Homepage">contact VPR</a> directly with your feedback (although you&#8217;re welcome to comment here as well).</p>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2010/10/behind-the-new-vpr-homepage/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CouchDB 1.0 Released</title>
		<link>http://bradley-holt.com/2010/07/couchdb-1-0-released/</link>
		<comments>http://bradley-holt.com/2010/07/couchdb-1-0-released/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 16:25:59 +0000</pubDate>
		<dc:creator>Bradley Holt</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[btvphpug]]></category>
		<category><![CDATA[CouchDB]]></category>
		<category><![CDATA[FOSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[NoSQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[REST]]></category>

		<guid isPermaLink="false">http://bradley-holt.com/?p=704</guid>
		<description><![CDATA[Apache CouchDB is a free/open source RESTful JSON document (NoSQL) database with map reduce views and peer-based replication. Version 1.0 was just released today and is 300% faster than the previous version and includes Microsoft Windows support, an authentication system, and flexible replicator options. The New York Times, ReadWriteEnterprise and InfoWorld covered the release. Couchio [...]]]></description>
			<content:encoded><![CDATA[<p>Apache CouchDB is a free/open source RESTful JSON  document (NoSQL) database with map reduce views and peer-based  replication. Version 1.0 was just released today and is 300% faster than the previous version and  includes Microsoft Windows support, an authentication system, and  flexible replicator options. The <a href="http://www.nytimes.com/external/idg/2010/07/14/14idg-couchdb-nosql-database-ready-for-production-use-58614.html">New York Times</a>, <a rel="nofollow" href="http://www.readwriteweb.com/enterprise/2010/07/nosql-database-couchdb.php">ReadWriteEnterprise</a> and <a rel="nofollow" href="http://www.infoworld.com/d/data-management/couchdb-releases-nosql-database-runs-windows-229">InfoWorld</a> covered the release. Couchio has a <a rel="nofollow" href="http://www.couch.io/">clever release announcement</a> as well. I&#8217;ve been reading up on CouchDB since <a href="http://weierophinney.net/matthew/">Matthew Weier O’Phinney</a>&#8216;s  presentation on Document Databases at the last <a href="http://groups.google.com/group/burlington-vt-php">Burlington,  VT  PHP Users Group</a> meeting and I may have some projects where CouchDB will be a good fit.</p>
]]></content:encoded>
			<wfw:commentRss>http://bradley-holt.com/2010/07/couchdb-1-0-released/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

