Last active
February 8, 2018 06:36
-
-
Save tlync/7913967 to your computer and use it in GitHub Desktop.
Scala Advent Calendar 2013 12/11 の記事で利用した Transparent IO Context パターンのコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Transparent IO Context pattern using implicit parameter | |
// --- | |
// domain | |
// --- | |
// base (サンプルなのでほぼただの Marker Trait) | |
trait Entity | |
// 永続化に利用するセッションを保持するただのコンテナ | |
case class IoContext[S](session: S) | |
// IoContext を各レイヤから透過的に扱える様にする為の trait | |
trait TransparentIoContext[S] { | |
implicit def wrapContext(implicit session: S) = IoContext(session) | |
implicit def unwrapContext(implicit ctx: IoContext[S]) = ctx.session | |
} | |
trait Repository[S] extends TransparentIoContext[S] | |
case class User(id: Int, name: String) extends Entity | |
trait Users[S] extends Repository[S] { | |
// Repository の各インターフェースは抽象的な IoContext に依存するだけ | |
def find(id: Int)(implicit ctx: IoContext[S]): Option[User] | |
} | |
// --- | |
// infra | |
// --- | |
import scalikejdbc._ | |
import SQLInterpolation._ | |
class ScalikeJdbcBasedUsers extends Users[DBSession] { | |
private def rsToEntity(rs: WrappedResultSet) = { | |
User(rs.int("id"), rs.string("name")) | |
} | |
def find(id: Int)(implicit ctx: IoContext[DBSession]): Option[User] = { | |
// TransparentIoContext#unwrapContext が評価され暗黙的に DBSession が渡される | |
// もちろん ctx が渡ってきているので明示的に使うこともできる | |
sql"select * from users where $id".map(rsToEntity).single().apply() | |
} | |
} | |
// --- | |
// app | |
// --- | |
class SomeService extends TransparentIoContext[DBSession] { | |
val users = new ScalikeJdbcBasedUsers // 実際には DI 使う | |
// UserRepo 以外も色々扱って処理するなにか | |
def doSomething() = { | |
DB localTx { implicit session => | |
// この implicit session は TransparentIoContext により、 | |
// IoContext[DBSession] に変換されて、Users#find に暗黙パラメータとして渡される | |
val u = users.find(1) | |
// ... | |
println(u) // -> Some(User(1,scalachan)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment