3
votes

I am working on a project that uses Slick 1.0 and the cake pattern to connect to a postgresql database.
As it is right now, everything seems to work fine, but I have a lot more tables to add and I realize that there are a number of common columns that all the tables contain. I would like to be able to make a trait that contains the common fields, but I cannot figure out how to get this to work. (I am fairly new at scala, but I think that I have the basics down pretty well.)

Here is an example that will hopefully illustrate what I want to do:

One.scala:

    package models.db.slick
    import java.util.UUID
    import play.api.db.slick.Profile
    case class One(common1:UUID, common2:String, unique1:String)
    trait OneComponent{this: Profile =>
      import profile.simple._
      object Ones extends Table[One]("One") with CommonColumns{
        def unique1 = column[String]("unique1")
        def * = common1 ~ common2 ~ unique1 <> (One.apply _, One.unapply _)
      }
    }

ColumnColumns.scala:

    package models.db.slick
    import java.util.UUID
    import play.api.db.slick.Profile
    trait CommonColumns{
      def common1 = column[UUID]("common1")
      def common2 = column[String]("common2")
    }

This does not compile because the ColumnColumns trait doesn't know column[T]. I tried specifying a self type of Table, but I can't figure out how to get to the Table object which is itself in a the scala.slick.driver.BasicTableComponent trait. I also tried to specify a self type that implements a column function like:

    trait CommonColumns{ this => {def column[C](n: String, options:    
                                   scala.slick.lifted.ColumnOption[C]* )
                                   (implicit tm:scala.slick.lifted.TypeMapper[C]
                                    ): scala.slick.lifted.Column[C]}
    ...
    }

but that doesn't work. I most likely have the syntax wrong on that one, but I can't find a good example of how to do this.

What do you think? Is there a good way to get this done?

1
Haven't tested, but it seems that CommonColumns have to extend Table[T] or have its self type declared to be Table[T].pedrofurla
Yes, that is something that I tried to do, but I can't figure out how to actually specify that it is a Table[T] type. It says that type Table is not found. In 'Ones' I get to reference Table[T], because OneComponent is a self type of Profile. Then when tried to find where Table[T] is defined, it is an object inside the trait scala.slick.driver.BasicTableComponent, and I don't know how to use that in CommonColumns. I am pretty sure this is just a lack of scala knowledge on my part.spdaniel
I just realized that I've been saying that Table[T] is an Object in the Trait, but it is actually an abstract class in the trait. So if I try to say that CommonColumns is a self type of slick.driver.BasicTableComponent.Table[T], I get a message about BasicTableComponent being a trait without a companion Objectspdaniel

1 Answers

3
votes

I figured it out! At least I think I did. If anyone notices something wrong with this, please let me know.

OK, so here is how I did it:

I changed the CommonColumns trait to be:

    trait CommonColumnsComponent{ this:Profile =>
      import profile.simple._
      trait CommonColumns{ this:Table[_] =>
        def common1 = column[UUID]("common1")
        def common2 = column[String]("common2")
      }
    }

and then I changed OneComponent to:

    trait OneComponent extends CommonColumnsComponent{this: Profile =>
      import profile.simple._
      object Ones extends Table[One]("One") with CommonColumns{
        def unique1 = column[String]("unique1")
        def * = common1 ~ common2 ~ unique1 <> (One.apply _, One.unapply _)
      }
    }

and it worked.