Appearance
Referencing Obejcts
In Vasat a model is ANY case class, there is no restriction on what fields it can and cant have. The problem with this approach is that there is additional metadata asscoiated with an object that Vasat must store. Fields like id, and dateMade are universal and apply to whatever object you might have.
The solution in Vasat is the Ref[A]
object
ResolvedRef
A resolved reference is the object in question as well as the metadata for that object
scala
case class User(firstName:String, lastName:String, email:Option[String])
val u:User = ???
Ref("1234", u)
A ResolvedRef is also designed to be serialisable to a JSON format
The above eample will display as:
json
{
id:"1234",
dateMade:...,
dateUpdated:...,
displayName:"Joe Spagetio",
item:{
firstName:"Joe",
lastName:"Spaegttio"
}
}
In Vasat a ModelContext can declare a displayName function that will derive the displayName out of a custom function
scala
override def displayNameValue(id: String, obj: User): Option[String] = Some(obj.firstName + " " + obj.lastName)
When using the @DBAuto macro if your case class has a field name:String, it will automatically be used for displayName :::
Creating a ResolvedRef
scala
val u:ResolvedRef[User] = User("joe","blogs").makeRef
// or if you want to specify the ID
val u:ResolvedRef[User] = User("joe","blogs").existingRef("12345")
u.save()
Ref
The superclass of a ResolvedRef is a Ref[A]
, this object only has 2 fields, the typeTag of the object (class) and the id. A Ref serializes to just the ID (ie a string)
Loading and Saving with Refs
There are some convenience methods when working with Ref objects. For all the convinice methods to work there needs to be an implicit modelRepository and executionContext present in the scope of execution
scala
val u = Ref[User]("12345")
u.load().andThenMap{resolvedRef =>
println("User is " + resolvedRef.item)
}
// or doing it synchronously (note this will block code)
val resolvedRef = u.load().await()
println("User is " + resolvedRef.item)
For Saving, a ResolvedRef
is needed as it actually has the contents that is to be saved.
scala
val u:ResolvedRef[User] = ???
u.save().andThenMap{_ => // return of a save is a Noop, so it can be ignored
println("User saved")
}
// or doing it synchronously
u.save().await()
println("User saved")
Relationships in objects
References to another object also make use of Ref objects
consider the following:
scala
case class User(
firstName:String,
lastName:String,
email:Option[String],
address:Ref[Address] // a reference to another model type
)
Using the ref object you can control when the relationship object is loaded
scala
val u:Ref[User] = ???
val res = u.load().andThenFuture{ur =>
ur.item.address.load().andThenMap{addr =>
(ur.item,addr.item)
}
}
// res == VValidF[(User,Address)]