用于处理枚举类型的通用映射函数

时间:2015-01-20 17:19:05

标签: scala slick

我有以下枚举类型。

class Payment extends Enumeration {
  type Payment = Value
  val Cash, CreditCard, Unspecified = Value
}
object Payment extends Payment

class Ticket extends Enumeration {
  type Ticket = Value
  val Normal, Discount, Other = Value
}
object Ticket extends Ticket

我将枚举声明为类而不是对象,因为稍后我将需要类型信息(对于MappedColumnType)。

这是光滑表的非工作版本:

class Stats(tag: Tag) extends Table[Stat](tag, "STATS") {

  implicit def enumToInt[E <: Enumeration : ClassTag, V : ClassTag](implicit conv: V => E#Value): BaseColumnType[V] =
    MappedColumnType.base[V, Int] (
      value => value.id,
      num => implicitly[ClassTag[E]].runtimeClass.newInstance().asInstanceOf[E](num).asInstanceOf[V]
    )

  def entityid = column[Int]("ENTITYID")
  def email = column[String]("EMAIL")
  def payment = column[Payment]("PAYMENT")
  def ticket = column[Ticket]("TICKET")
  def phone = column[String]("PHONE")
  def ticket_source = column[TicketSource]("TICKETSOURCE")

  def * = (entityid, email, payment, ticket, phone, ticket_source) <>
    (Stat.tupled, Stat.unapply)
}

我的目标是定义一个通用映射器函数来处理所有枚举,因为转换方法对所有类型的枚举都有效(值为id,id为value)。

在mapper函数中,我尝试捕获ClassTag信息并创建一个运行实例来调用apply方法,该方法返回枚举Value。我必须在.asinstanceOf[V]方法的结果中添加apply,否则E#Value的错误与V的预期值不匹配。 现在,这是我得到的错误消息:

Tables.scala:45: could not find implicit value for parameter tm: scala.slick.ast.TypedType[com.yokyer.tiyatrosever.models.Payment]
[error]   def payment = column[Payment]("PAYMENT")
[error]                                ^
Tables.scala:46: could not find implicit value for parameter tm: scala.slick.ast.TypedType[com.yokyer.tiyatrosever.models.Ticket]
[error]   def ticket = column[Ticket]("TICKET")

我是scala的新手,我把一堆关于反射的食谱放在一起,想知道我是否在做一些根本错误的事情。

1 个答案:

答案 0 :(得分:3)

您需要创建MappedColumnType

import profile.simple._

def enumValueMapper(enum: Enumeration) = MappedColumnType.base[enum.Value, String](
    e => e.toString,
    s => Try(enum.withName(s)).getOrElse(throw new IllegalArgumentException
                                        (s"enumeration $s doesn't exist $enum 
                                        [${enum.values.mkString(",")}]"))
)

def enumIdMapper(enum: Enumeration) = MappedColumnType.base[enum.Value, Int](
    e => e.id,
    i => enum.apply(i)
)

然后你可以使用

// It convert Enum to Int
implicit val paymentMapper = enumIdMapper(Payment) 

或者

// It convert Enum to String
implicit val paymentMapper = enumValueMapper(Payment)