2013-09-26 177 views
6

Tôi có một bảng PostgreSQL với một enum, được tạo ra bởi:Làm cách nào để tạo loại cột tùy chỉnh với Typesafe Slick trong Scala?

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

và một lĩnh vực liên quan đến

ánh xạ
CREATE TABLE files (... 
    status file_status NOT NULL, 
    ... 
); 

Với Scala 2.10 và typesafe Slick 1.0.1, tôi đã tạo ra để bảng Tệp của tôi hoạt động tốt với ngoại lệ trường status, yêu cầu loại file_status tùy chỉnh, một chuỗi.

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

Tôi đã chơi với TypeMapper Slick, nhưng có thể không hoàn toàn tìm ra cách để có được nó để làm việc:

sealed trait FileStatus 

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

tôi nhận được lỗi: loại không phù hợp; được tìm thấy: models.Files.FileStatus.type bắt buộc: Int

Tại sao yêu cầu Int? Có phải vì TypeMapper không? Tôi cũng đã thử

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

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

Cảm ơn bạn đã tìm mọi hướng dẫn giúp tôi hiểu bản đồ này.

Trả lời

9

Trích dẫn từ các tài liệu (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 
) 

Thích ứng này để nộp status:

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

Cập nhật:

khác, ít dư thừa, nhưng có thể cũng chưa rõ ràng phiên bản:

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, cảm ơn bạn - tạo các đối tượng trường hợp là mảnh tôi đã bỏ qua, vì lý do gì. Cảm ơn @cvogt – jbnunn

+0

Cập nhật: đã thêm một triển khai thay thế :) – cvogt

1

Slick phiên bản 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 
    ... 
    } 
)