2017-02-10 2 views
0

Ich lerne ReactiveMongo. In meiner Anwendung möchte ich Daten von MongoDB abrufen und in einem HTML-Formular ausfüllen.bekommen None.get beim Ausfüllen eines HTML-Formulars aus Daten von MongoDB in PlayFramework, Scala, reactivemongo Anwendung

Früher war mein Problem, dass Code nicht kompiliert wurde. Ich habe es behoben, aber jetzt bekomme ich None.get statt Wert aus der Datenbank.

Die Daten, die ich in MongoDB haben Karte zu folgenden Fall Klasse

case class User2(
        name:String, 
        email:String, 
        age:Int, 
        gender:Boolean 
       ) 

Es folgt der Leser durch Reaktive Mongo erforderlich.

Question1 - Ich erhalte None.get statt Wert von MongoDB

object User2{ 
    implicit object UserReader extends BSONDocumentReader[User2] { 
     def read(doc: BSONDocument): User2= { 
     val name = doc.getAs[String]("name").get 
     val email = doc.getAs[String]("email").get 
     val age = doc.getAs[Int]("age").get 
     val gender = doc.getAs[Boolean]("gender").get 

     User2(name, email, age, gender) 
     } 
    } 
    } 

Im Anschluss ist mein Controller-Code. Ignorieren Sie die unnötigen Importe

package controllers 

import anorm.{NotAssigned, Pk} 
import play.api.data.Form 
import play.api.data.Form._ 
import play.api.data.Forms 
import play.api.mvc.Controller 
import play.api.mvc._ 
import play.api.data.Forms._ 
import play.api.data.validation.Constraints._ 
import play.api.db.DB 
import models._ 
import scala.concurrent._ 
import ExecutionContext.Implicits.global 
import scala.util.Try 


import reactivemongo.api.MongoDriver 
import reactivemongo.bson._ 
import reactivemongo.api.MongoConnection 
import reactivemongo.api.collections.default.BSONCollection 



object Application_Test extends Controller { 
    val user2Form: Form[User2] = Form(
    mapping(
     "name" -> nonEmptyText, 
     "email" -> email, 
     "age" -> number, 
     "gender" -> boolean 
    )(User2.apply)(User2.unapply) 
) 

    def index = Action { 
    Async { 
     val driver = new MongoDriver() 
     val connection = driver.connection(List("localhost")) 
     val db = connection.db("website-users") 
     val collection = db.collection[BSONCollection]("user-table") 

     val query = BSONDocument("name" -> "Manu") 

     val result = collection.find(query).cursor[User2].collect[List]() 
/*  
      result.map { user => 
     //following code doesn't compile. I think result is List[models.User2]. I tried using user and user(0) but none of them compile 
      Ok(views.html.HTMLTest(user2Form.fill(user))) 
      } 
*/ 

// this version of code compiles 

result.map { user => user match { 
     case List() => Ok(views.html.HTMLTest(user2Form.fill(User2("a","[email protected]",1,true)))) 
     case h::v => Ok (views.html.HTMLTest (user2Form.fill (h))) 
     } 
     } 
    } 
    } 
} 

Es folgt der HTML

Question2 - ist @form ("name") Wert der richtige Weg, um einen Wert aus einem Formular zu extrahieren.?

@(form:Form[User2]) 

<!DOCTYPE html> 
<html lang="en" xmlns:font-variant="http://www.w3.org/1999/xhtml"> 
<head> 
    <meta charset="UTF-8"> 
    <meta http-equiv="X-UA-COMPATIBLE" content="IE=edge"> 
    <meta name="viewport" content="width=device-width,initial-scale=1"> 
    <title>HTML Test</title> 
    <link rel="stylesheet" type="text/css" href="@routes.Assets.at("stylesheets/bootstrap.min.css")"> 
    <!--link rel="stylesheet" href="stylesheets/bootstrap-theme.min.css"--> 
    <style type="text/css"> 

     html, body{height:100%; margin:0;padding:0} 

.center-form { 
    width:100%; 
    margin:auto; 
    position:relative; 
    top:50%; 
    transform: translateY(-50%) 
} 


