Cagette is a quick and dirty data store for prototyping. It allows to focus on designing your domain model, business rules, screens, user interactions, batch, reports, ... without bothering about how your data will eventually be persisted.
"Cagette saved my hackday" — Mr. Speaker
Configure a new resolver:
resolvers += "Guillaume Bort" at "http://guillaume.bort.fr/repository"
Add the library dependency:
libraryDependencies += "guillaume.bort" %% "cagette" % "0.2"
Let's try with a User
class:
case class User(id: Long, email: String, groups: Seq[String])
We usually name the Cageot
with the same name as the domain class:
object User extends cagette.Cageot[User,Long]
The Cageot
type provides convenient higher order query functions you can use directly:
val allusers: Seq[User] = User.findAll()
val maybeUser: Option[User] = User.findById(88)
val maybeUser: Option[User] = User.findOneBy(_.email == "[email protected]")
val adminUsers: Seq[User] = User.findBy(_.groups.contains("admin"))
While defining your Cageot
you can define the initial data set it will contain:
object User extends cagette.Cageot[User,Long] {
override def initialData = Seq(
User(1, "[email protected]", groups = Seq("admin", "user")),
User(2, "[email protected]", groups = Seq("user")),
User(3, "[email protected]", groups = Nil)
)
}
If you want to store a new instance into your Cageot
, just use the save
operation as:
User.save(
User(88, "[email protected]", groups = Seq("user"))
)
If the store already contains an instance with the same id, this instance will just be udpated:
User.findOneBy(_.email == "[email protected]").map { user =>
User.save(user.copy(groups = (user.groups :+ "admin").distinct ))
}
You can either delete by using the id of the instances you want to remove as:
User.delete(88)
or batch delete using a predicate as:
User.delete(_.groups.contains("archived"))
If you don't want to artificially specify an id
field in your case class, you can still provide your own Identifier
instance when creating your Cageot
:
case class User(email: String, groups: Seq[String])
object User extends Cageot[User,String]()(Identifier(_.email)) // Specify the identifier as `email`
You can directly use this for prototyping with http://www.playframework.org. Just add the resolver and library dependency to your Build.scala
file, and start defining your model. The initialData
set will be applied automatically at startup and each time your code change.
Check the source code and find secret features like pagination and autoincrement for domain class identifiers.
Enjoy!