[Lift 2.3] lift-couchdb not setting a record's id property on save anymore

38 views
Skip to first unread message

Hristo Deshev

unread,
Apr 6, 2011, 2:34:29 PM4/6/11
to lif...@googlegroups.com
Hi everyone,

I've been trying to upgrade my app from Lift 2.2 to Lift 2.3 and I've been seeing some failures in my test suite.  Here's what I found so far.

I'm using lift-couchdb to save a bunch of documents to well... CouchDB. My code works in the following way:

  1. It creates a record object.
  2. It saves it to the db using the meta "save" method
  3. It then gets the newly-saved document id via the record.id property that has been populated by the "save" method.
Here's some code that looks mine:

val r = TestRecordMeta.createRecord
r.text("blah")
TestRecordMeta.save(r)

println("text after save: " + r.text)
println("id after save: " + r.id.is)

println("Loading saved document...")
val loaded = TestRecordMeta.fetch(r.id.is.get).open_!
println("text after load: " + loaded.text.toString)

The above works just fine with Lift 2.2. After upgrading to Lift 2.3 the id property remains set to None after the call to "save". Is that expected? Can I obtain the document id in some other way? And, of course, am I doing something wrong?

I have put up a reproduction project on github: https://github.com/hdeshev/lift-couchdb-id. It is set to use Lift 2.3. To quickly switch to Lift 2.2, edit project/build/Project.scala and change the liftVersion variable. Then ask sbt to reload, update, and run.

Any help is much appreciated.

Hristo

Hristo Deshev

unread,
Apr 7, 2011, 12:20:01 PM4/7/11
to lif...@googlegroups.com
I think I found what's causing this!

I overrode the "hell" out of the default Database implementation to get to the guts of the code parsing the JSON response. That's how I found the DatabaseHelpers.handleUpdateResult method which looks like this:

def handleUpdateResult(original: JObject)(json: JValue): Box[JObject] =
  for {
    obj <- Full(json).asA[JObject] ?~ ("update result is not a JObject: " + json)
    ok  <- Full(json \ "ok" ).asA[JField].map(_.value).asA[JBool].filter(_.value) ?~ ("ok not present in reply or not true: "+json)
    id  <- Full(json \ "id" ).asA[JField].map(_.value).asA[JString].map(_.s)    ?~ ("id not present or not a string: " + json)
    rev <- Full(json \ "rev").asA[JField].map(_.value).asA[JString].map(_.s)    ?~ ("rev not present or not a string: " + json)
  } yield updateIdAndRev(original, id, rev)

I checked the result of the json \ "ok", json \ "id", and json \ "rev" expressions and discovered that they already return a JBool/JString object. It looks like they used to return a JField containing a JBool/JString before.

My temporary workaround is to provide my own Database object that overrides the post method to provide a new version of handleUpdateResult (you can find it in the override-workaround branch on github too):

object TestRecordMeta extends TestRecord with CouchMetaRecord[TestRecord] {
  override def defaultDatabase = new Database("testrecord") {
    override def post(doc: JObject): Handler[Box[JObject]] = {
      (JSONRequest(this) <<# doc) ># handleUpdateResult(doc) _
    }

   def handleUpdateResult(original: JObject)(json: JValue): Box[JObject] = {
     for {
       obj <- Full(json).asA[JObject] ?~ ("update result is not a JObject: " + json)
       ok  <- Full(json \ "ok" ).asA[JBool].filter(_.value) ?~ ("ok not present in reply or not true: "+json)
       id  <- Full(json \ "id" ).asA[JString].map(_.s)    ?~ ("id not present or not a string: " + json)
       rev <- Full(json \ "rev").asA[JString].map(_.s)    ?~ ("rev not present or not a string: " + json)
     } yield updateIdAndRev(original, id, rev)
   }
  }
}

Note that this is not an ideal solution since handleUpdateResult is called by the Document trait put method as well, and I don't know how to override that (not that I use it, but still...).

So, wasn't there a recent update to lift-json? Could that be the cause for this since I don't see any recent changes to the lift-couchdb implementation? Should I open a ticket?

Best,
Hristo

David Pollak

unread,
Apr 7, 2011, 12:35:32 PM4/7/11
to lif...@googlegroups.com

Please open a ticket.

Thanks for the detailed analysis!
 

Best,
Hristo

On Wed, Apr 6, 2011 at 9:34 PM, Hristo Deshev <hri...@deshev.com> wrote:
Hi everyone,

I've been trying to upgrade my app from Lift 2.2 to Lift 2.3 and I've been seeing some failures in my test suite.  Here's what I found so far.

I'm using lift-couchdb to save a bunch of documents to well... CouchDB. My code works in the following way:

