4 个版本
0.0.4 | 2021 年 11 月 1 日 |
---|---|
0.0.3 | 2021 年 10 月 25 日 |
0.0.2 | 2021 年 10 月 25 日 |
0.0.1 | 2021 年 10 月 23 日 |
1736 在 数据库接口 中
47KB
1K SLoC
Klub 模型
Rust 库 Crates,用于共享模型特质、结构和接口。
模型用于描述实体和关系。每个模型都有一个独特的模式,并且是这个 Crates 中的一个模块。
将每个模型作为一个中央库中的模块的优点是
- 版本控制模型
- 可以在多个 Rust 仓库之间共享
- 使用此库中定义的结构和特质生成 GraphQL 模式
- 前端仓库也可以使用此库生成 TypeScript 类型,如果构建为 wasm 目标
- 代码重用和降低维护成本
安装
该 Crates 已发布,并公开可用。这不是理想的。在投入生产之前,我们需要最终将其设置为私有。
开发
- 克隆 klub-com/klub-core
- 运行
make build
- 要将此包与其他 Rust 应用程序链接,请将以下代码添加到您的
Cargo.toml
您现在应该能够进行更改并使用您的 IDE 运行测试。
发布
- 在 core/models/Cargo.toml 中手动增加版本号
- 转到仓库的根目录并运行
make release-models
查看 Crates 文档
- 运行
cargo install https
- 在localhost:3000
上运行cargo doc
- 运行
npm install -g browser-sync
- 在您进行更改时实时重新加载文档 - 在仓库的根目录中运行
make docs
来启动 Rust 文档服务器 - 导航到
localhost:3000/klub_models
查看文档
用法
轻松构建模型
let problem = Problem::new(id, name);
将模型上转换为它们的父类。
由于 Problem
实现了 Topic
特性。你可以使用 .into()
将 Problem
上转换为 Topic
。
let problem = Problem::new(id, name);
let topic = Some(problem.clone().into()); // topic is problem's super class
对它们进行匹配。
每个具有子类的模型模式都声明了一个枚举,并使用 Strum crate 宏。Strum 使得将字符串转换为枚举以及反之变得容易。这使得匹配字符串和枚举变得简单。
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());
}
}
现在让我们把它们组合起来。
在这个例子中,我们从 Neo4J 图数据库中获取一个主题。然后我们手动将查询响应的 neo4rs::Node
序列化为 GraphQL TopicValue
接口。然后我们将 Neo4J 节点的模型名转换为 TopicType 枚举。然后我们对 TopicTypes 进行匹配,构建一个 Problem 或 Discussion。最后,我们将 Problem/Discussion 上转换为 TopicValue
,因为 GraphQL 字段期望返回该类型。
use klub_models::topic::topic::{TopicType, TopicValue, TOPIC_MODEL_ALIAS, TOPIC_MODEL_NAME};
...
// Example GraphQL topic field resolver
async fn topic(
#[graphql(context)] ctx: &GraphContext,
#[graphql(description = "id of topic")] id: String,
) -> Option<TopicValue> {
let model_params = ModelParams {
model_name: TOPIC_MODEL_NAME,
model_alias: TOPIC_MODEL_ALIAS,
};
let id_str = &id[..];
// Query neo4j for a topic by id
let topic_node = &ctx.find_one_by_id(model_params, id_str).await.unwrap();
// Convert Neo4J fields to GraphQL fields
let name: String = topic_node.get("name").unwrap();
let name_str = &name[..];
let model_name: String = topic_node.get("model_name").unwrap();
let model_name_as_enum = TopicType::from_str(&model_name).unwrap();
// Cast generic topic to either a Problem or Discussion
match model_name_as_enum {
TopicType::Problem => {
let problem = Problem::new(id_str, name_str, &["2000"], &["8000"]);
// Cast back to TopicValue
return Some(problem.clone().into());
}
TopicType::Discussion => {
let discussion = Discussion::new(id_str, name_str, &["2000"], &["8000"]);
// Cast back to TopicValue
return Some(discussion.clone().into());
}
}
}
依赖关系
~23–55MB
~1M SLoC