我正在尝试将MegaProtoUser
String
的主键ID字段设为Long
。我正在考虑扩展MegaProtoUser
特征并覆盖其成员,但我必须覆盖受保护的类(我认为),这在Scala中是不允许的。因为我无法弄清楚如何扩展MegaProtoUser
,所以我决定编写我自己的这个特性版本(见下文)并将其混合如下:
class User extends StringMegaProtoUser[User] with CreatedUpdatedNotEditable {
def getSingleton = User //
...
}
这不起作用。编译器抱怨我在User模型中定义的外键不是正确的类型。任何人都可以建议如何扩展MegaProtoUser,以便它使用String id而不是Long id?
谢谢!
更新:在下面的代码中,为了回应下面的评论,我将KeyedMapper[Long, T]
更改为KeyedMapper[String, T]
。这没有解决问题:当我使用这个新的StringMegaProtoUser时,编译器给我以下错误:
[error] ..../src/main/scala/code/model/User.scala:39: type mismatch;
[error] found : code.model.User.type
[error] required: net.liftweb.mapper.KeyedMetaMapper[String,code.model.User]
[error] def getSingleton = User // what's the "meta" server
有人可以建议如何解决这个问题吗?谢谢!
trait StringProtoUser[T <: net.liftweb.mapper.StringProtoUser[T]]
extends KeyedMapper[Long, T] with UserIdAsString {
self: T =>
override def primaryKeyField: MappedStringIndex[T] = id
/**
* The primary key field for the User. You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val id = new MyMappedLongClass(this) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val id: MappedStringIndex[T] = new MyMappedStringClass(this)
protected class MyMappedStringClass(obj: T) extends MappedStringIndex(obj, 50)
/**
* Convert the id to a String
*/
def userIdAsString: String = id.get.toString
/**
* The first name field for the User. You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val firstName = new MyFirstName(this, 32) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val firstName: MappedString[T] = new MyFirstName(this, 32)
protected class MyFirstName(obj: T, size: Int) extends
MappedString(obj, size) {
override def displayName = fieldOwner.firstNameDisplayName
override val fieldId = Some(Text("txtFirstName"))
}
/**
* The string name for the first name field
*/
def firstNameDisplayName = S.?("first.name")
/**
* The last field for the User. You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val lastName = new MyLastName(this, 32) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val lastName: MappedString[T] = new MyLastName(this, 32)
protected class MyLastName(obj: T, size: Int) extends
MappedString(obj, size) {
override def displayName = fieldOwner.lastNameDisplayName
override val fieldId = Some(Text("txtLastName"))
}
/**
* The last name string
*/
def lastNameDisplayName = S.?("last.name")
/**
* The email field for the User. You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val email = new MyEmail(this, 48) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val email: MappedEmail[T] = new MyEmail(this, 48)
protected class MyEmail(obj: T, size: Int) extends MappedEmail(obj, size) {
override def dbIndexed_? = true
override def validations = valUnique(S.?("unique.email.address"))
_ :: super.validations
override def displayName = fieldOwner.emailDisplayName
override val fieldId = Some(Text("txtEmail"))
}
/**
* The email first name
*/
def emailDisplayName = S.?("email.address")
/**
* The password field for the User. You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val password = new MyPassword(this) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val password: MappedPassword[T] = new MyPassword(this)
protected class MyPassword(obj: T) extends MappedPassword(obj) {
override def displayName = fieldOwner.passwordDisplayName
}
/**
* The display name for the password field
*/
def passwordDisplayName = S.?("password")
/**
* The superuser field for the User. You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val superUser = new MySuperUser(this) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val superUser: MappedBoolean[T] = new MySuperUser(this)
protected class MySuperUser(obj: T) extends MappedBoolean(obj) {
override def defaultValue = false
}
def niceName: String = (firstName.get, lastName.get, email.get) match {
case (f, l, e) if f.length > 1 && l.length > 1 => f+" "+l+" ("+e+")"
case (f, _, e) if f.length > 1 => f+" ("+e+")"
case (_, l, e) if l.length > 1 => l+" ("+e+")"
case (_, _, e) => e
}
def shortName: String = (firstName.get, lastName.get) match {
case (f, l) if f.length > 1 && l.length > 1 => f+" "+l
case (f, _) if f.length > 1 => f
case (_, l) if l.length > 1 => l
case _ => email.get
}
def niceNameWEmailLink = <a href={"mailto:"+email.get}>{niceName}</a>
}
trait StringMegaProtoUser[T <: StringMegaProtoUser[T]] extends
StringProtoUser[T] {
self: T =>
/**
* The unique id field for the User. This field
* is used for validation, lost passwords, etc.
* You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val uniqueId = new MyUniqueId(this, 32) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val uniqueId: MappedUniqueId[T] = new MyUniqueId(this, 32)
protected class MyUniqueId(obj: T, size: Int) extends
MappedUniqueId(obj, size) {
override def dbIndexed_? = true
override def writePermission_? = true
}
/**
* The has the user been validated.
* You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val validated = new MyValidated(this, 32) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val validated: MappedBoolean[T] = new MyValidated(this)
protected class MyValidated(obj: T) extends MappedBoolean[T](obj) {
override def defaultValue = false
override val fieldId = Some(Text("txtValidated"))
}
/**
* The locale field for the User.
* You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val locale = new MyLocale(this, 32) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val locale = new MyLocale(this)
protected class MyLocale(obj: T) extends MappedLocale[T](obj) {
override def displayName = fieldOwner.localeDisplayName
override val fieldId = Some(Text("txtLocale"))
}
/**
* The time zone field for the User.
* You can override the behavior
* of this field:
* <pre name="code" class="scala">
* override lazy val timezone = new MyTimeZone(this, 32) {
* println("I am doing something different")
* }
* </pre>
*/
lazy val timezone = new MyTimeZone(this)
protected class MyTimeZone(obj: T) extends MappedTimeZone[T](obj) {
override def displayName = fieldOwner.timezoneDisplayName
override val fieldId = Some(Text("txtTimeZone"))
}
/**
* The string for the timezone field
*/
def timezoneDisplayName = S.?("time.zone")
/**
* The string for the locale field
*/
def localeDisplayName = S.?("locale")
}