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 17:38:38 GMT
Janez,

Actually, my CouchDB instance is connecting to multiple interfaces of
an application. Those interfaces include PHP and Python scripts. Both
languages are making GET, PUT and DELETE requests to a CouchDB
database. From my example, the database name is 'basic.'  Since I have
multiple languages and machines in play, I am trying to centralize my
model validations. The validate_doc_update function seemed like a
decent candidate for this location since all operations flow through
it. Does this make sense?

Thanks,
Simeon

On Thu, Mar 10, 2011 at 1:21 AM, Janez Štupar <janez.stupar@gmail.com> wrote:
> Whoah Caolan and Simeon,
>
> have you looked into the couchapp.js framework that Chris Anderson has
> built?
>
> It pulls the design document to browser and enables you to run specific code
> from it. Id propose that you look into extending and/or clearing up
> couchapp.
>
> I understand that we might have different scenarios here.
>
> @Caolan: like i said, Couchapp already does that. IMHO it would need some
> clearing up so it doesn't pull exactly the whole design document to client
> (with base64 images and CSS + other attachments) - I hope to do it someday
> if  I come around to it.
>
> @Simeon:What Justin proposed would work in browser, not in middleware. So I
> guess youre using node.js? If so I'd look into improving couchapp.js to work
> on node - then you pull the design doc from couchdb and use same relative
> addresing design document wise.
>
> Kind regards, -Janez
>
> On Thu, Mar 10, 2011 at 9:47 AM, Caolan McMahon <caolan.mcmahon@gmail.com>wrote:
>
>> Simeon,
>>
>> If you're interested in the concept of sharing code, you might want to
>> take a look at Kanso (http://kansojs.org), which aims to bring all the
>> features of the design doc to the client-side. This means you can call
>> validate_doc_update on a document from the browser, or even call list,
>> show and update functions too. Still early days though :)
>>
>> Caolan
>>
>>
>> On 10 March 2011 00:00, Simeon F. Willbanks <simeon@simeons.net> 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