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 Mon, 14 Mar 2011 19:54:42 GMT
Patrick,

This sounds like a cleaner approach, since you aren't "extending" the
validate_doc_update responsibilities. Plus, you don't need to send an
intentionally bad request to the database.

Thanks,
Simeon

On Thu, Mar 10, 2011 at 8:32 PM, Patrick Barnes <mrtrick@gmail.com> wrote:
> I suggest using couchapp to store your field meta-info (validation, format,
> etc) in a config/ folder or file, then you can:
>
> a) Include it into your validate_doc_update.js file like:
> function (newDoc, oldDoc, userCtx) {
> // !json config.form
>
> b) Refer to it from elsewhere like:
> (PHP, because that is what I'm using)
> $config = $gateway->get('_design/couchapp')->config->form;
>
> So if you have a bunch of required fields, validation_doc_update can process
> them like:
> for(field in config.form.fields) {
>    ...
>    if (field.required == true && !(field.name in newDoc))
>        throw({forbidden:"Missing required field"});
>    ...
>
> And your application can use them like:
> foreach($config->form->fields as $f) {
>    ...
>    $e = $form->createElement($f->type, $f->name)
>        ...
>        ->setRequired($f->required);
> }
>
> Obviously there's plenty of application-specific design work, but this sort
> of pattern allows you to store lots of validation info in a way that you can
> store it in the db (where it belongs), and still access it within the
> application.
>
> Works for me,
> -Patrick
>
>
> On 10/03/2011 11:00 AM, Simeon F. Willbanks wrote:
>>
>> 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