Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I create traits to represent enum values for my models?

Tags:

scala

slick

Say I have a model like:

case class User(
 id: Int,
 name: String,
 userType: Int)

Should I then do this:

sealed trait UserType
case object Member() extends UserType
case object Anonymous() extends UserType

I should also somehow associate a value for each UserType.

I would then change the User case class to have a UserType property instead of the int?

I guess then I would create a implicit converter for slick, which I believe would be a MappedColumnType from int to UserType.

Update This is for using slick db access.

like image 638
Blankman Avatar asked Mar 08 '26 22:03

Blankman


2 Answers

I would do it the other way around. I would have a type for the user depending on the scenario that extends User:

sealed trait User
case class NormalUser(name: String, id: Int) extends User
case class SuperUser(name: String, id: Int, superPowers: Map[String, String]) extends User

And then pattern match on the actual User type when needed.

like image 76
Yuval Itzchakov Avatar answered Mar 11 '26 13:03

Yuval Itzchakov


I'd go with enum:

object UserType extends Enumeration {
  type UserType = Value

  val Member = Value("Member")
  val Anonymous = Value("Anonymous")
}

And the converter as you said:

implicit val userTypeColumnType = MappedColumnType.base[UserType, String](
  userType => userType.toString,
  UserType.withName
)

Then you can use userType: UserType in your User case class. In table definition you can have def userType = column[UserType]("user_type")

Update One of the reasons for choosing enum over trait is that slick is not able to find this implicit converter when you do not put the supertype explicitly. E.g.

.filter(_.userType === Member)

yields

type mismatch;
[error]  found   : Member.type
[error]  required: slick.lifted.Rep[?]
[error]       .filter(_.userType === Member).result

But the following works

.filter(_.userType === Member.asInstanceOf[UserType])

.filter(_.userType === (Member : UserType))
like image 21
Michal Tomanski Avatar answered Mar 11 '26 15:03

Michal Tomanski