1

I'm doing R&D whether we should or should not use Scala 2.11/Play 2.4/Slick 3.1 stack for out new app. I did some Scala programming few years ago and kept it as my favourite language for small personal projects but advanced concepts still are a mystery to me.

After reading this blog post by Matt Handler I want to replicate this behaviour in my PoC app but I run into some problems.

case class BaseModel[A] (id: Long, model: A)

object BaseModel {
  import scala.language.implicitConversions
  implicit def toModel[A](modelWithId: BaseModel[A]): A = modelWithId.model
}

case class Ingredient(name: String, description: String)

class IngredientsTable(tag: Tag) extends Table[BaseModel[Ingredient]](tag, "ingredients") {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def name = column[String]("name")
  def description = column[String]("description")

  def * = (id, name, description) <> ??? // ((BaseModel[Ingredient].apply _).tupled, BaseModel[Ingredient].unapply)
}

My question is what should I place instead of ??? as commented out pard doesn't work for obvious reason? I know I need to create there a custom Slick shape so it boxes/unboxes contained model val but how should I do it (Slick docs aren't too helpful in this matter)?

I tried to do something like that based on this answer but it gives me compile error as I taken this from earlier Slick version and apparently I don't understand what is going on here.

def * = (id, name, description) <> (
    (id, name, description) => BaseModel[Ingredient](id, Ingredient(name, description)),
    (f: BaseModel[Ingredient]) => Some((f.id, f.name, f.description))
  )

Hopefully I'm looking for something more automatic (overriden tupled, unapply in BaseModel?) but anything working and any help at all appreciated. Even RTFM if pointed to the right place.

EDIT: JimN suggested an answer which works but needs quite a lot of boilerplate when creating each such mapping. Could you suggest an answer which would minimize the amount of boilerplate?

Here is what's added to the IngredientsTable:

def toBaseModel(id: Long, name: String, description: String): BaseModel[Ingredient] = {
  BaseModel[Ingredient](id, Ingredient(name, description))
}

def fromBaseModel(m: BaseModel[Ingredient]): Option[(Long, String, String)] = {
  Some((m.id, m.name, m.description))
}

def * = (id, name, description) <> ((toBaseModel _).tupled, fromBaseModel)
Community
  • 1
  • 1
Oskar Gargas
  • 95
  • 1
  • 6

1 Answers1

1

This compiles for me:

def * = (id, name, description) <> ((toBaseModelIngredient _).tupled, fromBaseModelIngredient)

... 

def toBaseModelIngredient(id: Long, name: String, description: String): BaseModel[Ingredient] = ??? // implement this
def fromBaseModelIngredient(m: BaseModel[Ingredient]): Option[(Long, String, String)] = ??? // implement this
JimN
  • 3,120
  • 22
  • 35
  • Unfortunately it does not for me. I get the following error: http://pastebin.com/R9PtCrg7 I did: `def toBaseModelIngredient = BaseModel[Ingredient](id, Ingredient(name, description))` `def fromBaseModelIngredient = Some((m.id, m.name, m.description))` Am I missing something? – Oskar Gargas Nov 09 '15 at 22:22
  • Nvm, of course it works. It was a stupid mistake on my side (left some debug changes which caused conflict). Upvoting but will not mark as answered for next day or two as I hope to get some more automatic solution. – Oskar Gargas Nov 09 '15 at 22:36