如何将一个特性与一个扩展MappedLongForeignKey的对象混合在一起,这将覆盖def asHtml和def validSelectValues?

时间:2014-09-16 02:55:34

标签: scala lift traits

我已将我的模型定义如下:

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))) 
    }
}

我将拥有许多此类模型,并且我希望为具有外键的许多模型删除定义asHtmlvalidSelectValues的冗余。我想我可以用一个特性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个成员。任何人都可以建议如何实现这个特性吗?

谢谢!

1 个答案:

答案 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
}