2016-06-12 10 views
0

私は自分のscalaにplay-slickを使用しています。Play!ダミーレストAPI。Scala Play将来の相互依存性

したがって、複数のテーブルからレコードをフェッチする必要があります。しかし、彼らは、私がTABLE_1からレコードをフェッチし、その後ID2がTable_2からフェッチ使用する必要がTable_2からレコードを取得するために、すなわち

Table_1 Table_2 
id1  id2 
id2 

相互に依存しています。

マイコントローラ:

def getEntity(id : Long) = Action.async { 
    table1DAO.findById(id) map { t1 => 
    t1 map { t1Entity => 
     table2DAO.findById(t1Entity.id2) map { t2 => 
     t2 map { t2Entity => 
      Ok(Json.toJson(CombiningClass(t1Entity, t2Entity))) 
     } getOrElse { Ok(Json.toJson(t1Entity)) } 
     } 
    } getOrElse { NoContent } 
    } 
} 

は、コンパイルした後、私が手:

def findById(id : Long): Future[Option[A]] = { 
    db.run(tableQ.filter(_.id === id).result.headOption) 
} 

PS:

[error] DummyController.scala:17: overloaded method value async with alternatives: 
[error] [A](bodyParser: play.api.mvc.BodyParser[A])(block: play.api.mvc.Request[A] => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[A] <and> 
[error] (block: play.api.mvc.Request[play.api.mvc.AnyContent] => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] <and> 
[error] (block: => scala.concurrent.Future[play.api.mvc.Result])play.api.mvc.Action[play.api.mvc.AnyContent] 
[error] cannot be applied to (scala.concurrent.Future[Object]) 
[error] def getEntity(id : Long) = Action.async { 
[error]        ^
[error] one error found 

はここに私のDAOの方法だ私は、機能のパラダイムに非常に新しいですし、あなたができるならば、私の無知を許してください。単にあなたの問題を解決するために

+0

トップ 'map':' table1DAO.findById(id).map [結果] {t1 => ...} 'にアノテーションを付けて、' Future [Result] 'を与えてください。 P.S.あなたのコードの可読性は、理解のための使用から利益を得ます。 – cchantep

答えて

1

def getEntity(id : Long) = Action.async { 
    findById(id) flatMap { 
    case Some(t1Entity) => 
     findById(t1Entity.id2) map { t2Opt => 
     t2Opt map { t2Entity => 
      Ok(Json.toJson(t1Entity, t2Entity)) 
     } getOrElse { Ok(Json.toJson(t1Entity)) } 
     } 
    case None => Future.successful(NoContent) 
    } 
} 

問題ここでは、Scalaで一緒にflatMapOptionFutureをできないことです。 Hereはこのトピックに関する幻想的でシンプルな記事です(解決策としてはFutureOのモナド実装があります)。長い話では、catsライブラリ(またはscalazライブラリ)とOptionT機能を使用します。私はあなたのコードを少し簡略化しました。簡単flatMapモナドOptionTこの上で、あなたがOptionまたはFutureを扱っている場合は気にしない

def getEntity(id : Long) = Action.async { 
    (for { 
    t1 <- daoFindById(id) 
    t2 <- daoFindById(t1.id2) 
    } yield (t1, t2)).map{ 
    result => Ok(Json.toJson(result)) 
    }.getOrElse(NoContent) 
} 

case class T(id2: Long) 
def daoFindById(id : Long): OptionT[Future, T] = { 
    OptionT[Future, T](db.run(tableQ.filter(_.id === id).result.headOption)) 
} 

あなたは今(Scalaでは理解のための唯一のシンタックスシュガーである)ことができます。

+0

これは良い答えですが、Scalaを使い始めた人にとっては少し進んでいるかもしれません。 2番目のエンティティが見つからない場合、これは最初のエンティティにはなりません。 Catsには[OptionT'に関するチュートリアル(http://typelevel.org/cats/tut/optiont.html)もあります。 –

+1

あなたのアップデートは私のコメントを解決します。それはもう少し初心者フレンドリーで、OPが期待している結果を返すので、いい仕事です! –

+1

はい、すべてのビジネスロジックが保持されているわけではありません(私は猫のライブラリの有用性を実証したかっただけです)。私は外部ライブラリの助けを借りずに書かれた簡単なソリューションを追加しました。 – liosedhel

関連する問題