我正在使用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”列的那一刻,<>
符号的分辨率开始失败。我似乎无法看到这里的问题是什么。
任何指针?