  1. It creates a record object.
  2. It saves it to the db using the meta "save" method
  3. It then gets the newly-saved document id via the record.id property that has been populated by the "save" method.
Here's some code that looks mine:

val r = TestRecordMeta.createRecord
r.text("blah")
TestRecordMeta.save(r)

println("text after save: " + r.text)
println("id after save: " + r.id.is)

println("Loading saved document...")
val loaded = TestRecordMeta.fetch(r.id.is.get).open_!
println("text after load: " + loaded.text.toString)

The above works just fine with Lift 2.2. After upgrading to Lift 2.3 the id property remains set to None after the call to "save". Is that expected? Can I obtain the document id in some other way? And, of course, am I doing something wrong?

I have put up a reproduction project on github: https://github.com/hdeshev/lift-couchdb-id. It is set to use Lift 2.3. To quickly switch to Lift 2.2, edit project/build/Project.scala and change the liftVersion variable. Then ask sbt to reload, update, and run.

Any help is much appreciated.

Hristo

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To post to this group, send email to lif...@googlegroups.com.
To unsubscribe from this group, send email to liftweb+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.



--
Lift, the simply functional web framework http://liftweb.net

Hristo Deshev

unread,
Apr 7, 2011, 3:26:43 PM4/7/11
to lif...@googlegroups.com
On Thu, Apr 7, 2011 at 7:35 PM, David Pollak <feeder.of...@gmail.com> wrote:
...
Please open a ticket.


Best,
Hristo

Mariano Guerra

unread,
Nov 3, 2011, 8:16:19 AM11/3/11
to lif...@googlegroups.com
I'm getting the same problem with lift 2.4 M4

Failure(ok not present in reply or not true: JObject(List(JField(ok,JBool(true)),
        JField(id,JString(0d73765ab417a581e3d627ba0f001664)),                 
        JField(rev,JString(1-f8c648948c4 cba500d3a9f653c8a5f5f)))),Empty,Empty)

Mariano Guerra

unread,
Nov 3, 2011, 12:18:03 PM11/3/11
to lif...@googlegroups.com
I made a fix and a pull request:

https://github.com/lift/framework/pull/10

here I wrote a guide with the steps I followed to help other people willing to fix an issue like this:

https://github.com/marianoguerra/me/blob/master/guides/lift-fix.rst

expecting the veredict :)

PS: thanks for lift!

Naftoli Gugenheim

unread,
Nov 3, 2011, 9:01:11 PM11/3/11
to lif...@googlegroups.com
Unfortunately Lift doesn't except pull requests. DPP only takes code from committers, since they signed a document about the intellectual property.


--
Lift, the simply functional web framework: http://liftweb.net

Mariano Guerra

unread,
Nov 4, 2011, 3:41:33 AM11/4/11
to lif...@googlegroups.com
On Fri, Nov 4, 2011 at 2:01 AM, Naftoli Gugenheim <nafto...@gmail.com> wrote:
> Unfortunately Lift doesn't except pull requests. DPP only takes code from
> committers, since they signed a document about the intellectual property.

on how should I do it then?

the code is not mine but from the person that opened the ticket, if he
declares that his code is on the public domain or something can it be
merged?

David Pollak

unread,
Nov 4, 2011, 10:58:16 AM11/4/11
to lif...@googlegroups.com

On Friday, November 4, 2011 at 12:41 AM, Mariano Guerra wrote:

On Fri, Nov 4, 2011 at 2:01 AM, Naftoli Gugenheim <nafto...@gmail.com> wrote:
Unfortunately Lift doesn't except pull requests. DPP only takes code from
committers, since they signed a document about the intellectual property.

on how should I do it then?


You'll have to wait until a committer takes ownership of the ticket.  We do not accept pull requests.  We have a particular IP policy and there's no such thing in US copyright law of putting something in the public domain… things can only go into the public domain as a result of the copyright term lapsing.
 
the code is not mine but from the person that opened the ticket, if he
declares that his code is on the public domain or something can it be
merged?

Mariano Guerra

unread,
Nov 4, 2011, 11:03:21 AM11/4/11
to lif...@googlegroups.com
On Fri, Nov 4, 2011 at 3:58 PM, David Pollak <d...@liftweb.com> wrote:
>
> On Friday, November 4, 2011 at 12:41 AM, Mariano Guerra wrote:
>
> On Fri, Nov 4, 2011 at 2:01 AM, Naftoli Gugenheim <nafto...@gmail.com>
> wrote:
>
> Unfortunately Lift doesn't except pull requests. DPP only takes code from
> committers, since they signed a document about the intellectual property.
>
> on how should I do it then?
>
> You'll have to wait until a committer takes ownership of the ticket.  We do
> not accept pull requests.  We have a particular IP policy and there's no
> such thing in US copyright law of putting something in the public domain…
> things can only go into the public domain as a result of the copyright term
> lapsing.

ok, I will wait then.

thanks

Indrajit Raychaudhuri

unread,
Nov 4, 2011, 11:53:38 AM11/4/11
to lif...@googlegroups.com
This has cascading awesomeness! Great analysis, nice fix and wonderful summary to back the fix.

I'll implement in the codebase with credits to Mariano and Hristo in the comment.

- Indrajit

NB: @Hristo, what's your Github handle?

Indrajit Raychaudhuri

unread,
Nov 4, 2011, 11:59:55 AM11/4/11
to lif...@googlegroups.com

On 04-Nov-2011, at 9:23 PM, Indrajit Raychaudhuri wrote:

> This has cascading awesomeness! Great analysis, nice fix and wonderful summary to back the fix.
>
> I'll implement in the codebase with credits to Mariano and Hristo in the comment.
>
> - Indrajit
>
> NB: @Hristo, what's your Github handle?

Nevermind, I found in the ticket description :)

- Indrajit

Reply all
Reply to author
Forward
0 new messages