🐫
【Rust】親子関係にない別ディレクトリにあるmoduleを参照したい
概要
最近ようやくRustを触りはじめて、まず躓いたのがディレクトリ間のmoduleのインポートです。JavaScriptのような雰囲気で相対パスでimportできると思ったら、意外にハマりました。
今回はやりたいことと、どう対応したのかというのを書いてみたいと思います。
やりたいこと
下記のようなディレクトリ構成を想定していて、controller→service→modelの形で、親子関係にないmoduleを参照させたいです。
対応方法
stackoverflowの記事How do you use parent module imports in Rust?で、対応方法紹介されていますが、今回はmain.rs
でmoduleを定義する方法を試してみました。
実装サンプル
本筋とはあまり関係ないですが、actix-webでAPIを実装する前提とします。
まずはmain.rs
で参照するmoduleを定義します。
main.rs
use actix_cors::Cors;
use actix_web::http;
use actix_web::App;
use actix_web::HttpServer;
mod controller {
pub mod search_controller;
}
mod service {
pub mod search_service;
}
mod model {
pub mod api {
pub mod search_condition_response;
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
let cors = Cors::default()
.allowed_origin("http://localhost:19006")
.allowed_methods(vec!["GET", "POST", "PUT", "OPTIONS", "DELETE"])
.allowed_header(http::header::CONTENT_TYPE);
App::new()
.wrap(cors)
// ここでcontrollerを参照してる
.service(controller::search_controller::get_search_condition)
})
.bind("0.0.0.0:8080")?
.run()
.await
}
次にcontrollerの実装です。controllerではserviceのmoduleを参照します。
search_controller.rs
use crate::service::search_service;
use actix_web::{get, HttpResponse, Responder};
#[get("/get_search_condition")]
pub async fn get_search_condition() -> impl Responder {
HttpResponse::Ok()
.content_type("application/json")
// ここでserviceを参照してる
.json(search_service::get_search_condition_response())
}
次にserviceの実装です。serviceではmodelのmoduleを参照します。
search_service.rs
use crate::model::api::search_condition_response::SearchConditionResponse;
use crate::model::api::search_condition_response::SearchConditionResponseKV;
pub fn get_search_condition_response() -> SearchConditionResponse {
// ここでmodelを参照してる
return SearchConditionResponse {
category_type: vec![SearchConditionResponseKV {
key: "category1".to_string(),
value: "カテゴリー1".to_string(),
}],
location: vec![SearchConditionResponseKV {
key: "tokyo".to_string(),
value: "東京".to_string(),
}],
};
}
最後にmodelです。
search_condition_response.rs
use serde::Serialize;
#[derive(Serialize)]
pub struct SearchConditionResponse {
pub store_type: Vec<SearchConditionResponseKV>,
pub location: Vec<SearchConditionResponseKV>,
}
#[derive(Serialize)]
pub struct SearchConditionResponseKV {
pub key: String,
pub value: String,
}
Discussion