Closed thedodd closed 5 years ago
Should have a path forward now. Need to do some hacking on this when I have time. Ideally we'll be able to have a model definition like this:
#[derive(Model)] // This will add `Serialize` & `Deserialize` if not present.
struct User {
// Must be Option<T> & will also add needed serde bits for
// `skip_serializing_if="Option::is_none"`.
#[model(id)]
id: Option<ObjectId>,
// For a simple index on a single field, specify direction (asc,dsc) & named arguments.
// All of the other index options will take on their default when left unspecified.
// Index direction must be first argument.
#[model(index: dsc, background=true, unique=true)]
email: String,
// A stupid example, but remove this document after 5 min.
#[model(index: asc, background=true, ttl=300)] // Might allow simple arithmetic here for ease of use.
unverified_since: Option<DateTime<Utc>>,
// Compound indices will have a slightly more complex invocation.
// The first field's direction will be the first argument, as normal.
// But then the other fields of the compound index must be presented inside of braces. Simple.
// Then the remaining named arguments will follow.
#[model(index: asc, {compound1: asc, compound2: dsc}, background=true)]
compound0: u64,
compound1: i64,
compound2: String,
}
Need to reflect a bit more on this when I have time, but this may be a decent starting point to shoot for.
Some thoughts on what the new migration pattern will look like.
#[derive(Model)]
struct User {
...
}
impl Migrate for User {
fn migrations() -> Vec<Box<Migration>> {
// Define migrations here.
}
}
fn main() {
// Just sync indices.
User::sync(db).expect("Expected sync to succeed.");
// Sync indices & execute migrations.
User::sync_and_migrate().expect("Expected sync and migrations to succeed.");
}
There were a few things mentally blocking me on this at first.
Now that I've been able to think about it a bit, I'm thinking that a solid path forward will be to use a custom derive for all of the core components, and then allow users to optionally implement a new
Migrate
trait on their models, which is where the model's migrations will be defined.Deriving
Model
on your structs will give you a default implementation ofsync
, so that you can sync your indices with the database. If you choose to also implMigrate
on your struct, you will get a default implementation ofsync_and_migrate
, which will call the defaultsync
first, and then execute the migrations.