Search code examples
scalalifttraits

How does one replace the trait IdPK with a custom trait that uses a String Primary Key instead of Long Primary Key?


Yet another trait question :-(

I am mixing in the IdPK trait into my Lift Mapper models as follows:

class Test1 extends LongKeyedMapper[Test1] with IdPK {

I would like to switch to using String indexes instead of Long indexes (I don't want to but I have to, for now). I am trying to write a trait StringIdPK to replace the IdPK trait. Here is my attempt:

trait StringIdPK /* extends BaseLongKeyedMapper */ {  
  self: KeyedMapper[String] =>  
  def primaryKeyField = id  
  object id extends MappedStringIndex(this, 50)  
}

(I based this on the IdPK trait which is as follows:

trait IdPK /* extends BaseLongKeyedMapper */ {  
  self: BaseLongKeyedMapper =>  
  def primaryKeyField = id  
  object id extends MappedLongIndex[MapperType](this.asInstanceOf[MapperType])  
} 

the code for this trait can be found here)

When I try to compile, I get the following error:

wrong number of type arguments for net.liftweb.mapper.KeyedMapper, should be 2

The specification for KeyedMapper (which can be found here) is:

trait KeyedMapper[KeyType, OwnerType <: KeyedMapper[KeyType, OwnerType]] extends Mapper[OwnerType] with BaseKeyedMapper

I need to better understand what OwnerType <: KeyedMapper[KeyType, OwnerType] means and how to accommodate it in my custom trait above. So my question is: what am I doing wrong in my definition of the trait StringIdPK above? (This will help me to understand how to deal with OwnerType <: KeyedMapper[KeyType, OwnerType]).

Thanks!

UPDATE: I think the following comes close to solving it (see below - I took some of the code from here). It is still not quite right, since the compiler still complains about the FK objects I extended not having foreign meta defined.

trait BaseStringKeyedMapper extends BaseKeyedMapper{
    override type TheKeyType = String
}

trait StringKeyedMapper[OwnerType <: StringKeyedMapper[OwnerType]] extends KeyedMapper[String, OwnerType] with BaseStringKeyedMapper {
    self: OwnerType =>
}


trait StringKeyedMetaMapper[A <: StringKeyedMapper[A]] extends KeyedMetaMapper[String, A] {
    self: A =>
}

trait StringIdPK {  
  self: BaseStringKeyedMapper =>  
  def primaryKeyField = id  
  object id extends MappedStringIndex[MapperType](this.asInstanceOf[MapperType], 50)  
} 

Also, there was a posting about this issue on the lift google group here, but it seems unresolved.


Solution

  • I think the following solves it (I'm unable to confirm right now because I am working through another issue before I can really test it, but this seems to work so far. I took some of the code from here and here. I will update this as I learn more about this implementation):

    trait BaseStringKeyedMapper extends BaseKeyedMapper{
        override type TheKeyType = String
    }
    
    trait StringKeyedMapper[OwnerType <: StringKeyedMapper[OwnerType]] extends KeyedMapper[String, OwnerType] with BaseStringKeyedMapper {
        self: OwnerType =>
    }
    
    trait StringKeyedMetaMapper[A <: StringKeyedMapper[A]] extends KeyedMetaMapper[String, A] {
        self: A =>
    }
    
    trait StringIdPK {  
      self: BaseStringKeyedMapper =>  
      def primaryKeyField = id  
      object id extends MappedStringIndex[MapperType](this.asInstanceOf[MapperType], 50) {
          override def writePermission_? = true // if u want to set it via your code, keep this true
          override def dbAutogenerated_? = false
          override def dbNotNull_? = true
    
          // override def writePermission_? = false
          override def readPermission_? = true
          override def shouldDisplay_? = true
          override def show_? = true
          override def dbDisplay_? = true
          override def validations = valUnique(S.?("Must be unique")) _ :: super.validations
      }
    } 
    

    I've added some overrides to the id field for mixing this in along with CRUDify. For some reason that I cannot figure out, valUnique does not work (other validations such as valMinLen do work, however). I will post a new question about this.