0
+=        CouchApps       Blog: http://bradley-holt.com@BradleyHolt (http://twitter.com/BradleyHolt)        bradley.holt@f...
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 withCu...
Trade-OffsNo ad-hoc queries (you can use temporary views, but they’re slow onlarge data sets)Thinking in terms of MapReduce...
MapReduce Views
Mapping Document Titlesfunction(doc) { // JSON object representing a doc to be mapped  if (doc.title) { // make sure this ...
Mapped Document Titles           key                       id            value"Building iPhone Apps with                  ...
Mapping Document Authorsfunction(doc) { // JSON object representing a doc to be mapped  if (doc.authors) { // make sure th...
Mapped Authors        key                    id            value "J. Chris Anderson"   "978-0-596-15589-6"   null   "Jan L...
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:5...
Save New Document$.couch.db("mydb").saveDoc({}, {   success: function(data) {     console.log(data);   }});POST http://loc...
Save Updated Documentvar doc = {   _id: "0a72c9c36bd169818dc97ed18b000aa4",   _rev: "1-967a00dff5e02add41819138abb3284d",  ...
Save Updated Document (cont’d)PUT http://localhost:5984/mydb/0a72c9c36bd169818dc97ed18b000aa4   201 Created{    "ok":true,...
Remove Documentvar doc = {   _id: "0a72c9c36bd169818dc97ed18b000aa4",   _rev: "2-516027e3179a22a22e06874c374e8ef0"};$.couc...
Remove Document (cont’d)DELETE http://localhost:5984/mydb/0a72c9c36bd169818dc97ed18b000aa4?rev=2-516027e3179a22a22e06874c3...
Changes (Long Polling)$.couch.db("mydb").changes().onChange(function(data) {   console.log(data);});GET http://localhost:5...
Why CouchApps?
Bene tsStreamlining of your codebase (no middle tier)Same language on both the client and server (JavaScript)Show and list...
“Ground Computing”Replication lters allow you to replicate relevant data to a userLocal data means faster access to the us...
What about the HTML5Web Storage API?Allows persistent storage of key/value pairsEnjoys signi cant cross-browser supportLac...
Trade-OffsTooling could use some improvementTerminology still unclear—CouchApp can mean many different thingsMust use JavaSc...
UsesMobile applications that require offline accessMulti-device applications (e.g. address book, tasks)Peer-to-peer collabor...
}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>....
“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": "Jaso...
Non-False(and Not a List) ValuesTemplate:{{#user}} <p>Logged in as {{name}}</p>{{/user}}Hash:{ "user": {    "name": "Bradl...
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("Click...
Custom Events<p id="user"></p><script type="text/javascript">$("#user").evently({   login: function(e, user) {     $(this)...
Widgets$("#user").evently({   _init: {     async: function(callback) {        $.couch.session({           success: functio...
jQuery.data Syntactic Sugar// $$ inspired by @wycats: http://yehudakatz.com/2009/04/20/evented-programming-with-jquery/fun...
$$ ExamplesThis:$("#my-node").data("key", "value");Becomes:$$("#my-node").key = "value";This:var value = $("#my-node").dat...
Design Documents
CouchApps & Design DocumentsEach CouchApp is entirely self-contained in one design documentDesign documents live alongside...
What’s in a design document?Can contain:  • View de nitions    • Map functions    • Reduce functions  • Show functions  • ...
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 = {}; … $.co...
evently/comments/_init/query.jsfunction() { var docid = $$("#wiki").docid; return {   view : "recent-comments",   endkey :...
evently/comments/_init/data.jsfunction(view) { var docid = $$("#wiki").docid,   linkup = $$("#wiki").app.require("vendor/c...
evently/comments/_init/mustache.html<h3>Comments about {{title}}</h3><ul> {{#comments}} <li>  <div class="avatar">    {{#g...
evently/comments/_init/mustache.html (cont’d)<form> <label>Comment (w/ <a href="http://github.com/couchapp/couchapp"target...
evently/comments/_init/after.jsfunction() { $(".date").prettyDate();};
evently/comments/_init/selectors/form/submit.jsfunction() { var form = $(this), app = $$(form).app,   f = form.serializeOb...
All Comments, HTML
rewrites.json[    …    {       "from" : "/pages/comments",       "to" : "_list/comments/all-comments",       "query" : {  ...
CouchDB supports virtual hosts via the“vhosts” server con guration section.This lets you route to a rewrite handlerbased o...
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 = req...
templates/comments.html{{>header}}<ul> {{#comments}}  <li>    <span class="date">{{at}}</span>:    {{#by}}{{name}} {{/by}}...
templates/partials/header.html<!DOCTYPE html><html> <head>  <title>{{title}} - {{site_title}}</title>  <link rel="styleshe...
Securityvalidate_doc_update.js
Function De nitionfunction (newDoc, oldDoc, userCtx, secObj) {  var v = require("vendor/couchapp/lib/validate").init(newDo...
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 log...
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     lis...
README.mdGenerated by CouchAppCouchApps are web applications which can be served directly from CouchDB. Thisgives them the...
_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            ...
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...
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/tutor...
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></...
Path Parameters<div id="pro le"></div><script type="text/javascript">$("#pro le").html(<p><a href="#/pro le/Bradley">View ...
Pathbinder,Evently & Mustache<div id="pro le"></div><script type="text/javascript">$("#pro le").evently({   _init: {      ...
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:...
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/quirk...
ReupholsterA simple way to get started developing CouchAppshttp://reupholster.iriscouch.com/reupholster/_design/app/index....
See the CouchApp wiki for a list of CouchApps
Hosting is available through Iris Couchor Cloudant.
CouchDB & CouchApp ResourcesCouchApp Wiki                             Scaling CouchDBhttp://couchapp.org/                 ...
Questions?
Thank You                              Blog: http://bradley-holt.com                       @BradleyHolt (http://twitter.co...
Upcoming SlideShare
Loading in...5
×

OSCON 2011 CouchApps

7,609

Published on

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.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
7,609
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
84
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • \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 &amp;#x201C;user&amp;#x201D; context for the section\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • The recent comments view&amp;#x2019;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&amp;#x2019;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 {{&gt;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 &amp;#x201C;vendor&amp;#x201D; 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
  • Transcript of "OSCON 2011 CouchApps"

    1. 1. += CouchApps Blog: http://bradley-holt.com@BradleyHolt (http://twitter.com/BradleyHolt) bradley.holt@foundline.com
    2. 2. About Me(Bradley Holt)
    3. 3. Co-Founder andTechnical Director
    4. 4. from Vermont Battery Park - Burlington, Vermont by Marty Desilets, on Flickr
    5. 5. Organizer BTV
    6. 6. (Minor) Contributor
    7. 7. Author http://oreilly.com/catalog/9781449303129/ http://oreilly.com/catalog/9781449303433/
    8. 8. Why CouchDB?
    9. 9. CouchDB is a database,web server & application server
    10. 10. 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)
    11. 11. 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)
    12. 12. MapReduce Views
    13. 13. 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 }}
    14. 14. 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
    15. 15. 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 } }}
    16. 16. 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
    17. 17. HTTP APIvia the CouchDB jQuery Pluginhttp://localhost:5984/_utils/script/jquery.couch.js
    18. 18. The same-origin policy dictates that your HTMLand AJAX data (JSON) must be retrieved fromthe same origin.
    19. 19. Create Database$.couch.db("mydb").create({ success: function(data) { console.log(data); }});PUT http://localhost:5984/mydb 201 Created{"ok":true}
    20. 20. 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"}
    21. 21. Save Updated Documentvar doc = { _id: "0a72c9c36bd169818dc97ed18b000aa4", _rev: "1-967a00dff5e02add41819138abb3284d", title: "CouchApps"};$.couch.db("mydb").saveDoc(doc, { success: function(data) { console.log(data); }});
    22. 22. Save Updated Document (cont’d)PUT http://localhost:5984/mydb/0a72c9c36bd169818dc97ed18b000aa4 201 Created{ "ok":true, "id":"0a72c9c36bd169818dc97ed18b000aa4", "rev":"2-516027e3179a22a22e06874c374e8ef0"}
    23. 23. Remove Documentvar doc = { _id: "0a72c9c36bd169818dc97ed18b000aa4", _rev: "2-516027e3179a22a22e06874c374e8ef0"};$.couch.db("mydb").removeDoc(doc, { success: function(data) { console.log(data); }});
    24. 24. Remove Document (cont’d)DELETE http://localhost:5984/mydb/0a72c9c36bd169818dc97ed18b000aa4?rev=2-516027e3179a22a22e06874c374e8ef0 200 OK{ "id":0a72c9c36bd169818dc97ed18b000aa4 "ok":true, "rev":"3-e9a5aa1c486eee23c84fa028bc904991"}
    25. 25. 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}
    26. 26. Why CouchApps?
    27. 27. 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
    28. 28. “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
    29. 29. 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
    30. 30. 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
    31. 31. 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)
    32. 32. }MustacheLogic-Less Templates
    33. 33. Variables
    34. 34. VariablesTemplate:<p>Hello, {{name}}.</p>Hash:{ "name": "Bradley"}Output:<p>Hello, Bradley.</p>
    35. 35. Unescaped VariablesTemplate:<p>Hello, {{{name}}}.</p>Hash:{ "name": "<em>Bradley</em>"}Output:<p>Hello, <em>Bradley</em>.</p>
    36. 36. “Missed” VariablesTemplate:<p>Hello, {{name}}.</p>Hash:{ "role": "admin"}Output:<p>Hello, .</p>
    37. 37. Sections
    38. 38. False ValuesTemplate:<p>Shown.</p>{{#show}}<p>Not shown.</p>{{/show}}Hash:{ "show": false}Output:<p>Shown.</p>
    39. 39. Empty ListsTemplate:<p>Shown.</p>{{#show}}<p>Not shown.</p>{{/show}}Hash:{ "role": "admin"}Output:<p>Shown.</p>
    40. 40. Non-Empty ListsTemplate:{{#users}} <p>{{name}}</p>{{/users}}Hash:{ "users": [ { "name": "Bradley" }, { "name": "Jason" }, ]}Output: <p>Bradley</p> <p>Jason</p>
    41. 41. 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>
    42. 42. Inverted SectionsTemplate:{{^user}} <p>Not logged in</p>{{/user}}Hash:{ "user": false}Output: <p>Not logged in</p>
    43. 43. Evently
    44. 44. Evently is a jQuery plugin forwriting event-based applications
    45. 45. DOM Events<p id="foo"></p><script type="text/javascript">$("#foo").evently({ click: function() { $(this).text("Clicked"); }})</script>
    46. 46. Custom Events<p id="user"></p><script type="text/javascript">$("#user").evently({ login: function(e, user) { $(this).text(user); }})$("#user").trigger("login", "Bradley");</script>
    47. 47. 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; } }});
    48. 48. 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; }};
    49. 49. $$ ExamplesThis:$("#my-node").data("key", "value");Becomes:$$("#my-node").key = "value";This:var value = $("#my-node").data("key");Becomes:var value = $$("#my-node").key;
    50. 50. Design Documents
    51. 51. 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
    52. 52. 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>
    53. 53. Exploring Pages,a CouchApp Wiki
    54. 54. Page Comments, JavaScript
    55. 55. views/recent-comments/map.jsfunction(doc) { if (doc.type == "comment") { emit([doc.topic, doc.at], doc); }};
    56. 56. 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>
    57. 57. evently/comments/_init/query.jsfunction() { var docid = $$("#wiki").docid; return { view : "recent-comments", endkey : [docid, {}], startkey : [docid] };};
    58. 58. 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 } }) }};
    59. 59. 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>
    60. 60. 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>
    61. 61. evently/comments/_init/after.jsfunction() { $(".date").prettyDate();};
    62. 62. 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;};
    63. 63. All Comments, HTML
    64. 64. rewrites.json[ … { "from" : "/pages/comments", "to" : "_list/comments/all-comments", "query" : { "descending" : true, "limit" : 20 } }, …]
    65. 65. 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"}
    66. 66. views/all-comments/map.jsfunction(doc) { if (doc.type == "comment" && doc.comment) { emit(doc.at, doc); }};
    67. 67. 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)); });};
    68. 68. 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>
    69. 69. 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>
    70. 70. Securityvalidate_doc_update.js
    71. 71. Function De nitionfunction (newDoc, oldDoc, userCtx, secObj) { var v = require("vendor/couchapp/lib/validate").init(newDoc, oldDoc, userCtx, secObj); …}
    72. 72. Let Admins Do Anythingif (v.isAdmin()) { return true; // admin can do anything}
    73. 73. Require Login toMake Changesif (!userCtx.name) { // this could be con gurable based on secObj v.unauthorized("please login to make changes");}
    74. 74. Only Let Admins Delete// only admin may deleteif (newDoc._deleted) { v.unauthorized("only admin may delete docs");}
    75. 75. A special _security database propertylets you de ned database admins anddatabase readers
    76. 76. CouchApp Tool (Python)
    77. 77. CouchApps can be built withoutCouchApp tooling—but the toolingmakes things much easier.
    78. 78. Installing CouchApp$ sudo easy_install pip$ sudo pip install couchapp
    79. 79. CouchApp Tooling Basics
    80. 80. Generate a CouchApp$ couchapp generate tutorial2011-06-15 16:25:18 [INFO] /tutorial generated.$ cd tutorial
    81. 81. Generated Files$ tree -FL 1. README.md _attachments/ _id couchapp.json evently/ language lists/ shows/ updates/ vendor/
    82. 82. 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…
    83. 83. _attachments$ tree -F _attachments_attachments index.html style/ main.css1 directory, 2 files
    84. 84. _id$ cat _id_design/tutorial
    85. 85. couchapp.json$ cat couchapp.json{ "name": "Name of your CouchApp", "description": "CouchApp"}
    86. 86. evently$ tree -F eventlyevently items/    _changes/    data.js    mustache.html    query.json profile/ profileReady/ mustache.html selectors/ form/
    87. 87. language$ cat languagejavascript
    88. 88. lists$ tree -F listslists0 directories, 0 files
    89. 89. shows$ tree -F showsshows0 directories, 0 files
    90. 90. updates$ tree -F updatesupdates0 directories, 0 files
    91. 91. vendor$ tree -FL 2 vendorvendor couchapp/ _attachments/ evently/ lib/ metadata.json4 directories, 1 file
    92. 92. views$ tree -F viewsviews recent-items/ map.js1 directory, 1 file
    93. 93. views/recent-items/map.js$ cat views/recent-items/map.jsfunction(doc) { if (doc.created_at) { emit(doc.created_at, doc); }};
    94. 94. Deploying a CouchApp
    95. 95. 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
    96. 96. My New CouchApp
    97. 97. Pathbinder
    98. 98. Pathbinder is a jQuery plugin for triggeringevents based on the path components of aURL hash.
    99. 99. 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>
    100. 100. 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>
    101. 101. 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>
    102. 102. The path name can be stored in a path.txt lewithin an Evently widget in a CouchApp.
    103. 103. Alternative CouchApp Tools
    104. 104. 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
    105. 105. Kanso FrameworkAlso built using Node.jshttp://kansojs.org/
    106. 106. soca“Sammy On Couch App” or “Sittin’ on a Couch App”Command-line tool written in RubyUses Sammy.jshttps://github.com/quirkey/soca
    107. 107. ReupholsterA simple way to get started developing CouchAppshttp://reupholster.iriscouch.com/reupholster/_design/app/index.html
    108. 108. See the CouchApp wiki for a list of CouchApps
    109. 109. Hosting is available through Iris Couchor Cloudant.
    110. 110. 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
    111. 111. Questions?
    112. 112. Thank You Blog: http://bradley-holt.com @BradleyHolt (http://twitter.com/BradleyHolt) bradley.holt@foundline.comCopyright © 2011 Bradley Holt. All rights reserved.
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×