Scala + Slick + Accord - 自定义值 class 类型不起作用。只是一个糟糕的方法?

Scala + Slick + Accord - Custom value class types not working. Just a bad approach?

我对 Scala 还是很陌生,正在考虑使用 Slick。

我也在查看 Accord (github.com/wix/accord) 进行验证。

Accord 的验证似乎是针对整个对象的,但我希望能够为字段类型定义验证器,所以我想到了使用值 类 来使用类型别名,这样我就可以轻松在使用这些字段类型的各种情况 类 中重复使用验证。

因此,我定义了以下内容:

object FieldTypes {
  implicit class ID(val i: Int) extends AnyVal
  implicit class UserPassword(val s: String) extends AnyVal
  implicit class Email(val s: String) extends AnyVal
  implicit class Name(val s: String) extends AnyVal
  implicit class OrgName(val s: String) extends AnyVal
  implicit class OrgAlias(val s: String) extends AnyVal
}

package object validators {
  implicit val passwordValidator = validator[UserPassword] { _.length is between(8,255) }
  implicit val emailValidator = validator[Email]  { _ is notEmpty }
  implicit val nameValidator = validator[Name] { _ is notEmpty }
  implicit val orgNameValidator = validator[OrgName] { _ is notEmpty }
  implicit val teamNameValidator = validator[TeamName] { _ is notEmpty }
}

case object Records {
  import FieldTypes._

  case class OrganizationRecord(id: ID, uuid: UUID, name: OrgName, alias: OrgAlias)
  case class UserRecord(id: ID, uuid: UUID, email: Email, password: UserPassword, name: Name)
  case class UserToOrganizationRecord(userId: ID, organizationId: ID)
}

class Tables(implicit val p: JdbcProfile) {
  import FieldTypes._
  import p.api._


  implicit object JodaMapping extends GenericJodaSupport(p)

  case class LiftedOrganizationRecord(id: Rep[ID], uuid: Rep[UUID], name: Rep[OrgName], alias: Rep[OrgAlias])
  implicit object OrganizationRecordShape extends CaseClassShape(LiftedOrganizationRecord.tupled, OrganizationRecord.tupled)

  class Organizations(tag: Tag) extends Table[OrganizationRecord](tag, "organizations") {
    def id = column[ID]("id", O.PrimaryKey)
    def uuid = column[UUID]("uuid", O.Length(36, varying=false))
    def name = column[OrgName]("name", O.Length(32, varying=true))
    def alias = column[OrgAlias]("alias", O.Length(32, varying=true))
    def * = LiftedOrganizationRecord(id, uuid, name, alias)
  }
  val organizations = TableQuery[Organizations]
}

不幸的是,我显然误解或高估了 Scala 隐式转换的强大功能。我的 passwordValidator 似乎没有意识到 length 属性 到 UserPassword 和我的 Organizations [=34] 上的 * 声明=] 似乎不认为它符合 LiftedOrganizationRecord.

中定义的形状

总的来说,我只是在做一些非常愚蠢的事情吗?我什至不应该尝试使用这些类型的自定义类型,而是简单地使用标准类型,以更好的方式定义我的验证器吗?或者这是一种好的做事方式,但我只是忘记了一些简单的事情?

如有任何建议,我们将不胜感激!

感谢 scala gitter 频道的一些帮助,我意识到核心错误是对价值转换方向的误解 类。我理解为 ValueClass -> WrappedValueType,但实际上是 WrappedValueType -> ValueClass。因此,例如,Slick 没有将 ID 视为 Int。