Appearance
Ref and ResolvedRef
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 some of the fields like id, and dateMade are quite handy and universally apply to whatever object you might have.
The solution in vasat is the Reference object
Ref
A Ref is a container for the metadata of a data model. It contains things like the model's
- id
- date made
- date updated
- access control paths
- version hash
- displayName
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] = None)
val u:User = Ref("1234", u)
// will display as
{
id:"1234",
dateMade:...,
dateUpdated:...,
displayName:"Joe Spagettio",
item:{
firstName:"Joe",
lastName:"Spagettio"
}
}
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()
UnresolvedRef
An unresolved ref is a pointer for a data model. It contains the Model type and the id of that model
scala
val userRef = Ref[User]("1234")
Unresolved refs are useful in definition a link to an object from another object see Relationships
Loading and Saving with Refs
There are some convenience methods when working with Ref objects. For all the convince 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 (this will block code! not recommended)
val resolvedRef = u.load_!()
println("User is " + resolvedRef.item)
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 (this will block code! not recommended)
u.save_!()
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)]
If is important to note also that the json representation of a ref is just its ID as a string
js
{
firstName:"joe",
lastName:"blogs",
address:"1234-5678-90" // Ref[Address]
}
DisplayName
In the admin interface when selecting a list of items from a pulldown, there needs to be a standard string representation field for every object type. displayName is a field that can be set using code for every object type
eg: Setting the display name
scala
@DBAuto
class UserRepo extends DBContext[User,SlickBaseTable]{
override def displayNameValue(id: String, obj: User): Option[String] = Some(obj.firstName + " " + obj.lastName)
}
Macros
When using the @DBAuto macro if your case class has a field name:String, it will automatically be used for displayName