</style> 

</head> 
<body> 

<div class="container center-form" > 

    <!-- for medium and large screens, 
    First row of Bootstrap grid contains logo. Total 3 columns (12/4). Logo in middle column--> 

    <div class="row" > 
     <!--empty column--> 
     <div class="col-md-4 col-lg-4" ></div> 

     <!--logo column--> 
     <div class="col-md-4 col-lg-4" > 
      <div> 
       <img src="@routes.Assets.at("images/Logo303x64.png")" alt="SalesWorkspace Logo" height="64" width="303"> 
      </div> 
     </div> 
     <!--empty column--> 
     <div class="col-md-4 col-lg-4"></div> 
     </div> 

    <!-- for medium and large screens, 
    Second row of Bootstrap grid contains the form for username and password. Total 3 columns (12/4). --> 
     <div class="row" > 
      <!--empty column--> 
      <div class="col-md-4 col-lg-4"></div> 

      <!--form--> 
      <div class="col-md-4 col-lg-4"> 

      <form> 
        <div class="form-group"> 
         <label for="first-name">First Name</label> 
         <input type="text" class="form-control" id="first-name" value="@form("name").value" required> 
        </div> 

        <div class="form-group"> 
         <label for="last-name">Last Name</label> 
         <input type="text" class="form-control" id="last-name" value="@form("name").value" required> 
        </div> 

        <div class="form-group"> 
         <label for="email">Email</label> 
         <input type="email" class="form-control" id="email" value="@form("email").value" required> 
        </div> 
        <div class="form-group"> 
         <label for="password">Password</label> 
         <input type="password" class="form-control" id="password" required> 
        </div> 
        <div class="form-group"> 
         <label for="confirm-password">Password</label> 
         <input type="password" class="form-control" id="confirm-password" required> 
        </div> 


        <button type="submit" class="btn btn-primary">Login</button> 
       </form> 
      </div> 
      <!--empty column--> 
      <div class="col-md-4 col-lg-4"></div> 
     </div> 
</div> 
<!--script src="@routes.Assets.at("javascripts/jquery-1.9.0.min")"></script--> 
<!--script src="@routes.Assets.at("javascripts/bootstrap.min.js")"></script--> 
</body> 
</html> 
+0

Bitte separate Frage separat stellen – cchantep

Antwort

0

Wie in der API-Dokumentation angegeben, BSONDocument.getAs[T] liefert ein Option[T] und so für optionales Dokumentenfeld verwendet werden könnte.

Anwenden .get auf so Option ist eindeutig ein Code Geruch.

Wenn Sie ein Feld bekommen, die erforderlich angenommen wird, sollten Sie besser .getAsTry verwenden, die Details im Fehlerfall geben würde (hilfreicher als NoSuchElementException von None.get).

def read(doc: BSONDocument): User2= (for { 
    name <- doc.getAsTry[String]("name") 
    email <- doc.getAsTry[String]("email") 
    age <- doc.getAsTry[Int]("age") 
    gender <- doc.getAsTry[Boolean]("gender") 
    } yield User2(name, email, age, gender)).get 
+0

Vielen Dank. Dein Tipp war hilfreich. Das Problem war die Umwandlung des Booleschen Typs. '[RuntimeException: reactivemongo.bson.BSONString kann nicht in reacticmongo.bson.BSONBoolean]' umgesetzt werden. Ich habe dieses neue Problem noch nicht gelöst, aber den hardcoded Wert "true" in "User2 (name, email, age, true)" zu verwenden, scheint zu funktionieren. –

+0

Ein anderes Problem in meinem Code war die Dateneingabe in MongoDB. Ich hatte eine CSV-Datei verwendet und es scheint, dass ein Eintrag "falsch" in CSV in Zeichenfolge konvertiert wird, bevor Sie es in MongoDB speichern (anstatt es als boolean zu speichern). Anstatt csv zu verwenden, habe ich Robomongo verwendet, um einen Eintrag mit dem korrekten Datentyp zu erstellen –

Verwandte Themen