alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lift Framework example source code file (CouchRecordSpec.scala)

This example Lift Framework source code file (CouchRecordSpec.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lift Framework tags/keywords

company, couchmetarecord, couchrecord, database, full, full, http, http, jobject, net, network, person, person, seq, statuscode, statuscode

The Lift Framework CouchRecordSpec.scala source code

/*
 * Copyright 2010-2011 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.liftweb
package couchdb

import java.net.ConnectException

import dispatch.{Http, StatusCode}

import org.specs.Specification

import common._
import json._
import JsonDSL._
import record.field.{IntField, StringField}
import DocumentHelpers.stripIdAndRev


package couchtestrecords {
  class Person private () extends CouchRecord[Person] {
    def meta = Person
  
    object name extends StringField(this, 200)
    object age extends IntField(this)
  }
  
  object Person extends Person with CouchMetaRecord[Person]
  
  class Company private () extends CouchRecord[Company] {
    def meta = Company
  
    object name extends StringField(this, 200)
  }    
  
  object Company extends Company with CouchMetaRecord[Company]
}

/**
 * Systems under specification for CouchRecord.
 */
object CouchRecordSpec extends Specification("CouchRecord Specification") {
  import CouchDB.defaultDatabase
  import couchtestrecords._
  
  val design: JObject = 
    ("language" -> "javascript") ~
    ("views" -> (("people_by_age" ->  ("map" -> "function(doc) { if (doc.type == 'Person') { emit(doc.age, doc); } }")) ~
                 ("oldest"        -> (("map" -> "function(doc) { if (doc.type == 'Person') { emit(doc.name, doc.age); } }") ~
                                      ("reduce" -> "function(keys, values) { return Math.max.apply(null, values); }")))))

  def setup = {
    val database = new Database("test")
    (try { Http(database delete) } catch { case StatusCode(_, _) => () }) must not(throwAnException[ConnectException]).orSkipExample
    Http(database create)
    Http(database.design("test") put design)
    defaultDatabase = database
  }

  def assertEqualPerson(a: Person, b: Person) = {
    a.name.value must_== b.name.value
    a.age.value must_== b.age.value
  }

  def assertEqualRows(foundRows: Seq[Person], expectedRows: Seq[Person]) = {
    foundRows.length must_== expectedRows.length
    for ((found, expected) <- foundRows.toList zip expectedRows.toList) {
      found.id.valueBox must_== expected.id.valueBox
      found.rev.valueBox must_== expected.rev.valueBox
      assertEqualPerson(found, expected)
    }
  }
    
  "A couch record" should {
    def testRec1: Person = Person.createRecord.name("Alice").age(25)
    val testDoc1: JObject = ("age" -> 25) ~ ("name" -> "Alice") ~ ("type" -> "Person")
    def testRec2: Person = Person.createRecord.name("Bob").age(30)
    val testDoc2: JObject = ("age" -> 30) ~ ("extra1" -> "value1") ~ ("extra2" -> "value2") ~ ("name" -> "Bob") ~ ("type" -> "Person")
    def testRec3: Company = Company.createRecord.name("Acme")

    "give emtpy box on get when nonexistant" in {
      setup must_== ()
 
      Person.fetch("testdoc") must verify (!_.isDefined)
    }

    "be insertable" in {
      setup
      
      val newRec = testRec1
      newRec save

      assertEqualPerson(newRec, testRec1)
      newRec.saved_? must_== true
      newRec.id.valueBox must verify (_.isDefined)
      newRec.rev.valueBox must verify (_.isDefined)

      val Full(foundRec) = Person.fetch(newRec.id.valueBox.open_!)
      assertEqualPerson(foundRec, testRec1)
      foundRec.id.valueBox must_== newRec.id.valueBox
      foundRec.rev.valueBox must_== newRec.rev.valueBox
      
    }

    "generate the right JSON" in {
      setup
      val newRec = testRec1
      newRec save

      val foundDoc = Http(defaultDatabase(newRec.id.valueBox.open_!) fetch)
      compact(render(stripIdAndRev(foundDoc))) must_== compact(render(testDoc1))
    }

    "be deletable" in {
      setup
      val newRec = testRec1
      newRec.save

      newRec.id.valueBox must verify(_.isDefined)
      val id = newRec.id.valueBox.open_!

      Person.fetch(id) must verify(_.isDefined)
      newRec.delete_! must verify(_.isDefined)
      Person.fetch(id) must not(verify(_.isDefined))
      newRec.delete_! must not(verify(_.isDefined))

      newRec.save
      Http(defaultDatabase(newRec.id.valueBox.open_!) @@ newRec.rev.valueBox.open_! delete)
      newRec.delete_! must not(verify(_.isDefined))
    }

    "be fetchable in bulk" in {
      setup
      val newRec1, newRec2, newRec3 = testRec1

      newRec1.save
      newRec2.save
      newRec3.save

      newRec1.saved_? must_== true
      newRec2.saved_? must_== true
      newRec3.saved_? must_== true

      val expectedRows = newRec1::newRec3::Nil

      Person.fetchMany(newRec1.id.valueBox.open_!, newRec3.id.valueBox.open_!).map(_.toList) must beLike {
        case Full(foundRows) => assertEqualRows(foundRows, expectedRows); true
      }
    }

    "support queries" in {
      setup

      val newRec1, newRec3 = testRec1
      val newRec2 = testRec2
      newRec1.save
      newRec2.save
      newRec3.save

      newRec1.saved_? must_== true
      newRec2.saved_? must_== true
      newRec3.saved_? must_== true

      val expectedRows = newRec2::Nil

      Person.queryView("test", "people_by_age", _.key(JInt(30))) must beLike {
        case Full(foundRows) => assertEqualRows(foundRows, expectedRows); true
      }
    }

    "support queries returning documents" in {
      setup

      val newRec1 = testRec1
      val newRec2 = testRec2
      newRec1.save
      newRec2.save

      newRec1.saved_? must_== true
      newRec2.saved_? must_== true

      val expectedRows = newRec1::newRec2::Nil

      Person.queryViewDocs("test", "oldest", _.dontReduce) must beLike {
        case Full(foundRows) => assertEqualRows(foundRows, expectedRows); true
      }
    }

    "support queries returning documents for a non-reducing view" in {
      setup

      val newRec1 = testRec1
      val newRec2 = testRec2
      newRec1.save
      newRec2.save

      newRec1.saved_? must_== true
      newRec2.saved_? must_== true

      val expectedRows = newRec1::newRec2::Nil

      Person.queryViewDocs("test", "people_by_age", identity) must beLike {
        case Full(foundRows) => assertEqualRows(foundRows, expectedRows); true
      }
    }

    "support multiple databases for fetching" in {
      setup
      val database2 = new Database("test2")
      (try { Http(database2 delete) } catch { case StatusCode(_, _) => () }) must not(throwAnException[ConnectException]).orSkipExample
      Http(database2 create)

      val newRec = testRec1
      newRec.database = database2
      newRec.save

      newRec.saved_? must_== true

      val foundRecBox = Person.fetchFrom(database2, newRec.id.valueBox.open_!)
      foundRecBox must verify(_.isDefined)
      val Full(foundRec) = foundRecBox
      assertEqualPerson(foundRec, testRec1)
      foundRec.id.valueBox must_== newRec.id.valueBox
      foundRec.rev.valueBox must_== newRec.rev.valueBox
      
      Person.fetch(newRec.id.valueBox.open_!) must not(verify(_.isDefined))
    }

    "support multiple databases for fetching in bulk" in {
      setup
      val database2 = new Database("test2")
      (try { Http(database2 delete) } catch { case StatusCode(_, _) => () }) must not(throwAnException[ConnectException]).orSkipExample
      Http(database2 create)

      val newRec1, newRec2, newRec3 = testRec1
      newRec1.database = database2
      newRec2.database = database2
      newRec3.database = database2
      newRec1.save
      newRec2.save
      newRec3.save

      newRec1.saved_? must_== true
      newRec2.saved_? must_== true
      newRec3.saved_? must_== true

      val expectedRows = newRec1::newRec3::Nil

      Person.fetchManyFrom(database2, newRec1.id.valueBox.open_!, newRec3.id.valueBox.open_!).map(_.toList) must beLike {
        case Full(foundRows) => assertEqualRows(foundRows, expectedRows); true
      }

      Person.fetchMany(newRec1.id.valueBox.open_!, newRec3.id.valueBox.open_!) must beLike { case Full(seq) if seq.isEmpty => true }
    }

    "support multiple databases for queries" in {
      setup
      val database2 = new Database("test2")
      (try { Http(database2 delete) } catch { case StatusCode(_, _) => () }) must not(throwAnException[ConnectException]).orSkipExample
      Http(database2 create)
      Http(database2.design("test") put design)

      val newRec1, newRec3 = testRec1
      val newRec2 = testRec2
      newRec1.database = database2
      newRec2.database = database2
      newRec3.database = database2
      newRec1.save
      newRec2.save
      newRec3.save

      newRec1.saved_? must_== true
      newRec2.saved_? must_== true
      newRec3.saved_? must_== true

      val expectedRows = newRec2::Nil

      Person.queryViewFrom(database2, "test", "people_by_age", _.key(JInt(30))) must beLike {
        case Full(foundRows) => assertEqualRows(foundRows, expectedRows); true
      }

      Person.queryView("test", "people_by_age", _.key(JInt(30))) must beLike { case Full(seq) if seq.isEmpty => true }
    }

    "support multiple databases for queries returning documents" in {
      setup
      val database2 = new Database("test2")
      (try { Http(database2 delete) } catch { case StatusCode(_, _) => () }) must not(throwAnException[ConnectException]).orSkipExample
      Http(database2 create)
      Http(database2.design("test") put design)

      val newRec1 = testRec1
      val newRec2 = testRec2
      newRec1.database = database2
      newRec2.database = database2
      newRec1.save
      newRec2.save

      newRec1.saved_? must_== true
      newRec2.saved_? must_== true

      val expectedRows = newRec1::newRec2::Nil

      Person.queryViewDocsFrom(database2, "test", "oldest", _.dontReduce) must beLike {
        case Full(foundRows) => assertEqualRows(foundRows, expectedRows); true
      }

      Person.queryViewDocs("test", "oldest", _.dontReduce) must beLike { case Full(seq) if seq.isEmpty => true }
    }
  }
}

Other Lift Framework examples (source code examples)

Here is a short list of links related to this Lift Framework CouchRecordSpec.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.