Skip to content

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)]