incubator-couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Simeon F. Willbanks" <sim...@simeons.net>
Subject Re: validate_doc_update responsibilities
Date Thu, 10 Mar 2011 00:00:12 GMT
Justin,

Thank you for the reply and helping me brainstorm a solution. I like
the !code macro idea, but my CouchDB server isn't on the same machine
as my application. They communicate through a network. Could I do
this?

function(newDoc, oldDoc, userCtx) {
 //!code path/to/validate.py
 validate(newDoc, oldDoc, userCtx);
}

path/to/validate.py would be network aware and would return valid JavaScript.

Thanks,
Simeon

On Wed, Mar 9, 2011 at 1:27 PM, Justin Walgran <jwalgran@azavea.com> wrote:
> Simeon,
>
> the !code macro in CouchApp was created so you can DRY up your
> functions in the exact way you want. If you extract your validator,
> you can include it in both your validate_doc_update function and your
> client code. Something like this:
>
> function(newDoc, oldDoc, userCtx) {
>  //!code path/to/validate.js
>  validate(newDoc, oldDoc, userCtx);
> }
>
> // Content of validate.js
> var validate = function(newDoc, oldDoc, userCtx) {
>        var Errors = {count: 0};
>
>        var Message = function(field, type, text) {
>                this.type = type || 'string';
>                this.text = text || field + ' is required';
>                this.required = true;
>        };
>
>        var require = function(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)});
>        };
> }
>
> If you refactor a little further, you could go the next step and
> generate a form from the configuration of the validator without the
> making the extra, intentionally bad request to the server.
>
> Justin
>
>
> On Wed, Mar 9, 2011 at 4:10 PM, Simeon F. Willbanks <simeon@simeons.net> wrote:
>> 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
>>
>

Mime
View raw message