Reputation: 99
I am using play framework and slick, play framework uses a case map in the form validation but there are values that I don't need validated as they are not inputed by the user, e.g. the ID & Date which is done is provided on the backend.
By the end I would like to have a class case like this, to provide to Slick and use with my Table.
case class Order(id: Long, order: String, date: Date)
For Play's Form validation I would provide a seperate case class:
case Class inputableOrder(order: String)
Can I then create the Order class that will grab the variables from inputableOrder and added it the Order class?
case class Order(id: Long, date: Date) // <- some way to add the variable from inputableOrder?
I'm just trying to prevent repetition but I still need two different case classes (one for form validation and another for working with the database).
Is there a way to modify an existing case Class , remove a variable or modify a variable type?
Upvotes: 0
Views: 268
Reputation: 63419
I think you have several options here:
Make InputableOrder
a part of Order
:
case class InputableOrder(order: String) // ...
case class Order(input: InputableOrder, id: Long, date: Date) // ..
This is probably the most idiomatic solution. But it can be inflexible if you later realize that InputableOrder
needs something that shouldn't be in Order
.
Make Order
a subclass of InputableOrder
. In this case there is some code repetition when passing arguments to the superclass, and the superclass can't be a case
class, so you have to declare it as a regular class and create an extractor yourself:
class InputableOrder(val order: String) // ...
object InputableOrder {
def unapply(o: InputableOrder): Option[String] = Some(o.order);
// if you have more than one constructor arguments, return
// a tuple like Option[(String,String)] etc.
}
case class Order(override val order: String, id: Long, date: Date)
extends InputableOrder(order) // ...
Again, the same problems can arise as with the previous point.
Make the classes distinct and create helper methods to convert between them. The choice depends on your design, but I find this solution to be most flexible:
case class InputableOrder(order: String);
case class Order(order: String, id: Long, date: java.util.Date) {
// An additional constructor to use when converting from Inputable:
def this(other: InputableOrder, id: Long, date: java.util.Date) =
this(other.order, id, date);
// Update this instance with `other`:
def this(that: Order, other: InputableOrder) =
this(other, that.id, that.date);
def toInput = InputableOrder(order);
}
This way you can create an Order
from an InputableOrder
just by supplying the missing fields and vice versa. You need to write these helper methods/constructors once, but using them is then easy.
You can also use implicit methods such as
implicit def toInput(other: InputableOrder): Order = other.toInput;
to make things even easier.
Upvotes: 4