I ended yesterday with a couchapp error. When I was editing a new document, I got "The document could not be retrieved: missing":
Not unexpectedly, this turns out to be my fault. A peak in the CouchDB log when I accessed the edit page reveals several successful requests (the page itself, CSS, javascript files, etc.):
[Sun, 21 Feb 2010 15:11:01 GMT] [info] [<0.1509.0>] 127.0.0.1 - - 'GET' /eee/_design/relax/_show/edit 304And finally, the missing document:
[Sun, 21 Feb 2010 15:11:01 GMT] [info] [<0.6869.0>] 127.0.0.1 - - 'GET' /eee/_design/relax/style/main.css 304
[Sun, 21 Feb 2010 15:11:01 GMT] [info] [<0.6869.0>] 127.0.0.1 - - 'GET' /_utils/script/json2.js 304
[Sun, 21 Feb 2010 15:11:02 GMT] [info] [<0.6871.0>] 127.0.0.1 - - 'GET' /_utils/script/jquery.js?1.2.6 304
[Sun, 21 Feb 2010 15:11:02 GMT] [info] [<0.6872.0>] 127.0.0.1 - - 'GET' /_utils/script/jquery.couch.js?0.8.0 304
[Sun, 21 Feb 2010 15:11:02 GMT] [info] [<0.6873.0>] 127.0.0.1 - - 'GET' /eee/_design/relax/vendor/couchapp/jquery.couchapp.js 304
[Sun, 21 Feb 2010 15:11:02 GMT] [info] [<0.6874.0>] 127.0.0.1 - - 'GET' /eee/edit 404The problem here is in the
docForm()
function in the edit.html
template:$.CouchApp(function(app) {I was most likely first exploring edits when I tried calculating the document ID from the URL, which would look something like:
var docid = document.location.pathname.split('/').pop();
app.docForm("form#update-recipe", {
id: docid,
fields: ['title', 'summary', 'instructions'],
template: {type: "Recipe"},
beforeSave: function(doc) {
alert("Here!");
},
success: function(res, doc) {
alert("Success!");
}
});
});
http://localhost:5984/eee/_design/relax/_show/edit/2008-07-12-salmonEditing a new document would have this URL:
http://localhost:5984/eee/_design/relax/_show/editWith my current document ID code, couchapp would end up trying to pull back a document with an ID of "edit". So how to do this the idiomatic couchapp way?
To answer that question, I look at the edit show function and template in sofa. The show function contains a
docid
setting:return template(templates.edit, {In the template, sofa uses this value in the
docid : toJSON((doc && doc._id) || null),
//...
docForm()
function:var postForm = app.docForm("form#new-post", {Ah, that explains the use of
id : <%= docid %>,
...
toJSON()
in the show function. For a document ID of 2008-07-21-spinach
, toJSON
will produce "2008-07-21-spinach"
, which will be a valid value in the docForm()
option hash. If there is no document, the toJSON()
function will produce null
—another valid javascript value.While perusing the sofa code, I also noticed that it never passes in existing form values or uses them in templates like I have been:
<label>Title: <input type="text" id="title" name="title" value="" size="50"><%= title ></label>This is because the
docForm()
method, which is responsible for mapping form values into JSON to be PUT into the CouchDB database, also looks up existing documents and populates form values for editing.So my edit.html template become much simpler:
<!DOCTYPE html>The title, summary, and instructions fields are populated in the web form by couchapp, which uses the
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Recipe Edit</title>
<link rel="stylesheet" href="<%= asset_path %>/style/main.css" type="text/css" />
</head>
<body>
<%= header %>
<h1>Editing</h1>
<!-- form to create a post -->
<form id="update-recipe" action="update.html" method="post">
<p>
<label>Title: <input type="text" id="title" name="title" value="" size="50"></label>
</p>
<p>
<label>Summary:<br>
<textarea name="summary" rows="5" cols="80"></textarea>
</label>
</p>
<p>
<label>Instructions:<br>
<textarea name="instructions" rows="15" cols="80"></textarea>
</label>
</p>
<p>
<input type="submit" value="Save →"/> <span id="saved" style="display:none;">Saved</span>
</p>
</form>
<%= footer %>
</body>
<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) {
app.docForm("form#update-recipe", {
id : <%= docid %>,
fields: ['title', 'summary', 'instructions'],
template: {type: "Recipe"},
beforeSave: function(doc) {
alert("Here!");
},
success: function(res, doc) {
alert("Success!");
}
});
});
</script>
</html>
fields
attribute to drive this. When I view the edit form for the 2008 spinach pie recipe I see all of the fields populated:In the log, I see the request for the edit template itself, and the subsequent request made for the document to be edited:
[Mon, 22 Feb 2010 03:24:26 GMT] [info] [<0.18563.1>] 127.0.0.1 - - 'GET' /eee/_design/relax/_show/edit/2008-07-21-spinach 200And, when I access the edit show function without a document ID, I get an empty edit form:
[Mon, 22 Feb 2010 03:24:27 GMT] [info] [<0.18714.1>] 127.0.0.1 - - 'GET' /eee/2008-07-21-spinach 200
Blank and with no error message this time! Removing code and getting better results—I do believe that I am getting the hang of this.
Day #21
No comments:
Post a Comment