Return-Path: Delivered-To: apmail-couchdb-user-archive@www.apache.org Received: (qmail 84681 invoked from network); 9 Feb 2009 16:05:34 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 9 Feb 2009 16:05:34 -0000 Received: (qmail 60306 invoked by uid 500); 9 Feb 2009 16:05:31 -0000 Delivered-To: apmail-couchdb-user-archive@couchdb.apache.org Received: (qmail 60279 invoked by uid 500); 9 Feb 2009 16:05:31 -0000 Mailing-List: contact user-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: user@couchdb.apache.org Delivered-To: mailing list user@couchdb.apache.org Received: (qmail 60268 invoked by uid 99); 9 Feb 2009 16:05:31 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 09 Feb 2009 08:05:31 -0800 X-ASF-Spam-Status: No, hits=2.2 required=10.0 tests=HTML_MESSAGE,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: domain of jwall@google.com designates 216.239.33.17 as permitted sender) Received: from [216.239.33.17] (HELO smtp-out.google.com) (216.239.33.17) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 09 Feb 2009 16:05:22 +0000 Received: from zps75.corp.google.com (zps75.corp.google.com [172.25.146.75]) by smtp-out.google.com with ESMTP id n19G4xe2011311 for ; Mon, 9 Feb 2009 16:04:59 GMT DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=google.com; s=beta; t=1234195500; bh=duvV/JT0EyUq9uw08V7mPIy5rLc=; h=DomainKey-Signature:MIME-Version:In-Reply-To:References:Date: Message-ID:Subject:From:To:Content-Type:X-GMailtapped-By: X-GMailtapped; b=UVXCNCMlTL2JWKsIStzychnn83uto9va4xhOJwJldQZqnEWjq c/K33PKXRabb70IO4zOOWWs8lCXgSduYjs3IA== DomainKey-Signature: a=rsa-sha1; s=beta; d=google.com; c=nofws; q=dns; h=mime-version:in-reply-to:references:date:message-id:subject:from:to: content-type:x-gmailtapped-by:x-gmailtapped; b=DlTNRh52CHgvkdY6uJPWV3NFIxvF1gNPyU++iq4gF0fiM9u8poRuwHG2yDKxBaV3t vXzqJnoBhp2ZPVNVM3XDA== Received: from rn-out-0910.google.com (rndk57.prod.google.com [10.38.137.57]) by zps75.corp.google.com with ESMTP id n19G4u86017056 for ; Mon, 9 Feb 2009 08:04:56 -0800 Received: by rn-out-0910.google.com with SMTP id k57so1508167rnd.13 for ; Mon, 09 Feb 2009 08:04:56 -0800 (PST) MIME-Version: 1.0 Received: by 10.90.32.14 with SMTP id f14mr532262agf.56.1234195496180; Mon, 09 Feb 2009 08:04:56 -0800 (PST) In-Reply-To: <20090208212554.GB11012@uk.tiscali.com> References: <7d8fb2e90902060110me4c87f3q963083913f6e9666@mail.gmail.com> <20090208212554.GB11012@uk.tiscali.com> Date: Mon, 9 Feb 2009 10:04:55 -0600 Message-ID: <7c40ded80902090804x44cd4f55hd46dae0ff9ae5d12@mail.gmail.com> Subject: Re: Database Disruption From The Couch From: Jeremy Wall To: user@couchdb.apache.org Content-Type: multipart/alternative; boundary=0016e64f90e8221bc104627e8837 X-GMailtapped-By: 172.25.146.75 X-GMailtapped: jwall X-Virus-Checked: Checked by ClamAV on apache.org --0016e64f90e8221bc104627e8837 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On Sun, Feb 8, 2009 at 3:25 PM, Brian Candler wrote: > On Fri, Feb 06, 2009 at 10:10:29AM +0100, Andrea Schiavini wrote: > > Daniel, I've read your post, and it is definitely interesting. However I > > don't agree with you, when you say that CouchDB makes Rails obsolete. > Rails > > is not only ActiveRecord, it's a model-view-controller framework that > helps > > hugely during the development of big applications. The target of Rails is > > not to merely interact with the db, but to provide a good framework to > > handle a complex application that *also* interacts with a DB. > > I have been working through some ideas related to this over the weekend and > playing with some code. I have a few points which I'd like to raise for > discussion. > > (1) Personally, I'm not yet ready to move all view generation into the > browser (Futon-like), i.e. where Javascript fetches the JSON, reformats as > HTML, and submits back as JSON. In any case, supporting browsers without > Javascript is still a useful capability. > > So for now at least, I still need a layer which will build HTML from a > document, and allow document create/update via form POST. > > (2) I need an application logic layer, which enforces business rules. > > Whilst couchdb may be gaining some features which could be used for 1 and 2 > (_show and _action?) I don't think that Couchdb is necessarily the right > place to put this logic. In particular, I don't want to write lots of > application logic in Javascript, especially without a decent testing > framework which is independent of any browser and of Java. Just wanted to plug Test.TAP here. We use it on the Joose project and it's completely environment agnostic. We test joose in .NET, Rhino and all browsers using it. So the testing framework might just be there for you. http://code.google.com/p/test-tap/ I built it specifically because I wanted something that didn't need a browser to work. Also Joose makes building application logic a little bit easier if you like Meta-Object programming styles. > > > Put another way: document *storage/replication* and application > *processing* > of documents can (and in many cases probably should) remain separate. > Couchapps remain an interesting idea however. > > (3) I do like the idea of non-HTML clients being able to read and submit > native JSON. This gives an external API, and also a possible migration > route > to moving more functionality into the browser and/or the couchdb server in > future. Potentially, many of these requests can be proxied straight through > to couchdb. > > So I've been thinking about the impedence mismatch between Rails-style > applications and couchdb. > > An important issue here is what the URL scheme should look like. Couchdb > has > a single flat space for all documents; Rails and co. tend to break up > resources into /resourcetype/id (where 'resourcetype' really is a > controller > class). For HTML interaction we need the usual bundle of > > Collection actions: list, new, create > Member actions: show, edit, update, destroy > > So if you treat couchdb as a flat pool of documents, you might end up with > > /876384763284718 having {"type":"Post"} -- show post > /129837823746876 having {"type":"Comment"} -- show comment > /_new?type=Post > /_new?type=Comment > > This means that the application layer has to fetch the named document, > *then* analyse what type it has, before dispatching to the appropriate > controller/view logic. > > An alternative I have been exploring is to combine the class and the ID > into > the doc_id, separated by space (e.g. "Post 1234", "Comment 9999"). These > could be either user-assigned meaningful IDs, or random uuids; it doesn't > really make much difference. So you might have: > > GET /Post%201234 -- show > GET /Post%201234/_edit > PUT /Post%201234 > DELETE /Post%201234 > GET /Post -- index collection > GET /Post/_new > POST /Post/_create > > (Aside: this implies that attachment names cannot start with underscore, as > I'm using them for member actions like _edit. Also, I'd be interested to > know what URLs couchapps like sofa use for these actions) > > Some useful side effects of this are: > - browsing in Futon becomes a lot more useful; > - belongs-to links can display useful information (comment belongs-to > Post 1234) without necessarily having to retrieve the other document. > > Anyway, I have started writing some Ruby code to try out this pattern: > > http://pobox.com/~b.candler/software/couchdb/miniblog.rb > > [WARNING: extremely rough code!! You also need to install > public/javascripts/jquery.js if you want to be able to add/remove tags] > > This was an interesting learning experience. For example, I found that even > the 'bare metal' couchrest was too thick: it didn't let me pass on raw > JSON. > So I just used sinatra and rest-client directly. > > I found I missed certain helpers, such as Javascript ones. But I think it > shows that this sort of 'thin middleware' approach could be workable, > perhaps still using Rails for its richer view generation capabilities. > > I didn't (yet) miss having true "model" classes, although I have not > started > to work on doing server-side validation. > > Some of the actions turned out to be extremely simple though: e.g. > > get '/Post' do > # TODO: pagination > @posts = Db.get_docs("_all_docs", :startkey=>"Post ", :endkey=>"Post!") > haml :post_index > end > > (4) Error handling: for Javascript user interfaces, if they are going to > rely on the JSON response for failed 'model' validation, then the JSON > error > format needs to be carefully described and sufficiently detailled that the > front-end can display meaningful messages to the user, e.g. which > particular > fields are invalid and why. This would apply for Javascript front-ends > talking to Rails-like middleware, and also talking directly to couchdb > should the validation end up in there (as it seems is soon going to be > possible). > > This is something that it would be helpful to standardise, as it may make > it > easier to move the validation into couchdb later. That is, I'm quite happy > with the idea of couchdb providing the 'model' part of MVC which 'models' > normally provide in Rails. > > (5) Without a schema and without migrations, apps are going to have to be > more robust against coming across member data of the 'wrong' type (e.g. > expecting post.tags to be an array, and finding a string). In an ORM, > perhaps the expected type could be declared, and either ignoring it or > making an automatic cast if the data is of the wrong type. > > Map-reduce functions are also going to have to be robust to data of the > 'wrong' type being present. > > I discovered this when I found my post/tags structure was setting > "tags":"foo" instead of "tags":["foo"] when a single tag was entered in the > web page - this was an issue with sinatra, see > > http://groups.google.com/group/sinatrarb/browse_thread/thread/4790a956bb3242eb > > (6) I want to "think" in couchdb and to write my application in terms of > couchdb native structures, like map/reduce views which I have hand-designed > to work how I want, rather than use an abstraction layer which forces its > own particular way of working. > > The abstraction layers I have looked at so far don't allow me to work how I > want - such as embedding the class and ID into the doc_id as described > above, or handling has-many collections using specially collated views > where > the parent is immediately followed by all its children. > > Oh well, that's just a bit of a brain dump. Maybe looking through the code > I > linked to above will make more sense of it, at least for Ruby people. > > Regards, > > Brian. > --0016e64f90e8221bc104627e8837--