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数据库接口

MIT 许可证

47KB
1K SLoC

Klub 模型

Rust 库 Crates,用于共享模型特质、结构和接口。

模型用于描述实体和关系。每个模型都有一个独特的模式,并且是这个 Crates 中的一个模块。

将每个模型作为一个中央库中的模块的优点是

  • 版本控制模型
  • 可以在多个 Rust 仓库之间共享
  • 使用此库中定义的结构和特质生成 GraphQL 模式
  • 前端仓库也可以使用此库生成 TypeScript 类型,如果构建为 wasm 目标
  • 代码重用和降低维护成本

安装

该 Crates 已发布,并公开可用。这不是理想的。在投入生产之前,我们需要最终将其设置为私有。

在此处查看最新版本

开发

  1. 克隆 klub-com/klub-core
  2. 运行 make build
  3. 要将此包与其他 Rust 应用程序链接,请将以下代码添加到您的 Cargo.toml

您现在应该能够进行更改并使用您的 IDE 运行测试。

发布

  1. core/models/Cargo.toml 中手动增加版本号
  2. 转到仓库的根目录并运行 make release-models

查看 Crates 文档

  1. 运行 cargo install https - 在 localhost:3000 上运行 cargo doc
  2. 运行 npm install -g browser-sync - 在您进行更改时实时重新加载文档
  3. 在仓库的根目录中运行 make docs 来启动 Rust 文档服务器
  4. 导航到 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