validation内でデータベースへの問合せ方法につきまして

196 views
Skip to first unread message

芳山翼

unread,
May 4, 2016, 10:42:46 PM5/4/16
to 日本Playframeworkユーザー会
はじめて投稿させて頂きます。

今まで、Java版を利用させて頂いており、Scala版を利用したいと思い、
GW中に勉強させて頂いております。

現状利用しているframeworkとバージョンは下記の通りです。

Play 2.5.3 Scala
Slick 3.1.0

以前、作ったJava版で作ったプログラムを、Scala版に置き換えをして、
勉強しているのですが、validation内でのデータベースへの問合せ方法が理解できておらず、
下記のようなコードを記述させて頂きました。

class BookController @Inject()(book: bookDao)(implicit context: ExecutionContext) extends Controller {

 
def validate(name: String, category: String) = {

    logger
.debug(bookDataId)

   
val f = book.isPrice(name, category)
    f
.isCompleted
match {
     
case true =>
       
Some(BookData(name, category))
     
case _ =>
       
Some(null)
   
}
 
}

 
val userForm = Form(
    mapping
(
     
"name" -> text,
     
"category" -> text
   
)(
BookData.apply)(BookData.unapply) verifying("エラー", fields => fields match {
     
case bookData => validate(bookData.name, bookData.category).isDefined
   
})
 
)
}


class BookDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)
 
extends HasDatabaseConfigProvider[JdbcProfile] {

 
import driver.api._

 
val booktable = TableQuery[BookTable]

 
def all(): Future[Seq[Book]] = db.run(booktable.result)

 
def isPrice(name: String, category: String): Future[Option[BookTable]] =
    db
.run(
      booktable
.filter(
        n
=>
         
(n.name === name) && (n.category === category)
     
).result.headOption)
}


上記を実行すると、データベースへは接続し値を取得できるのですが、
f.isCompletedの結果が必ずfalseになります。
非同期で実行されているようで、どうしたら、正常な処理となるのか、
わかりませんでした。

私の記述に問題があると思うのですが、どのように修正すればよいかわからないため、
こちらに投稿させて頂きました。

初歩的なことかもしれませんが、アドバイス頂けると幸いです。

大変、お手数をおかけしますが、よろしくお願い致します。

周防竜

unread,
Oct 22, 2016, 7:27:14 AM10/22/16
to 日本Playframeworkユーザー会
芳山〔よしやま?〕さん、はじめまして

投稿ありがとうございます。

実はPlayとScalaを始めた時は僕もこういう問題で困っていたのです。
一先ず分からないといけないのはPlayが基本的に並列実行ということです。
それからScalaのmapの関数という基本です。mapとは値を変える関数です。この場合の変えるのはいわゆるラッパーの中身ですよ

コードを直して、説明してみます。

class BookController @Inject()(book: bookDao)(implicit context: ExecutionContext) extends Controller
{

 
def validate(name: String, category: String) = Action.async {

    logger
.debug(bookDataId)

   
book.isPrice(name, category) map {
       
case Some(b: BookTable) =>
Ok(s"見つかった! - name: $b.name, category: $b.category")
        case _ => NotFound("見つからなかった T_T")
    }

 
}

 
val userForm = Form(
    mapping
(
     
"name" -> text,
     
"category" -> text
   
)(
BookData.apply)(BookData.unapply) verifying("エラー", fields => fields match {
     
case bookData => validate(bookData.name, bookData.category).isDefined
   
})
 
)
}


コードは未完成なのでちゃんとテストできませんでしたが、こんな風になんとかなると思います。

Futureとは未来という意味通りに結果が出るはずですけどいつかは分からないことですね。

結果がFutureなので、Action.asyncを使わないといけません。

isPriceの結果はFuture[Option[BookTable]]なのでmapを利用すればFutureの値〔中身〕を変えることができます。ということはこの場合はResultに変えることですね。mapの結果はFuture[Result]となりますね。


それからPlayの用法を分かるのには大丈夫ですけど、アーキテクチャはちょっと。。。

下手な日本語すみませんでした。
それより詳しい説明が欲しければ、遠慮なく知らせてみてください。

よろしくお願いいたします。
Reply all
Reply to author
Forward
0 new messages