• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
OSCON 2011 CouchApps
 

OSCON 2011 CouchApps

on

  • 6,629 views

CouchApps are web applications built using CouchDB, JavaScript, and HTML5. CouchDB is a document-oriented database that stores JSON documents, has a RESTful HTTP API, and is queried using map/reduce ...

CouchApps are web applications built using CouchDB, JavaScript, and HTML5. CouchDB is a document-oriented database that stores JSON documents, has a RESTful HTTP API, and is queried using map/reduce views. This talk will answer your basic questions about CouchDB, but will focus on building CouchApps and related tools.

Statistics

Views

Total Views
6,629
Views on SlideShare
4,550
Embed Views
2,079

Actions

Likes
2
Downloads
81
Comments
0

11 Embeds 2,079

http://bradley-holt.com 1273
http://css.dzone.com 501
http://www.oscon.com 235
http://lanyrd.com 46
http://feeds.feedburner.com 9
http://architects.dzone.com 8
http://fasoulas.posterous.com 2
http://www.dzone.com 2
http://www.netvibes.com 1
http://posterous.com 1
http://webcache.googleusercontent.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Descends into the “user” context for the section\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • The recent comments view’s map function\n
  • Note that this template gets rendered server-side\n
  • Builds a query to a CouchDB view\n
  • Handles the resultant data from the CouchDB view and prepares it for use by the Mustache template\n
  • The widget’s Mustache template\n
  • \n
  • This is executed after everything else is done\n
  • Creates a selector based on the file path, and calls the function when its namesake event is fired\n
  • \n
  • Rewrites to the comments list, using the all-comments view\n
  • \n
  • \n
  • \n
  • The {{>header}} syntax is for partials\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Update this file to be a README for your CouchApp\n
  • _attachments/index.html will be the starting point for your CouchApp\n_attachments/style/main.css should be self-explanatory\n
  • This is the name of the design document in which your CouchApp will live\n
  • Metadata about the CouchApp\n
  • User made widgets, which an override vendor widgets\n
  • The language used for functions defined within the design document\n
  • Contains CouchDB list functions\n
  • Contains CouchDB show functions\n
  • Contains CouchDB update functions, which can transform arbitrary HTTP requests into document updates\n
  • Third-party “vendor” code that ships with CouchApp as a convenience, as well as some useful Evently widgets\n
  • Function definitions for CouchDB MapReduce views\n
  • \n
  • \n
  • \n
  • Note the account, profile, and items widgets\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

