Reputation: 2168
I have:
case class One(someParam: String) {
private val _defaultTimeout = readFromConfig("defaultTimeout")
val timeout: Timeout = akka.util.Timeout(_defaultTimeout seconds)
val info: Option[Info] = Await.result(someSmartService.getInformationForSomething(someParam)), timeout.duration)
}
I'm building a service, which will obscure (encrypt) some sensitive data. I'm doing it in a such way:
def encrypt(oldOne: One): One = {
val encryptedSomeParam = EncryptService.getHash(oldOne.someParam)
val encryptedInfo = encryptInfo(oldOne.info)
// what to do with that? ^^
one.copy(someParam = encryptedSomeParam)
}
Also, I need to encrypt some data inside this "info" field of class One. The issue is that it is a val and I cannot reassign the value of a val. Is there an easy way how to do that? For now I'm thinking about changing it to a var, but I think it's not the best way to do that. Also, I cannot write encrypted data to this value from the beginning like this:
val info: Option[Info] = EncryptionService.encrypt(someSmartService.getInformationForSomething(someParam))
As this field is used in other places where I need the fields to be not encrypted. I want to encrypt sensitive data before the persistence of the object to a database.
Any ideas?
Thanks in advance!
EDIT: I know, that this looks like a bad design, so if someone has a better idea how to deal with it I'm looking forward to hear from you :)
Upvotes: 0
Views: 2120
Reputation: 12852
Why not make info
a case class argument as well?
case class One(someParam: String, info: Option[Info])
You could implement a default value for info
by defining the companion object like
object One {
def apply(someParam: String): One = One(someParam, someSmartService.getInformationForSomething(someParam))
}
That would allow you to work with One
s as follows:
One("foo")
One("foo", Some(...))
One(encryptedSomeParam, encryptedInfo)
One("plaintext").copy(someParam = encryptedSomeParam, info = encryptedInfo)
EDIT 1: Lazy info
Case classes cannot have lazy val arguments, i.e., neither info: => Option[String]
nor lazy val info: Option[String]
is allowed as an argument type.
You could make info
a parameter-less function, though
case class One(someParam: String, info: () => Option[String])
object One {
def apply(someParam: String): One = One(someParam, () => Some(someParam))
}
and then use it as
One("hi", () => Some("foo"))
println(One("hi", () => None).info())
This is obviously not ideal since it is not possible to introduce these changes without breaking code client code. Better solutions are welcome.
EDIT 2: Lazy info, no case class
If you don't insist on One
being a case class (for example, because you really need copy
), you could use a regular class with lazy values and a companion object for easy use:
class One(_someParam: String, _info: => Option[String]) {
val someParam = _someParam
lazy val info = _info
}
object One {
def apply(someParam: String): One = new One(someParam, Await.result(...))
def apply(someParam: String, info: => Option[String]): One = new One(someParam, info)
def unapply(one: One) = Some((one.someParam, one.info))
}
Upvotes: 2