Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create projection class for complex case class in slick?

For example I have this case class:

case class User(
  var identityId: IdentityId, //Its a user created class
  var firstName: String,
  var lastName: String,
  var fullName: String,
  var email: Option[String],
  var avatarUrl: Option[String],
  var authMethod: AuthenticationMethod,
  var oAuth1Info: Option[OAuth1Info] = None,
  var oAuth2Info: Option[OAuth2Info] = None,
  var passwordInfo: Option[PasswordInfo] = None) extends Identity {

  def this() = this(null, "", "", "", None, None, null, None, None, None)

}

Its actually a securesocial identity, now identityId is an object of case class:

case class IdentityId(
var userId:String,
var providerId:String
)

So how do I create a projection class for situations like, this?? If I had to create a projection class datatypes like String,Int it would have been no problem but what about user defined objects and classes??

like image 991
mane Avatar asked Aug 16 '14 12:08

mane


1 Answers

I did some research and found some very useful answers here Link1 and Link2

The second link didn't have implementations for PasswordInfo so, here I have provided my own implementation, though this approach seems a bit more code, can anyone suggest a more efficient approach that is if there is one:

*Note: And the second link was very helpful, its actually whole working project example Based on Play, Slick and SecureSocial thanks to Lunatech and others.

class Users(tag: Tag) extends Table[User](tag, "user") {

  implicit def string2AuthenticationMethod = MappedColumnType.base[AuthenticationMethod, String](
    authenticationMethod => authenticationMethod.method,
    string => AuthenticationMethod(string))

  implicit def tuple2OAuth1Info(tuple: (Option[String], Option[String])): Option[OAuth1Info] = tuple match {
    case (Some(token), Some(secret)) => Some(OAuth1Info(token, secret))
    case _ => None
  }

  implicit def tuple2OAuth2Info(tuple: (Option[String], Option[String], Option[Int], Option[String])): Option[OAuth2Info] = tuple match {
    case (Some(token), tokenType, expiresIn, refreshToken) => Some(OAuth2Info(token, tokenType, expiresIn, refreshToken))
    case _ => None
  }

  implicit def tuple2PasswordInfo(tuple: (Option[String], Option[String], Option[String])) = tuple match {
    case (Some(hasher), Some(password), salt) =>
      Some(PasswordInfo(hasher, password, salt))
    case _ => None
  }

  implicit def tuple2IdentityId(tuple: (String, String)): IdentityId = tuple match {
    case (userId, providerId) => IdentityId(userId, providerId)
  }

  def uid = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def userId = column[String]("userId")
  def providerId = column[String]("providerId")
  def email = column[Option[String]]("email")
  def firstName = column[String]("firstName")
  def lastName = column[String]("lastName")
  def fullName = column[String]("fullName")
  def authMethod = column[AuthenticationMethod]("authMethod")
  def avatarUrl = column[Option[String]]("avatarUrl")
  // oAuth 1
  def token = column[Option[String]]("token")
  def secret = column[Option[String]]("secret")
  // oAuth 2
  def accessToken = column[Option[String]]("accessToken")
  def tokenType = column[Option[String]]("tokenType")
  def expiresIn = column[Option[Int]]("expiresIn")
  def refreshToken = column[Option[String]]("refreshToken")
  //PasswordInfo
  def hasher = column[Option[String]]("hasher")
  def password = column[Option[String]]("password")
  def salt = column[Option[String]]("salt")

  def * : ProvenShape[User] = {
    val shapedValue = (
      userId,
      providerId,
      firstName,
      lastName,
      fullName,
      email,
      avatarUrl,
      authMethod,
      token,
      secret,
      accessToken,
      tokenType,
      expiresIn,
      refreshToken,
      hasher,
      password,
      salt).shaped
    shapedValue.<>({
      tuple =>
        User.apply(
          identityId = tuple2IdentityId(tuple._1, tuple._2),
          firstName = tuple._3,
          lastName = tuple._4,
          fullName = tuple._5,
          email = tuple._6,
          avatarUrl = tuple._7,
          authMethod = tuple._8,
          oAuth1Info = (tuple._9, tuple._10),
          oAuth2Info = (tuple._11, tuple._12, tuple._13, tuple._14),
          passwordInfo = (tuple._15, tuple._16, tuple._17))
    }, {
      (u: User) =>
        Some {
          (u.identityId.userId,
            u.identityId.providerId,
            u.firstName,
            u.lastName,
            u.fullName,
            u.email,
            u.avatarUrl,
            u.authMethod,
            u.oAuth1Info.map(_.token),
            u.oAuth1Info.map(_.secret),
            u.oAuth2Info.map(_.accessToken),
            u.oAuth2Info.flatMap(_.tokenType),
            u.oAuth2Info.flatMap(_.expiresIn),
            u.oAuth2Info.flatMap(_.refreshToken),
            u.passwordInfo.map(_.hasher),
            u.passwordInfo.map(_.password),
            u.passwordInfo.flatMap(_.salt))
        }
    })
  }
}
like image 55
mane Avatar answered Sep 21 '22 10:09

mane