4

Implementing my domain model in scala using case classes I got

abstract class Entity { val _id: Option[BSONObjectID] val version: Option[BSONLong] } 

and several case classes defining the different entities like

case class Person ( _id: Option[BSONObjectID], name: String, version: Option[BSONLong] ) extends Entity 

What I need is a way to set the _id and version later on from a generic method which operates on an Entity because I have to share this behavior over all Entities and want to avoid writing it down hundreds of times ;-). I would love to be able to

def createID(entity: Entity): Entity = { entity.copy(_id = ..., version = ...) } 

...but of course this does not compile since an Entity has no copy-method. It is generated for each single case class by the compiler...

What is the best way to achieve this in scala?

To prevent somebody asking: I have to use case classes since this is what the third-party-library is extracting for me from the requests I get and the case class instances are what is serialized back to BSON / MongoDB later on...

3
  • possible duplicate of Create common trait for all case classes supporting copy(id=newId) method Commented Mar 9, 2013 at 20:14
  • Why not factor out the _id and version bit? You would have a case class Entity[T](_id: ..., version: ..., data: T). T would be probably another case class with the appropriate data. Commented Mar 9, 2013 at 22:37
  • Sorry, but as I mentioned the case class instances (including id and version) are created by a third-party-library and therefore this is not an option here. Commented Mar 9, 2013 at 23:17

2 Answers 2

3

Indeed one can find a way to implement something like this at

Create common trait for all case classes supporting copy(id=newId) method

but since it is quite complicated for my use case I would prefer just to create two new classes

class MongoId(var id : BSONObjectID = null) { def generate = { id = BSONObjectID.generate } } class MongoVersion(var version: Long = 0) { def update = { version = System.currentTimeMillis } } 

and implemented the shared behavior regarding these fields there. Of course you have to change the definition of your base class accordingly:

abstract class Entity { def _id: MongoId def version: MongoVersion } 

To make it clear: This works only if the behavior you want to share over several case classes does only affect (in my case changes) one attribute ...

Sign up to request clarification or add additional context in comments.

Comments

0

Would implementing a trait work?

trait MongoIdHandler { def createId(entity : Entity) : Option[BSONObjectID] = { ..} def setVersion(version : String) : Unit = { ..} } case class Person (..) with MongoIdHandler .. 

If any of the instances require specialized versions of the id generator they can override the 'default' impl provided by the trait.

1 Comment

No, unfortunately it does not help since I have to change the id-value of the Person since the Person is the object that gets serialized to BSON/MongoDB later on. I was not able to find a way to change the value of the field from any method of not knowing the exact type of the Entity (like Person in this example)...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.