>From the 'CouchDB The Definitive Guide', "CouchDB uses the
validate_doc_update function to prevent invalid or unauthorized
document updates from proceeding." This clearly defines the
validate_doc_update function's responsibility. That said, can we
extend this responsibility a bit? I'd rather not redefine valid
document attributes in my external application since
validate_doc_update is already doing the work (DRY). Maybe the
application can query the validate_doc_update function for the exact
attributes of a valid document. Here is a proof of concept
validate_doc_update function.
function(newDoc, oldDoc, userCtx) {
Errors = {count: 0};
function Message(field, type, text) {
this.type = type || 'string';
this.text = text || field + ' is required';
this.required = true;
};
function require(field, type, text) {
if (!newDoc[field]) {
Errors[field] = new Message(field, type, text);
Errors.count += 1;
};
};
if (newDoc.type == 'post') {
require('title');
require('created_at', 'datetime');
require('body');
require('author');
};
if (newDoc.type == 'comment') {
require('name');
require('created_at', 'datetime');
require('comment', 'string', 'You may not leave an empty comment');
};
if (Errors.count > 0) {
throw({forbidden: JSON.stringify(Errors)});
};
}
In my application, before putting a new document or building a
document input UI (web form), I can "query" the validate_doc_update
function like so:
$ curl -X PUT couchdb:5984/basic/a1a0d5f1e202b48e5bc55f616d0021ff -d
'{"type":"post"}'
{"error":"forbidden","reason":"{\"count\":4,\"title\":{\"type\":\"string\",\"text\":\"title
is
required\",\"required\":true},\"created_at\":{\"type\":\"datetime\",\"text\":\"created_at
is required\",\"required\":true},\"body\":{\"type\":\"string\",\"text\":\"body
is
required\",\"required\":true},\"author\":{\"type\":\"string\",\"text\":\"author
is required\",\"required\":true}}"}
>From the response, I can decode the JSON object's reason property to a
useful array.
array
'count' => int 4
'title' =>
array
'type' => string 'string' (length=6)
'text' => string 'title is required' (length=17)
'required' => boolean true
'created_at' =>
array
'type' => string 'datetime' (length=8)
'text' => string 'created_at is required' (length=22)
'required' => boolean true
'body' =>
array
'type' => string 'string' (length=6)
'text' => string 'body is required' (length=16)
'required' => boolean true
'author' =>
array
'type' => string 'string' (length=6)
'text' => string 'author is required' (length=18)
'required' => boolean true
>From this array, I can build the input UI or validate the new document
before putting.
To reiterate, I am trying to DRY up the validation
rules/responsibilities by defining them in one spot. This proof of
concept uses the validate_doc_update function in CouchDB. The
validate_doc_update function is now responsible for preventing invalid
documents from being PUT to CouchDB, and it can respond to application
queries for what constitutes a valid document.
So, is this a bad idea? Is there a more idiomatic way to accomplish this goal?
Thanks,
Simeon