生成列映射

时间:2017-11-03 10:23:45

标签: scala playframework slick

我正在使用play-slick插件3.0.1和Play! 2.6.6似乎遇到了问题。

我要做的是从包含多个列的数据库表中实现基于“grant”的权限系统。由于此表可以很宽泛,我想找到一种方法以编程方式生成列名并从每列读取位,并评估是否存在授权。

例如,表格可能如下所示:

granted_for  grantee  read  write
id1          id2      1     0

接下来,我这样设置:

import centralapp.api.string.CamelToUnderscore
import models.permissions.grants.Grant
import slick.ast.{BaseTypedType, TypedType}
import slick.jdbc
import slick.jdbc.JdbcType
import slick.jdbc.MySQLProfile.api._
import slick.lifted.ProvenShape

trait HasName {
  /**
    * @note "HasName"
    */
  def simpleName: String = getClass.getSimpleName.replaceAll("[^a-zA-Z0-9_]", "")

  /**
    * @note "has_name"
    */
  def classNameLower: String = simpleName.toUnderscoreLower

  /**
    * @note "HAS_NAME"
    */
  def classNameUpper: String = simpleName.toUnderscoreUpper
}

然后是一个定义DB列抽象的特征:

trait DBColumn[C, T <: Table[_]] extends HasName {

  /**
    * the name of the column
    */
  def columnName: String = classNameLower

  /**
    * get the column representation
    *
    * @param c     the TypedType representation of this column's type
    * @param table the table for which the column is being generated
    * @return a Rep[C] (representation of type C)
    */
  def col(implicit c: TypedType[C], table: T): Rep[C] = table.column[C](columnName)

}

然后使用它来生成“Grant”列映射:

package object db {

  /**
    * creates a grant column mapping from a boolean column for a given grant
    *
    * @param g the grant to obtain if the column is set to "true"
    * @tparam G the subtype of the grant
    * @return the JDBC type for the desired value
    */
  def optGrantFromBoolCol[G <: Grant](g: G): JdbcType[Option[G]] with BaseTypedType[Option[G]] = MappedColumnType.base[Option[G], Boolean](
    _.isDefined,
    {
      case true => Some(g)
      case false => None
    }
  )

  abstract class GrantCol[G <: Grant, T <: Table[_]](grant: G) extends DBColumn[Option[G], T] {

    // class Grant also extends HasName; here I want to ensure the column name is exactly the same as the string representation of the grant. 
    override def columnName: String = grant.classNameLower

    /**
      * get the column representation
      *
      * @param table the table for which the column is being generated
      * @return a Rep[C] (representation of type C)
      */
    def grantCol(implicit table: T): jdbc.MySQLProfile.api.Rep[Option[G]] = col(optGrantFromBoolCol(grant), table)
  }

}

然后我试着像这样使用它:

object Columns {

  case object GrantedFor extends DBColumn[String, MyTable]
  case object Grantee extends DBColumn[String, MyTable]
  case object Read extends GrantCol[UserGrant, MyTable](usergrants.Read)

}

// and then used it in a table:

class MyTable(tag: Tag) extends Table[SomeClass](tag, "my_table") {

  implicit def table = this

  val grantedFor = Columns.GrantedFor.col
  val grantee = Columns.Grantee.col
  val read = Columns.Read.grantCol

  def * : ProvenShape[SomeClass] =
    (grantedFor, grantee, read) <> // <- this is the problem: Cannot resolve symbol "<>"  
      (
        ???, // valid constructor from tuple
        ??? // valid unapply
    )

  def other : ProvenShape[OtherClass] =
    (grantedFor, grantee) <> (
      ???,
      ???
    )

}

如评论中所述,我看到元组中有“Grant”列的那一刻,<>符号的分辨率开始失败。我似乎无法看到这里的问题是什么。

任何指针?

0 个答案:

没有答案