2013-09-26 2 views
6

Ich habe eine PostgreSQL-Tabelle mit einem enum, die erstellt wird:Wie kann ich einen benutzerdefinierten Spaltentyp mit TypeSafe Slick in Scala erstellen?

CREATE TYPE file_status AS ENUM ('new', 'uploading', 'queued', 'processing', 'done', 'failed'); 

und ein zugehöriges Feld

CREATE TABLE files (... 
    status file_status NOT NULL, 
    ... 
); 
Slick 1.0.1

Mit Scala 2.10 und Typesafe, die ich angelegt habe Mappings Meine Dateien Tabelle, die mit Ausnahme des status Felds, das den benutzerdefinierten Typ file_status Typ eine Zeichenfolge, eine große Zeichenfolge funktioniert.

def status = column[FileStatus]("status") 

Ich habe mit Slicks TypeMapper spielen, kann aber nicht ganz herausfinden, wie man es an die Arbeit:

sealed trait FileStatus 

implicit val fileStatusMapper: TypeMapper[String] = base[FileStatus, String](
    s => s.toString, 
    f => f(FileStatus) 
) 

ich den Fehler: Typenkonflikt; gefunden: models.Files.FileStatus.type erforderlich: Int

Warum wird ein Int benötigt? Liegt es am TypeMapper? Ich habe auch versucht

... 
f => f.toString 
// type mismatch; found : String required: models.Files.FileStatus 

f => f 
// type mismatch; found : String required: models.Files.FileStatus 

Vielen Dank für alle Hinweise in mir helfen, diese Zuordnung zu verstehen.

Antwort

9

von den docs Zitiert (http://slick.typesafe.com/doc/1.0.1/lifted-embedding.html#user-defined-functions-and-types):

// An algebraic data type for booleans 
sealed trait Bool 
case object True extends Bool 
case object False extends Bool 

// And a TypeMapper that maps it to Int values 1 and 0 
implicit val boolTypeMapper = MappedTypeMapper.base[Bool, Int](
    { b => if(b == True) 1 else 0 }, // map Bool to Int 
    { i => if(i == 1) True else False } // map Int to Bool 
) 

Anpassung dieser Status in Datei:

sealed trait FileStatus 
case object New extends FileStatus 
case object Uploading extends FileStatus 
... 

implicit val fileStatusTypeMapper = MappedTypeMapper.base[FileStatus, String](
    { 
    case New => "new" 
    case Uploading => "uploading" 
    ... 
    },{ 
    case "new" => New 
    case "uploading" => Uploading 
    ... 
    } 
) 

Update:

Eine andere, weniger redundant, aber möglicherweise auch weniger klar Version:

sealed trait FileStatus 
case object New extends FileStatus 
case object Uploading extends FileStatus 
... 

val statusMap = Map(
    New -> "new", 
    Uploading -> "uploading", 
    ... 
) 

implicit val fileStatusTypeMapper = MappedTypeMapper.base[FileStatus, String](
    statusMap, 
    statusMap.map(_.swap) 
) 
+0

Ahhh, danke - die Schaffung Fall Objekte war das Stück, das ich hüpfte, egal aus welchem ​​Grund. Danke @cvogt – jbnunn

+0

Update: eine alternative Implementierung hinzugefügt :) – cvogt

1

Slick 3.x Version:

sealed trait FileStatus 
    case object New extends FileStatus 
    case object Uploading extends FileStatus 
    ... 

    implicit val fileStatusColumnType = MappedColumnType.base[FileStatus, String](
    { 
    case New => "new" 
    case Uploading => "uploading" 
    ... 
    },{ 
    case "new" => New 
    case "uploading" => Uploading 
    ... 
    } 
)