2 个不稳定版本
0.2.0 | 2024 年 6 月 1 日 |
---|---|
0.1.4 | 2024 年 5 月 30 日 |
#377 在 开发工具
369 每月下载
47KB
681 行
页面猎手
页面猎手 库是一个基于 Rust 的分页工具,提供了一种管理和导航数据页面的方法。它提供了一套资源,封装了所有必要的分页信息,例如当前页、总页数、上一页、下一页以及当前页上的项目。
该库还包括验证方法以确保分页数据的完整性。它旨在灵活且易于集成到任何需要分页功能的标准数据验证的 Rust 项目中。
要从 GitHub 仓库使用特定版本的 page-hunter,请在 Cargo.toml 文件中设置依赖项如下
[dependencies]
page-hunter = { git = "https://github.com/JMTamayo/page-hunter.git", version = "0.2.0", features = ["serde"] }
您可以通过向您的 Cargo.toml
文件添加以下依赖项来依赖它
[dependencies]
page-hunter = { version = "0.2.0", features = ["utoipa", "pg-sqlx"] }
CRATE 特性
serde
: 为Page
和Book
添加基于 serde 的 Serialize 和 Deserialize 支持。此功能对于在 REST API 中实现分页模型作为请求或响应体非常有用。utoipa
: 为Page
和Book
添加基于 utoipa 的 ToSchema 支持。此功能对于生成分页模型的 OpenAPI 架构非常有用。此功能依赖于serde
特性,因此您只需实现utoipa
即可同时获得两者。pg-sqlx
: 为 PostgreSQL 数据库添加与 SQLx 的分页支持。mysql-sqlx
: 为 MySQL 数据库添加与 SQLx 的分页支持。
基本操作
page-hunter 库提供了两种主要模型来管理分页
Page
: 代表一个记录页,包含当前页、总页数、上一页、下一页以及当前页上的项目。Book
: 代表一个页面集,包含一系列Page
实例。
该库还提供了一套函数,将记录分页到 Page
模型,并将记录绑定到 Book
模型。以下示例展示了如何使用 page-hunter 库
分页记录
如果您需要分页记录并获取特定的 Page
页面
use page_hunter::*;
let records: Vec<u32> = vec![1, 2, 3, 4, 5];
let page: usize = 0;
let size: usize = 2;
let pagination_result: PaginationResult<Page<u32>> =
paginate_records(&records, page, size);
要从已知参数创建一个 Page
实例
use page_hunter::*;
let items: Vec<u32> = vec![1, 2];
let page: usize = 0;
let size: usize = 2;
let total_elements: usize = 5;
let page_model_result: PaginationResult<Page<u32>> = Page::new(
&items,
page,
size,
total_elements,
);
在启用 serde
功能的情况下,您可以按照以下方式序列化和反序列化一个 Page
use page_hunter::*;
let items: Vec<u32> = vec![1, 2];
let page: usize = 0;
let size: usize = 2;
let total_elements: usize = 5;
let page_model: PaginationResult<Page<u32>> = Page::new(
&items,
page,
size,
total_elements,
).unwrap_or_else(|error| {
panic!("Error creating page model: {:?}", error);
});
let serialized_page: String = serde_json::to_string(&page_model).unwrap_or_else(|error| {
panic!("Error serializing page model: {:?}", error);
});
let deserialized_page: Page<u32> = serde_json::from_str(&serialized_page).unwrap_or_else(|error| {
panic!("Error deserializing page model: {:?}", error);
});
当您从构造函数或反序列化创建一个新的 Page
实例时,对页面上的字段进行以下验证
- pages 必须等于 total 除以 size 并向上取整。当 size 为 0 时,pages 必须为 1。
- page 必须小于或等于 pages - 1。
- 如果 page 小于 pages - 1,则 items 的长度必须等于 size。
- 如果 page 等于 pages - 1,则 total 必须等于 (pages - 1) * size + items 的长度。
- previous_page 必须等于 page - 1,如果 page 大于 0,否则它必须是
None
。 - next_page 必须等于 page + 1,如果 page 小于 pages - 1,否则它必须是
None
。
如果违反了这些规则中的任何一个,将返回一个 PaginationError
。
绑定记录
如果您需要将记录绑定到 Book
模型
use page_hunter::*;
let records: Vec<u32> = vec![1, 2, 3, 4, 5];
let size: usize = 2;
let book_result: PaginationResult<Book<u32>> =
bind_records(&records, size);
要从已知参数创建一个 Book
实例
use page_hunter::*;
let sheets: Vec<Page<u32>> = vec![
Page::new(&vec![1, 2], 0, 2, 5).unwrap(),
Page::new(&vec![3, 4], 1, 2, 5).unwrap(),
];
let book: Book<u32> = Book::new(&sheets);
在启用 serde
功能的情况下,您可以按照以下方式序列化和反序列化一个 Book
use page_hunter::*;
let sheets: Vec<Page<u32>> = vec![
Page::new(&vec![1, 2], 0, 2, 5).unwrap(),
Page::new(&vec![3, 4], 1, 2, 5).unwrap(),
];
let book: Book<u32> = Book::new(&sheets);
let serialized_book: String = serde_json::to_string(&book).unwrap_or_else(|error| {
panic!("Error serializing book model: {:?}", error);
});
let deserialized_book: Book<u32> = serde_json::from_str(&serialized_book).unwrap_or_else(|error| {
panic!("Error deserializing book model: {:?}", error);
});
生成 OpenAPI 架构
在启用 utoipa
功能的情况下,您可以按照以下方式为 Page
和 Book
模型生成 OpenAPI 架构
use page_hunter::*;
use utoipa::ToSchema;
use serde::{Deserialize, Serialize};
#[derive(Clone, ToSchema)]
pub struct Person {
id: u16,
name: String,
last_name: String,
still_alive: bool,
}
pub type PeoplePage = Page<Person>;
pub type PeopleBook = Book<Person>;
#[derive(OpenApi)]
#[openapi(
components(schemas(PeoplePage, PeopleBook))
)]
pub struct ApiDoc;
请查看 示例 文件夹,其中包含一些 Web 框架中 REST API 实现的实用示例。
使用 SQLx 从 PostgreSQL 数据库分页记录
从 PostgreSQL 数据库分页记录
use page_hunter::*;
use sqlx::postgres::{PgPool, Postgres};
use sqlx::{FromRow, QueryBuilder};
use uuid::Uuid;
#[tokio::main]
async fn main() {
#[derive(Clone, Debug, FromRow)]
pub struct Country {
id: Uuid,
name: String,
}
let pool: PgPool = PgPool::connect(
"postgres://username:password@localhost/db"
).await.unwrap_or_else(|error| {
panic!("Error connecting to database: {:?}", error);
});
let query: QueryBuilder<Postgres> = QueryBuilder::new(
"SELECT * FROM db.geo.countries"
);
let page: Page<Country> =
query.paginate(&pool, 0, 10).await.unwrap_or_else(|error| {
panic!("Error paginating records: {:?}", error);
});
}
从 MySQL 数据库分页记录
use page_hunter::*;
use sqlx::mysql::{MySqlPool, MySql};
use sqlx::{FromRow, QueryBuilder};
use uuid::Uuid;
#[tokio::main]
async fn main() {
#[derive(Clone, Debug, FromRow)]
pub struct Country {
id: Uuid,
name: String,
}
let pool: MySqlPool = MySqlPool::connect(
"mysql://username:password@localhost/db"
).await.unwrap_or_else(|error| {
panic!("Error connecting to database: {:?}", error);
});
let query: QueryBuilder<MySql> = QueryBuilder::new(
"SELECT * FROM countries"
);
let page: Page<Country> =
query.paginate(&pool, 0, 10).await.unwrap_or_else(|error| {
panic!("Error paginating records: {:?}", error);
});
}
开发
要测试 page-hunter
,请遵循以下建议
设置环境变量
在工作空间文件夹中创建 local.env
文件以存储所需的环境变量
DB_HOST=localhost
DB_USER=test
DB_PASSWORD=docker
DB_NAME=test
PG_DB_PORT=5432
MYSQL_DB_PORT=3306
设置数据库
使用以下命令以 Docker 容器运行数据库
Postgres SQL
make pg-db-docker
MySQL
make mysql-db-docker
运行数据库迁移
- 安装 sqlx-cli
make install-sqlx-cli
Postgres SQL
- 运行迁移
make run-postgres-migrations
- 撤销迁移
make revert-postgres-migrations
MySQL
- 运行迁移
make run-mysql-migrations
- 撤销迁移
make revert-mysql-migrations
测试
make test
使用 tarpaulin 进行测试
- 安装 cargo-tarpaulin
make install-tarpaulin
- 运行测试
make test-tarpaulin
使用 llvm-cov 进行测试
- 安装 llvm-cov
make install-llvm-cov
- 运行测试
make test-llvm-cov
贡献
Page Hunter 项目是开源的,因此任何感兴趣的软件开发者都可以为其改进做出贡献。要做出贡献,请查看以下建议
- 错误报告:如果您发现了一个错误,请创建一个问题,详细说明问题、重现步骤和预期行为。
- 功能请求:如果您有一个新功能或对现有功能进行改进的想法,请创建一个问题来描述您的想法。
- 拉取请求:如果您修复了一个错误或实现了一个新的功能,我们非常愿意看到您的工作!请提交一个拉取请求。请确保您的代码遵循现有的风格并且所有测试都通过。
依赖项
~0–15MB
~145K SLoC