关于 scala:如何制作一个特征以与扩展 MappedLongForeignKey 的对象混合,该对象将覆盖 def asHtml 和 def validSelectValues?

How do I make a trait to mix in with an object that extends MappedLongForeignKey, that will override def asHtml and def validSelectValues?

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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 来做到这一点,它会混合到我的模型中,如下所示:

1
object currid extends {val MyModel = Curr } MappedLongForeignKey(this, Curr) with MyField[Curr] {

特征被定义为:

1
2
3
4
5
6
7
8
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)))
}

我的特质,如上所述,不起作用。这是编译器生成的错误:

1
2
3
4
5
6
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 成员。任何人都可以就如何实现这个特性提出建议吗?

谢谢!


我找到了解决办法。我创建了自己的 KeyedMapper、MetaMapper 和 MappedForeignKey。在示例中 MyData 和 MyForeignData 是两个数据库表,MyData 包含 MyForeignData 的外键。包含 CRUDify,您可以在浏览器中查看和编辑与表列一起显示的外键
覆盖 def primaryKeyDisplayField = table_column_field

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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
}