Rust library crate for sharing model traits, structs and interfaces.
Models are used to describe entities and relationships. Each model has a unique schema and is a mod in this crate.
The advantages of making each model a mod in a centralized lib are: - Version control models - Can be shared across numerous rust repos - GraphQL schemas are generated using the structs and traits defined in this lib - Front-end repos can also use this lib to generate typescript types if built for wasm targets - Code re-usability and less maintainance
The crate has been published and it publicly available. This not ideal. We need to make the crate private eventually before going to production.
make build
rust
klub_models = { path = "../../core/models", version = "0.0.3" }
to your Cargo.toml
You should now be able to make changes and use your IDE to run tests.
make release-models
cargo install https
- to run cargo doc
on localhost:3000
npm install -g browser-sync
- to live reload your docs as you make changesmake docs
in the root directory of the repo to start the rust docs serverlocalhost:3000/klub_models
to view docsEasily construct a model
rust
let problem = Problem::new(id, name);
Since Problem
implements the Topic
trait. You can use .into()
to up-cast Problem
to Topic
.
rust
let problem = Problem::new(id, name);
let topic = Some(problem.clone().into()); // topic is problem's super class
Every model mode with sub classes declares an enum deriving strum crate macros.
Strum makes it easy to cast strings to enums and vice versa.
This make is easy to match strings against emums.
rust
let model_name_as_enum = TopicType::from_str(&model_name).unwrap();
match model_name_as_enum {
TopicType::Problem => {
let problem = Problem::new(id_str, name_str, &["2000"], &["8000"]);
return Some(problem.clone().into());
}
TopicType::Discussion => {
let discussion = Discussion::new(id_str, name_str, &["2000"], &["8000"]);
return Some(discussion.clone().into());
}
}
In this example we are getting a topic from Neo4J graph database.
We then serialize the query response neo4rs::Node
to a GraphQL TopicValue
interface manually.
We then cast the Neo4J node's modelname to a TopicType enum.
We then match against the TopicTypes and construct either a Problem or a
Discussion. Lastly we up cast the Problem/Discussion to being a TopicValue
since that is what
the GraphQL field is expecting as the return type.
```rust
use klubmodels::topic::topic::{TopicType, TopicValue, TOPICMODELALIAS, TOPICMODELNAME};
...
// Example GraphQL topic field resolver
async fn topic(
#[graphql(context)] ctx: &GraphContext,
#[graphql(description = "id of topic")] id: String,
) -> Option
// Query neo4j for a topic by id let topicnode = &ctx.findonebyid(modelparams, idstr).await.unwrap();
// Convert Neo4J fields to GraphQL fields let name: String = topicnode.get("name").unwrap(); let namestr = &name[..]; let modelname: String = topicnode.get("modelname").unwrap(); let modelnameasenum = TopicType::fromstr(&modelname).unwrap();
// Cast generic topic to either a Problem or Discussion match modelnameasenum { TopicType::Problem => { let problem = Problem::new(idstr, name_str, &["2000"], &["8000"]);
// Cast back to TopicValue
return Some(problem.clone().into());
} TopicType::Discussion => { let discussion = Discussion::new(idstr, namestr, &["2000"], &["8000"]);
// Cast back to TopicValue
return Some(discussion.clone().into());
} } }