2017-02-10 3 views
0

Я изучаю ReactiveMongo. В моем приложении я хочу получить данные из MongoDB и заполнить его в форме HTML.Получение None.get при заполнении формы HTML из данных MongoDB в PlayFramework, scala, reactivemongo application

Раньше у меня была проблема с тем, что код не компилировался. Я исправил его, но теперь я получаю None.get вместо значения из базы данных.

Данные, которые я имею в MongoDB будет отображаться в следующем случае класс

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

Ниже читатель требует Реактивная Монго.

Question1 - Я получаю None.get вместо значения из 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) 
     } 
    } 
    } 

Ниже мой код контроллера. Не обращайте внимания на ненужный импорт

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))) 
     } 
     } 
    } 
    } 
} 

Ниже в HTML

question2 - это @form («имя») значение правильного путь для извлечения значения из формы.?

@(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

Пожалуйста, задайте отдельный вопрос отдельно – cchantep

ответ

0

Как указано в документации API, BSONDocument.getAs[T] возвращает Option[T] и поэтому может быть использован для дополнительного поля документа.

Применить .get на таких Option, безусловно, является запахом кода.

Если вы хотите, чтобы получить поле, которое, как предполагается, потребуется, вы бы лучше использовать .getAsTry, который дал бы детали в случае ошибки (более полезно, чем NoSuchElementException от 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

Спасибо. Ваш отзыв был полезен. Проблема заключалась в преобразовании булевого типа. '[RuntimeException: reactivemongo.bson.BSONString не может быть отброшено в responseivemongo.bson.BSONBoolean]'. Я еще не решил эту новую проблему, но использовал hardcoded значение «true» в 'User2 (имя, адрес электронной почты, возраст, истина)). Get', похоже, работает. –

+0

Еще одна проблема в моем коде была запись данных в MongoDB. Я использовал файл csv, и кажется, что запись «false» в csv преобразуется в строку перед сохранением в MongoDB (вместо того, чтобы хранить ее как логическую). Вместо использования csv я использовал Robomongo для записи с правильным типом данных –

Смежные вопросы