我已将我的模型定义如下:
object Curr extends Curr with LongKeyedMetaMapper[Curr] with CRUDify[Long, Curr] {
}
class Curr extends LongKeyedMapper[Curr] with IdPK with CreatedUpdated {
def getSingleton = Curr
object code extends MappedString(this, 100)
object name extends MappedString(this, 100)
}
object Country extends Country with LongKeyedMetaMapper[Country] with CRUDify[Long, Country] {
}
class Country extends LongKeyedMapper[Country] with IdPK with CreatedUpdated {
def getSingleton = Country
object name extends MappedString(this, 100)
object currid extends MappedLongForeignKey(this, Curr) {
override def asHtml = {
<span>{Curr.find(By(Curr.id, this)).map(c => (c.name + " " + c.code)).openOr(Text(""))}</span>
}
override def validSelectValues: Box[List[(Long, String)]] =
Full(Curr.findAll(OrderBy(Curr.name, Ascending)).map(c => (c.id.is, c.code.is)))
}
}
我将拥有许多此类模型,并且我希望为具有外键的许多模型删除定义asHtml
和validSelectValues
的冗余。我想我可以用一个特性MyField
做到这一点,它会混合到我的模型中,如下所示:
object currid extends {val MyModel = Curr } MappedLongForeignKey(this, Curr) with MyField[Curr] {
将特征定义为:
trait MyField[T <: LongKeyedMetaMapper[T] with IdPK] {
val MyModel: T
override def asHtml = {
<span>{MyModel.find(By(MyModel.id, this)).map(c => (c.name + " " + c.name)).openOr(Text(""))}</span>
}
override def validSelectValues: Box[List[(Long, String)]] =
Full(MyModel.findAll(OrderBy(MyModel.name, Ascending)).map(c => (c.id.is, c.name.is)))
}
如上所述,我的特质不起作用。以下是编译器生成的错误:
No implicit view available from net.liftweb.mapper.MyField[T] => Long.
[error] <span>{MyModel.find(By(MyModel.id, this)).map(c => (c.name + " " + c.name)).openOr(Text(""))}</span>
[error] ^
value name is not a member of type parameter T
[error] Full(MyModel.findAll(OrderBy(MyModel.name, Ascending)).map(c => (c.id.is, c.name.is)))
[error] ^
我会确保每个MyModel
都有name
个成员。任何人都可以建议如何实现这个特性吗?
谢谢!
答案 0 :(得分:1)
我找到了解决方案。我创建了自己的KeyedMapper,MetaMapper和MappedForeignKey。在示例中,MyData和MyForeignData是两个数据库表,MyData包含MyForeignData的外键。包含CRUDify,您可以在浏览器中查看和编辑与表列一起显示的外键 override def primaryKeyDisplayField = table_column_field
import scala.xml._
import net.liftweb.common._
import net.liftweb.mapper._
import net.liftweb.util._
trait MyMapper[OwnerType <: MyMapper[OwnerType]]
extends LongKeyedMapper[OwnerType] with IdPK {
self: OwnerType =>
}
trait MyMetaMapper[A <: MyMapper[A]]
extends LongKeyedMetaMapper[A]
with LongCRUDify[A] {
self: A =>
def primaryKeyDisplayField: BaseOwnedMappedField[A] = null
}
abstract class MyMappedForeignKey[T<:MyMapper[T], O<:MyMapper[O]](theOwner: T, _foreignMeta: => MyMetaMapper[O])
extends MappedLongForeignKey[T, O](theOwner, _foreignMeta) {
override def foreignMeta = _foreignMeta
override def dbIndexed_? = true
override def asHtml = {
<span>{foreignMeta.findByKey(this.get)
.map(_.fieldByName(foreignMeta.primaryKeyDisplayField.name).openOr(Text("Error"))).openOr(Text("ERROR MyMappedForeignKey"))}</span>
}
override def validSelectValues/*: Box[List[(Long, String)]]*/ = {
Full(foreignMeta.findAll(/*OrderBy(foreignMeta.primaryKeyField, Ascending)*/)
.map(i => (i.id.get,
i.fieldByName(foreignMeta.primaryKeyDisplayField.name).openOr(Text("ERROR")).toString())))
}
}
class MyData extends MyMapper[MyData] {
def getSingleton = MyData
object myForeignData extends MyMappedForeignKey(this, MyForeignData)
object name extends MappedString(this, 30)
}
object MyData extends MyData with MyMetaMapper[MyData] { }
class MyForeignData extends MyMapper[MyForeignData] {
def getSingleton = MyForeignData
object name extends MappedString(this, 30)
}
object MyForeignData extends MyForeignData with MyMetaMapper[MyForeignData] {
override def primaryKeyDisplayField = name
}