Skip to content

Instantly share code, notes, and snippets.

@KentaKomai
Last active August 29, 2015 14:18
Show Gist options
  • Save KentaKomai/d2e72b272b4c756cc562 to your computer and use it in GitHub Desktop.
Save KentaKomai/d2e72b272b4c756cc562 to your computer and use it in GitHub Desktop.
anormで汎用的なモデル考えてみた
package models
import java.sql.Connection
import anorm._
import anorm.SqlParser._
import play.api.Play.current
import play.api.db.DB
/** 性別を表すクラス(本来は別ファイルにしたほうがいいかも) */
sealed abstract class Gender(val code:Int)
object Gender{
case object Unknown extends Gender(0)
case object Male extends Gender(1)
case object Female extends Gender(2)
def all:Set[Gender] = Set(Unknown, Male, Female)
def apply(code:Int):Gender = all.find( t => code == t.code ).getOrElse(Unknown)
}
/** ユーザの週別を表すクラス(本来は別ファイルにしたほうがいいかも) */
sealed abstract class UserType(val code:Int)
object UserType{
case object SuperAdmin extends UserType(1)
case object Admin extends UserType(2)
case object Normal extends UserType(3)
case object Invalid extends UserType(0)
def all:Set[UserType] = Set(SuperAdmin, Admin, Normal)
def apply(code:Int):UserType = all.find( t => code == t.code ).getOrElse(Invalid)
}
/** Userテーブル */
case class User(id:Long, name:String, gender:Gender, age:Int, profile:Option[String], userTYpe:UserType)
object User {
/** テーブル名 */
protected[models] val tableName = "user"
/** 各カラム名 */
protected[models] object ColumnNames{
val id = "id"
val name = "name"
val gender = "gender"
val age = "age"
val profile = "profile"
val userType = "user_type"
}
private val userParser = long(ColumnNames.id) ~ str(ColumnNames.name) ~ int(ColumnNames.gender) ~ int(ColumnNames.age) ~ get[Option[String]](ColumnNames.profile) ~ int(ColumnNames.userType)
private val userMapper = userParser.map({
case id ~ name ~ gender ~ age ~ profile ~ userTypeCode =>
User(id, name, Gender(gender), age, profile, UserType(userTypeCode))
})
private def userValues(implicit user:User) = {
Seq[NamedParameter](
ColumnNames.name -> user.name,
ColumnNames.gender -> user.gender.code,
ColumnNames.age -> user.age,
ColumnNames.profile -> user.profile,
ColumnNames.userType -> user.userTYpe.code
)
}
/** ID検索 */
def findById(id:Long):Option[User] = DB.withConnection { implicit con =>
SQL(s"""
SELECT * FROM $tableName WHERE ${ColumnNames.id} = {${ColumnNames.id}}
"""
).on(ColumnNames.id -> id).as(userMapper.singleOpt)
}
/** 汎用的な検索 */
def find(whereConditions:String*):List[User] = DB.withConnection { implicit con =>
SQL(s"""
SELECT * FROM $tableName WHERE ${assembleWhereSentence(whereConditions)}
"""
).as(userMapper.*)
}
/** 更新 */
def update(user:User):Int = DB.withConnection { implicit con =>
SQL(s"""
UPDATE $tableName SET
${ColumnNames.name} = {${ColumnNames.name}},
${ColumnNames.gender} = {${ColumnNames.gender}},
${ColumnNames.age} = {${ColumnNames.age}},
${ColumnNames.profile} = {${ColumnNames.profile}},
${ColumnNames.userType} = {${ColumnNames.userType}}
WHERE ${ColumnNames.id} = ${ColumnNames.id}
"""
).on( (userValues(user) ++: Seq[NamedParameter](ColumnNames.id -> user.id) ): _* ).executeUpdate()
}
/** 挿入 SQL Interpolation使ったほうがいいかな・・・ */
def insert(user:User):Option[Long] = DB.withConnection { implicit con =>
SQL(s"""
INSERT INTO $tableName (
${ColumnNames.name},
${ColumnNames.gender},
${ColumnNames.age},
${ColumnNames.profile},
${ColumnNames.userType},
) VALUE (
{${ColumnNames.name}},
{${ColumnNames.gender}},
{${ColumnNames.age}},
{${ColumnNames.profile}},
{${ColumnNames.userType}},
)
"""
).on(userValues(user): _*).executeInsert()
}
/** 削除 */
def delete(id:Long):Int = DB.withConnection { implicit con =>
SQL(s"""
DELETE FROM $tableName WHERE ${ColumnNames.id} = {${ColumnNames.id}}
"""
).on(ColumnNames.id -> id).executeUpdate()
}
/** WHERE文を組み立てて文字列を返す関数 */
private def assembleWhereSentence(conditions:Seq[String]):String = {
val wherePrefix = "WHERE 1"
conditions.foldLeft(wherePrefix) {
(acc, sentence) => acc + "AND " + sentence
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment