3

Currently I have a method that accept ModelA and know to perform actions on it.

so in my controller I accept request of ModelA and call this method with it.

And now, I want to be able to accept request of ModelB, map the request to be of ModelA (cause it has the same data just not all of it and in different names), and call this method with it.

lets say the method would look like:

def myMethod(data: ModelA): ResModel = {
    // do something with data
}

my controller currrently would be:

def doActions(): Action[JValue] = { request => 
    val dataExctracted = request.body.extract[ModelA]
    myMethod(dataExctracted)
    ...
}

and both of my models are just case classes in seperate files:

case class ModelA(a: String, b: String, c: String)

case class ModelB(aAsDifferentName: String, bAsDifferntName: String)

What would be the best practice of Scala to have the myMethod accept both Models (without Either) ? and how the controller should look like in reaction to that?

is there also a classic way to return different models without having to accept the calls in different controller methods?

Thanks!

jack miao
  • 1,398
  • 1
  • 16
  • 32

1 Answers1

-1

You can try to model the union type (like Int | String in Dotty).

Something like this:

scala> case class Or[A, B](a: A, b: B)
defined class Or

scala> def test(v: Int Or String): String = {
     | v.toString
     | }
test: (v: Or[Int,String])String

scala> implicit def Int2Or(x: Int): Int Or String = Or(x, "")
Int2Or: (x: Int)Or[Int,String]

scala> implicit def String2Or(x: String): Int Or String = Or(-1, x)
String2Or: (x: String)Or[Int,String]

scala> test(1)
res0: String = Or(1,)

scala> test("")
res1: String = Or(-1,)

The cool thing is, you can use the Or class like this String Or Boolean, but this is definitely not the real union type from Dotty.

In my opinion the strait forward solution is using a sealed trait and do pattern matching.

codejitsu
  • 3,162
  • 2
  • 24
  • 38
  • The issue is how do you know what `Or(-1, "")` is? case class is a product type when what we want is a union type (sealed trait). The straight-forward solution is to do neither and use a different route! :p – Andy Hayden Oct 20 '17 at 06:12
  • 1
    @AndyHayden good point! Sure, as I said, more simple solution is to use trait or even overloaded methods. – codejitsu Oct 20 '17 at 06:19
  • How is this an improvement on just using `Either`? OP said they didn't want to use `Either`, but your `Or` is just `Either` under a different name, except (as Andy points out) mis-implemented. – Seth Tisue Oct 20 '17 at 18:20