OSCON 2011 CouchApps OSCON 2011 CouchApps Presentation Transcript

  • += CouchApps Blog: http://bradley-holt.com@BradleyHolt (http://twitter.com/BradleyHolt) bradley.holt@foundline.com
  • About Me(Bradley Holt)
  • Co-Founder andTechnical Director
  • from Vermont Battery Park - Burlington, Vermont by Marty Desilets, on Flickr
  • Organizer BTV
  • (Minor) Contributor
  • Author http://oreilly.com/catalog/9781449303129/ http://oreilly.com/catalog/9781449303433/
  • Why CouchDB?
  • CouchDB is a database,web server & application server
  • Bene tsSchema-less “self-contained” JSON documents—no tables, just documentsRESTful HTTP API is simple to integrate withCustom-written MapReduce “views” index your data for fast retrievalMulti-master replication can happen continuously, in any direction, and/orwhenever nodes can connectCan run on anything from a server to a mobile device (CouchDB can be embeddedin Android and iOS apps)
  • Trade-OffsNo ad-hoc queries (you can use temporary views, but they’re slow onlarge data sets)Thinking in terms of MapReduce views can take some time to get used toNo transactions across document boundariesYour data will be “eventually consistent” and con icts can occur (butcan be resolved)
  • MapReduce Views
  • Mapping Document Titlesfunction(doc) { // JSON object representing a doc to be mapped if (doc.title) { // make sure this doc has a title emit(doc.title); // emit the doc’s title as the key }}
  • Mapped Document Titles key id value"Building iPhone Apps with "978-0-596-80579-1" nullHTML, CSS, and JavaScript""CouchDB: The Definitive "978-0-596-15589-6" null Guide""DocBook: The Definitive "978-1-565-92580-9" null Guide" "RESTful Web Services" "978-0-596-52926-0" null
  • Mapping Document Authorsfunction(doc) { // JSON object representing a doc to be mapped if (doc.authors) { // make sure this doc has an authors eld for (var i in doc.authors) { emit(doc.authors[i]); // emit each author as the key } }}
  • Mapped Authors key id value "J. Chris Anderson" "978-0-596-15589-6" null "Jan Lehnardt" "978-0-596-15589-6" null "Jonathan Stark" "978-0-596-80579-1" null "Leonard Muellner" "978-1-565-92580-9" null"Leonard Richardson" "978-0-596-52926-0" null "Noah Slater" "978-0-596-15589-6" null "Norman Walsh" "978-1-565-92580-9" null "Sam Ruby" "978-0-596-52926-0" null
  • HTTP APIvia the CouchDB jQuery Pluginhttp://localhost:5984/_utils/script/jquery.couch.js
  • The same-origin policy dictates that your HTMLand AJAX data (JSON) must be retrieved fromthe same origin.
  • Create Database$.couch.db("mydb").create({ success: function(data) { console.log(data); }});PUT http://localhost:5984/mydb 201 Created{"ok":true}
  • Save New Document$.couch.db("mydb").saveDoc({}, { success: function(data) { console.log(data); }});POST http://localhost:5984/mydb 201 Created{ "ok":true, "id":"e15d848571c8a0352e94738ba6018790", "rev":"1-967a00dff5e02add41819138abb3284d"}
  • Save Updated Documentvar doc = { _id: "0a72c9c36bd169818dc97ed18b000aa4", _rev: "1-967a00dff5e02add41819138abb3284d", title: "CouchApps"};$.couch.db("mydb").saveDoc(doc, { success: function(data) { console.log(data); }});
  • Save Updated Document (cont’d)PUT http://localhost:5984/mydb/0a72c9c36bd169818dc97ed18b000aa4 201 Created{ "ok":true, "id":"0a72c9c36bd169818dc97ed18b000aa4", "rev":"2-516027e3179a22a22e06874c374e8ef0"}
  • Remove Documentvar doc = { _id: "0a72c9c36bd169818dc97ed18b000aa4", _rev: "2-516027e3179a22a22e06874c374e8ef0"};$.couch.db("mydb").removeDoc(doc, { success: function(data) { console.log(data); }});
  • Remove Document (cont’d)DELETE http://localhost:5984/mydb/0a72c9c36bd169818dc97ed18b000aa4?rev=2-516027e3179a22a22e06874c374e8ef0 200 OK{ "id":0a72c9c36bd169818dc97ed18b000aa4 "ok":true, "rev":"3-e9a5aa1c486eee23c84fa028bc904991"}
  • Changes (Long Polling)$.couch.db("mydb").changes().onChange(function(data) { console.log(data);});GET http://localhost:5984/mydb/_changes?heartbeat=10000&feed=longpoll&since=34 200 OK{ "results":[ { "seq":35, "id":"d12ee5ea1df6baa2b06451f44a01b7b5", "changes":[ { "rev":"1-967a00dff5e02add41819138abb3284d" } ] } ], "last_seq":35}
  • Why CouchApps?
  • Bene tsStreamlining of your codebase (no middle tier)Same language on both the client and server (JavaScript)Show and list functions let you generate HTML from within CouchDB, if you don’twant to rely on JavaScriptReplication of both data and code togetherDeploy/replicate an application along with its dataGoes “with the grain” of the web
  • “Ground Computing”Replication lters allow you to replicate relevant data to a userLocal data means faster access to the user’s dataOffline accessData portabilityDecentralization—no need for a canonical databasePotentially gives more control to the user over his or her own data
  • What about the HTML5Web Storage API?Allows persistent storage of key/value pairsEnjoys signi cant cross-browser supportLacks indexed queriesNo replication featuresIndexedDB might help, but is not part of the HTML5 speci cation and is onlyimplemented in a limited number of browsersNeed to look outside the HTML5 speci cation if you need more than just a key/value storage
  • Trade-OffsTooling could use some improvementTerminology still unclear—CouchApp can mean many different thingsMust use JavaScript for the presentation tierPure JavaScript applications may have SEO issuesShow and list functions must be side-effect free, which can be limiting
  • UsesMobile applications that require offline accessMulti-device applications (e.g. address book, tasks)Peer-to-peer collaboration applicationsDistributed social networkingAny application that stores “documents”—CMS, wiki, etc.Geospatial applications (via GeoCouch)
  • }MustacheLogic-Less Templates
  • Variables
  • VariablesTemplate:<p>Hello, {{name}}.</p>Hash:{ "name": "Bradley"}Output:<p>Hello, Bradley.</p>
  • Unescaped VariablesTemplate:<p>Hello, {{{name}}}.</p>Hash:{ "name": "<em>Bradley</em>"}Output:<p>Hello, <em>Bradley</em>.</p>
  • “Missed” VariablesTemplate:<p>Hello, {{name}}.</p>Hash:{ "role": "admin"}Output:<p>Hello, .</p>
  • Sections
  • False ValuesTemplate:<p>Shown.</p>{{#show}}<p>Not shown.</p>{{/show}}Hash:{ "show": false}Output:<p>Shown.</p>
  • Empty ListsTemplate:<p>Shown.</p>{{#show}}<p>Not shown.</p>{{/show}}Hash:{ "role": "admin"}Output:<p>Shown.</p>
  • Non-Empty ListsTemplate:{{#users}} <p>{{name}}</p>{{/users}}Hash:{ "users": [ { "name": "Bradley" }, { "name": "Jason" }, ]}Output: <p>Bradley</p> <p>Jason</p>
  • Non-False(and Not a List) ValuesTemplate:{{#user}} <p>Logged in as {{name}}</p>{{/user}}Hash:{ "user": { "name": "Bradley" }}Output: <p>Logged in as Bradley</p>
  • Inverted SectionsTemplate:{{^user}} <p>Not logged in</p>{{/user}}Hash:{ "user": false}Output: <p>Not logged in</p>
  • Evently
  • Evently is a jQuery plugin forwriting event-based applications
  • DOM Events<p id="foo"></p><script type="text/javascript">$("#foo").evently({ click: function() { $(this).text("Clicked"); }})</script>
  • Custom Events<p id="user"></p><script type="text/javascript">$("#user").evently({ login: function(e, user) { $(this).text(user); }})$("#user").trigger("login", "Bradley");</script>
  • Widgets$("#user").evently({ _init: { async: function(callback) { $.couch.session({ success: function(data) { callback(data); } }); }, mustache: "<span>{{#name}}Logged in as {{name}}{{/name}}{{^name}}Not loggedin{{/name}}</span>", data: function(data) { return data.userCtx; } }});
  • jQuery.data Syntactic Sugar// $$ inspired by @wycats: http://yehudakatz.com/2009/04/20/evented-programming-with-jquery/function $$(node) { var data = $(node).data("$$"); if (data) { return data; } else { data = {}; $(node).data("$$", data); return data; }};
  • $$ ExamplesThis:$("#my-node").data("key", "value");Becomes:$$("#my-node").key = "value";This:var value = $("#my-node").data("key");Becomes:var value = $$("#my-node").key;
  • Design Documents
  • CouchApps & Design DocumentsEach CouchApp is entirely self-contained in one design documentDesign documents live alongside other documents, but have a special namingconvention of _design/<name>A database can have multiple CouchApps (and/or design documents) andCouchDB server can host multiple databases
  • What’s in a design document?Can contain: • View de nitions • Map functions • Reduce functions • Show functions • List functions • Document update handlers • Document update validation functions • Rewrite de nitions • Any other elds you want, just like with any other document • Attachments, just like with any other documentID follows the form of:_design/<design_name>
  • Exploring Pages,a CouchApp Wiki
  • Page Comments, JavaScript
  • views/recent-comments/map.jsfunction(doc) { if (doc.type == "comment") { emit([doc.topic, doc.at], doc); }};
  • Wiring the Evently Widget <div id="comments"></div> …<script type="text/javascript" charset="utf-8"> var opts = {}; … $.couch.app(function(app) { … $$("#wiki").docid = {{docid}}; $$("#wiki").title = {{title_json}}; $("#comments").evently("comments", app); … }, opts);</script>
  • evently/comments/_init/query.jsfunction() { var docid = $$("#wiki").docid; return { view : "recent-comments", endkey : [docid, {}], startkey : [docid] };};
  • evently/comments/_init/data.jsfunction(view) { var docid = $$("#wiki").docid, linkup = $$("#wiki").app.require("vendor/couchapp/lib/linkup"); return { topic : docid, title : $$("#wiki").title, comments : view.rows.map(function(r) { var by = r.value.by || {}; return { gravatar_url : by.gravatar_url, by : by.nickname, at : r.key[1], comment : linkup.encode(r.value.comment) // move to view } }) }};
  • evently/comments/_init/mustache.html<h3>Comments about {{title}}</h3><ul> {{#comments}} <li> <div class="avatar"> {{#gravatar_url}}<img src="{{gravatar_url}}"/>{{/gravatar_url}} <div class="name"> {{by}} </div> </div> <p>{{{comment}}}</p> <em><span class="date">{{at}}</span></em> <div class="clear"></div> </li> {{/comments}}</ul>
  • evently/comments/_init/mustache.html (cont’d)<form> <label>Comment (w/ <a href="http://github.com/couchapp/couchapp"target="_new">linkup</a>*)</label> <br/> <!-- <input type="text" size="60" name="comment"> --> <textarea name="comment" rows="4" cols="60"></textarea> <input type="hidden" name="topic" value="{{topic}}"> <p><input type="submit" value="Save Comment"></p></form>
  • evently/comments/_init/after.jsfunction() { $(".date").prettyDate();};
  • evently/comments/_init/selectors/form/submit.jsfunction() { var form = $(this), app = $$(form).app, f = form.serializeObject(); f.type = "comment"; f.at = new Date(); f.by = $$("#pro le").pro le; app.db.saveDoc(f, { success : function() { $("#comments").trigger("_init"); } }) return false;};
  • All Comments, HTML
  • rewrites.json[ … { "from" : "/pages/comments", "to" : "_list/comments/all-comments", "query" : { "descending" : true, "limit" : 20 } }, …]
  • CouchDB supports virtual hosts via the“vhosts” server con guration section.This lets you route to a rewrite handlerbased on the Host HTTP header.{ "example.com": "/db/_design/tutorial/_rewrite", "www.example.com": "/db/_design/tutorial/_rewrite"}
  • views/all-comments/map.jsfunction(doc) { if (doc.type == "comment" && doc.comment) { emit(doc.at, doc); }};
  • lists/comments.jsfunction() { var row, ddoc = this, mustache = require("vendor/couchapp/lib/mustache"), markdown = require("vendor/couchapp/lib/markdown"), data = { title : "All Comments", site_title : this.couchapp.name, path : "/pages/comments", comments : [] }; provides("html", function() { while (row = getRow()) { log(row); data.comments.push(row.value) } send(mustache.to_html(ddoc.templates.comments, data, ddoc.templates.partials)); });};
  • templates/comments.html{{>header}}<ul> {{#comments}} <li> <span class="date">{{at}}</span>: {{#by}}{{name}} {{/by}} {{^by}}Unknown {{/by}} (<a href="../page/{{topic}}">{{topic}}</a>) <span class="idontknow">{{comment}}</span> </li> {{/comments}}</ul> </body> …</html>
  • templates/partials/header.html<!DOCTYPE html><html> <head> <title>{{title}} - {{site_title}}</title> <link rel="stylesheet" href="../style/base-min.css" type="text/css"> <link rel="stylesheet" href="../style/main.css" type="text/css"> </head> <body> <div id="header"> <div id="account"></div> <h1><a href="../page/index">{{site_title}}</a>: <a href="{{path}}">{{title}}</a></h1> </div> <div id="pro le"></div>
  • Securityvalidate_doc_update.js
  • Function De nitionfunction (newDoc, oldDoc, userCtx, secObj) { var v = require("vendor/couchapp/lib/validate").init(newDoc, oldDoc, userCtx, secObj); …}
  • Let Admins Do Anythingif (v.isAdmin()) { return true; // admin can do anything}
  • Require Login toMake Changesif (!userCtx.name) { // this could be con gurable based on secObj v.unauthorized("please login to make changes");}
  • Only Let Admins Delete// only admin may deleteif (newDoc._deleted) { v.unauthorized("only admin may delete docs");}
  • A special _security database propertylets you de ned database admins anddatabase readers
  • CouchApp Tool (Python)
  • CouchApps can be built withoutCouchApp tooling—but the toolingmakes things much easier.
  • Installing CouchApp$ sudo easy_install pip$ sudo pip install couchapp
  • CouchApp Tooling Basics
  • Generate a CouchApp$ couchapp generate tutorial2011-06-15 16:25:18 [INFO] /tutorial generated.$ cd tutorial
  • Generated Files$ tree -FL 1. README.md _attachments/ _id couchapp.json evently/ language lists/ shows/ updates/ vendor/
  • README.mdGenerated by CouchAppCouchApps are web applications which can be served directly from CouchDB. Thisgives them the nice property of replicating just like any other data stored in CouchDB.They are also simple to write as they can use the built-in jQuery libraries and pluginsthat ship with CouchDB.More info about CouchApps here.Deploying this appAssuming you just cloned this app from git, and you have changed into the app directoryin your terminal, you want to push it to your CouchDB with the CouchApp commandline tool…
  • _attachments$ tree -F _attachments_attachments index.html style/ main.css1 directory, 2 files
  • _id$ cat _id_design/tutorial
  • couchapp.json$ cat couchapp.json{ "name": "Name of your CouchApp", "description": "CouchApp"}
  • evently$ tree -F eventlyevently items/    _changes/    data.js    mustache.html    query.json profile/ profileReady/ mustache.html selectors/ form/
  • language$ cat languagejavascript
  • lists$ tree -F listslists0 directories, 0 files
  • shows$ tree -F showsshows0 directories, 0 files
  • updates$ tree -F updatesupdates0 directories, 0 files
  • vendor$ tree -FL 2 vendorvendor couchapp/ _attachments/ evently/ lib/ metadata.json4 directories, 1 file
  • views$ tree -F viewsviews recent-items/ map.js1 directory, 1 file
  • views/recent-items/map.js$ cat views/recent-items/map.jsfunction(doc) { if (doc.created_at) { emit(doc.created_at, doc); }};
  • Deploying a CouchApp
  • Deploy to Localhost$ couchapp push tutorial2011-06-16 11:16:05 [INFO] Visit your CouchApp here:http://127.0.0.1:5984/tutorial/_design/tutorial/index.html
  • My New CouchApp
  • Pathbinder
  • Pathbinder is a jQuery plugin for triggeringevents based on the path components of aURL hash.
  • Basic Usage<div id="pro le"></div><script type="text/javascript">$("#pro le").html(<p><a href="#/pro le">View Pro le</a></p>);$("#pro le").bind("pro le", function() { $(this).html("<p>Pro le goes here…</p>");});$("#pro le").pathbinder("pro le", "/pro le");</script>
  • Path Parameters<div id="pro le"></div><script type="text/javascript">$("#pro le").html(<p><a href="#/pro le/Bradley">View Bradleys Pro le</a></p>);$("#pro le").bind("pro le", function(e, params) { $(this).html("<p>Viewing " + params.id + "s pro le</p>");});$("#pro le").pathbinder("pro le", "/pro le/:id");</script>
  • Pathbinder,Evently & Mustache<div id="pro le"></div><script type="text/javascript">$("#pro le").evently({ _init: { path: "/", mustache: <p><a href="#/pro le/Bradley">View Pro le</a></p> }, viewPro le: { path: "/pro le/:id", mustache: <p>Viewing {{id}}s pro le; <a href="#/">Back</a></p>, data: function(e, params) { return params; } }});</script>
  • The path name can be stored in a path.txt lewithin an Evently widget in a CouchApp.
  • Alternative CouchApp Tools
  • node.couchapp.jsCommand-line tool, written for Node.jsSimpler folder structureNot compatible with the Python versionLinks: • https://github.com/mikeal/node.couchapp.js • http://japhr.blogspot.com/2010/04/quick-intro-to-nodecouchappjs.html • http://vimeo.com/26147136
  • Kanso FrameworkAlso built using Node.jshttp://kansojs.org/
  • soca“Sammy On Couch App” or “Sittin’ on a Couch App”Command-line tool written in RubyUses Sammy.jshttps://github.com/quirkey/soca
  • ReupholsterA simple way to get started developing CouchAppshttp://reupholster.iriscouch.com/reupholster/_design/app/index.html
  • See the CouchApp wiki for a list of CouchApps
  • Hosting is available through Iris Couchor Cloudant.
  • CouchDB & CouchApp ResourcesCouchApp Wiki Scaling CouchDBhttp://couchapp.org/ by Bradley Holt (O’Reilly) 063-6-920-01840-7CouchDB Wikihttp://wiki.apache.org/couchdb/ Beginning CouchDB by Joe Lennon (Apress)CouchDB: The De nitive Guide 978-1-430-27237-3by J. Chris Anderson, Jan Lehnardt, andNoah Slater (O’Reilly)978-0-596-15589-6Writing and Querying MapReduce Views inCouchDBby Bradley Holt (O’Reilly)978-1-449-30312-9
  • Questions?
  • Thank You Blog: http://bradley-holt.com @BradleyHolt (http://twitter.com/BradleyHolt) bradley.holt@foundline.comCopyright © 2011 Bradley Holt. All rights reserved.