Tonight I continue my exploration of couchapp by attempting to update CouchDB documents. Reading through documentation has left me with the sense that this is rather involved, so I am not sure how far I can get tonight. Only one way to find out!
First up, I copy my recipe show function over to an edit function, removing the textile conversion so that raw textile can be edited:
function(doc, req) {Then some simple form HTML goes into the new
// !json templates.edit
// !json templates._header
// !json templates._footer
// !code vendor/couchapp/template.js
// !code vendor/couchapp/path.js
// !code lib/super_textile.js
var image;
for (var prop in doc._attachments) {
image = prop;
}
return template(templates.edit, {
title: doc.title,
docid: (doc && doc._id),
asset_path: assetPath(),
summary: doc.summary,
instructions: doc.instructions,
image: image,
header: template(templates._header, {}),
footer: template(templates._footer, {})
});
}
templates/edit.html
:<!DOCTYPE html>Easy enough, that gives me this edit screen:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Recipe: <%= title %></title>
<link rel="stylesheet" href="<%= asset_path %>/style/main.css" type="text/css" />
</head>
<body>
<%= header %>
<h1>Editing <%= title %></h1>
<!-- form to create a post -->
<form id="udpate-recipe" action="update.html" method="post">
<p>
<label>Title: <input type="text" id="title" name="title" value="<%= title %>" size="50">
</p>
<p>
<label>Summary:<br>
<textarea name="summary" rows="5" cols="80"><%= summary %></textarea>
</label>
</p>
<p>
<label>Instructions:<br>
<textarea name="instructions" rows="15" cols="80"><%= instructions %></textarea>
</label>
</p>
<p>
<input type="submit" value="Save →"/> <span id="saved" style="display:none;">Saved</span>
</p>
</form>
<img src="../../../../<%= docid %>/<%= image %>" />
<%= footer %>
</body>
</html>
Unfortunately, it is not quite that easy. Clicking the Save button does not work:
Forms in couchapp are not old-fashioned POSTs. They need to perform PUTs, DELETEs and POSTs of JSON data. Web browsers won't do that, so some javascript is needed. Fortunately, couchapp takes care of much of the heavy lifting for me. I add this to the bottom of the edit template:
<script src="<%= asset_path %>/vendor/couchapp/jquery.couchapp.js"></script>I am using a never-gets-old debug through javascript alerts in there—the classics never really go out of style. Actually, that is not so much an example of debugging through alerts as it is an example of using tracer bullets. At least that is what I will tell myself when I try to sleep tonight.
<script type="text/javascript" charset="utf-8">
$.CouchApp(function(app) {
var docid = document.location.pathname.split('/').pop();
app.docForm("form#update-recipe", {
fields: ['title', 'summary', 'instructions'],
template: {type: "Recipe", _id: docid},
beforeSave: function(doc) {
alert("Here!");
},
success: function(res, doc) {
alert("Success!");
}
});
});
</script>
Anyhow...
The two
<script>
tags pull in some necessary javascript (jquery and some couchapp javascript built with jQuery). With that, I can call the $.CouchApp
function to attach RESTful behavior to my form. Specifically, I create a couchapp document form (docForm()
) that will convert the form contents into a JSON document to be PUTted into the DB.The
field
option supplied to docForm()
describes which fields need to be converted from elements into JSON attributes before being PUTted onto the database. The template
attribute describes default fields to be submitted (the '_id' is definitely needed to PUT onto the correct document). Lastly, the beforeSave
and success
callbacks contain my awesome alert()
tracer bullets. Once I have the rest of the code hitting them correctly, I can replace the alerts with code to manipulate the JSON document before PUT, and custom code to handle successful updates.For now, when I submit, I expect to see the
beforeSave
's "Here!" alert, and a JSON document submitted to the CouchDB database. Unfortunately, what I get is Cannot call method 'db' of undefined
at:It turns out that the following lines are very important:
...</body>I had ignored those
<script src="/_utils/script/json2.js"></script>
<script src="/_utils/script/jquery.js?1.2.6"></script>
<script src="/_utils/script/jquery.couch.js?0.8.0"></script>
<script src="<%= asset_path %>/vendor/couchapp/jquery.couchapp.js"></script>
<script type="text/javascript" charset="utf-8">
$.CouchApp(function(app) {
...
_utils
files because I could not find them on the filesystem and just assumed that they were part of sofa. Not so, they are provided by CouchDB itself and, yeah, kinda important.With those in place, when I submit, I do see the
beforeSave()
"Here!" tracer bullet, but find that I am not saving the document because of a 409/Conflict:That actually makes perfect sense—I have not supplied a
_rev
attribute in the PUT document so CouchDB has no way to apply optimistic locking against the save. That should be easy enough to address, but I will leave that until tomorrow (along with getting the remaining recipe document elements into the form).Day #19
No comments:
Post a Comment