2013-09-26 3 views
6

Ho una tabella di PostgreSQL con un enum, che viene creato da:Come posso creare un tipo di colonna personalizzato con Typesafe Slick in Scala?

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

e di un campo associato

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

Con Scala 2.10 e Typesafe Slick 1.0.1, che ho creato per la mia tabella Files funziona perfettamente con l'eccezione del campo status, che richiede il tipo personalizzato file_status, una stringa.

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

Ho giocato con TypeMapper di Slick, ma non riesco a capire come farlo funzionare:

sealed trait FileStatus 

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

ottengo l'errore: tipo non corrispondente; trovato: model.Files.FileStatus.type richiesto: Int

Perché è necessaria una Int? È a causa di TypeMapper? Ho anche provato

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

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

Grazie per tutti i puntatori per aiutare a capire questa mappatura.

risposta

9

Citando la documentazione (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 
) 

Adattare questo file di stato:

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

Aggiornamento:

Un altro, meno ridondante, ma forse anche meno chiaro versione:

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, grazie - la creazione di oggetti caso è stato il pezzo che stavo saltando, per qualsiasi motivo. Grazie @cvogt Aggiornamento – jbnunn

+0

: aggiunta un'implementazione alternativa :) – cvogt

1

Slick versione 3.x:

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